Bagaimana cara mencetak uint64_t? Gagal dengan: "jejak palsu '%' dalam format"

133

Saya menulis kode uji printf uint64_t yang sangat sederhana:

#include <inttypes.h>
#include <stdio.h>

int main()
{
  uint64_t ui64 = 90;
  printf("test uint64_t : %" PRIu64 "\n", ui64);
  return 0;
}

Saya menggunakan ubuntu 11.10 (64 bit) dan gcc versi 4.6.1 untuk mengkompilasinya, tetapi gagal:

main.cpp: In function int main()’:
main.cpp:9:30: error: expected ‘)’ before PRIu64
main.cpp:9:47: warning: spurious trailing ‘%’ in format [-Wformat]
Dan
sumber
1
Tampaknya Anda mengkompilasi kode C sebagai C ++, itu adalah kesalahan Anda. Jika Anda mengganti nama file Anda main.cdan mengompilasinya dengan gcc, semua akan berfungsi dengan baik.
Jens Gustedt
Sama tanpa kesalahan: stackoverflow.com/questions/9225567/…
Ciro Santilli 郝海东 冠状 病 六四 六四 事件 法轮功
Baik dengan gcc atau dentang, itu ide yang baik untuk menentukan -std=c11atau versi standar yang Anda gunakan. Itu menangkap kesalahan ini dan lainnya. Saya juga merekomendasikan -Wall -Wextra -Wpedantic -Wconversionsetidaknya.
Davislor

Jawaban:

164

Standar ISO C99 menetapkan bahwa makro ini hanya boleh didefinisikan jika diminta secara eksplisit.

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

... now PRIu64 will work
Akan
sumber
@Dan, jangan lupa menandai jawaban sebagai diterima (klik gambar tanda centang di sebelah kiri) jika itu menyelesaikan masalah Anda.
zneak
9
Hm, cukup sertakan header saja. The __STDC_FORMAT_MACROSmakro hanya diperlukan untuk dimasukkan dalam C ++.
Jens Gustedt
15
@Jens: Memang; __STDC_FORMAT_MACROShanya muncul di catatan kaki di C99, menunjukkan bahwa C ++ hanya mendefinisikan makro ini di hadapan permintaan. Namun komite C ++ memilih untuk mengabaikan saran: misalnya dalam konsep n3242, 27.9.2 / 3: Catatan: Makro yang didefinisikan oleh <cinttypes> disediakan tanpa syarat. Secara khusus, simbol __STDC_FORMAT_MACROS, yang disebutkan dalam catatan kaki 182 dari standar C, tidak memainkan peran dalam C ++. Jadi ketika kompiler mengejar, kita tidak perlu __STDC_FORMAT_MACROSdalam C atau C ++.
John Marshall
3
@John Marshall g ++ 4.7.3 tampaknya membutuhkan makro, bahkan ketika <inttypes.h> disertakan.
crockeea
4
@Eric: Rupanya g ++ 4.7.3 belum menyusul! Bahkan, mungkin Anda menggunakannya dengan versi glibc yang ada sebelum perbaikan bug ini . Seperti dibahas dalam laporan glibc itu, libstdc ++ ++ g g Anda memiliki kode untuk mengatasi masalah ini. Jika Anda mengkompilasi dengan -std=c++0xdan mungkin #include <cinttypes> daripada <inttypes.h>, saya percaya itu akan memberikan format makro tanpa Anda berikan __STDC_FORMAT_MACROS.
John Marshall
4

Ketika mengkompilasi memcached di bawah Centos 5.xi mendapat masalah yang sama.

Solusinya adalah dengan memperbarui gcc dan g ++ ke versi 4.4 setidaknya.

Pastikan CC / CXX Anda disetel (diekspor) ke binari kanan sebelum dikompilasi.

Anders Eliasson
sumber
1

Karena Anda memasukkan tag C ++, Anda bisa menggunakan pustaka {fmt} dan menghindari masalah PRIu64makro dan lainnya printf:

#include <fmt/core.h>

int main() {
  uint64_t ui64 = 90;
  fmt::print("test uint64_t : {}\n", ui64);
}

Fasilitas format berdasarkan pustaka ini diusulkan untuk standardisasi dalam C ++ 20: P0645 .

Penafian : Saya penulis {fmt}.

riwayat hidup
sumber
Keren! Apakah itu datang juga sesuatu yang mirip sscanf?
ceztko
Sangat mungkin. Kami sedang menyelidiki kemungkinan penggantian scanf.
vitaut
Bagus! Saya juga bertanya-tanya apakah ada kemajuan menuju versi bebas lokal dan / atau lokal yang dipilih std::to_string(). Halaman cppreference masih terhubung hanya ke std::to_chars(), yang sebenarnya tidak dibutuhkan orang. Saya ingin tahu apakah fmtdan / atau c ++ 20 menghadapinya atau belum.
ceztko
std::to_stringmungkin akan tetap apa adanya, tetapi std::formatmemungkinkan Anda untuk mengontrol apakah akan menggunakan lokal atau tidak (dan secara default tidak menggunakan lokal).
vitaut