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]

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


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

@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.


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}.


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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.