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.