Saya memiliki beberapa kode C ++ yang mencetak size_t
:
size_t a;
printf("%lu", a);
Saya ingin ini mengompilasi tanpa peringatan pada arsitektur 32 dan 64-bit.
Jika ini C99, saya bisa menggunakan printf("%z", a);
. Tetapi AFAICT %z
tidak ada dalam dialek C ++ standar. Jadi, saya harus melakukannya
printf("%lu", (unsigned long) a);
yang sangat jelek.
Jika tidak ada fasilitas untuk mencetak yang ada size_t
di dalam bahasa, saya bertanya-tanya apakah mungkin untuk menulis pembungkus printf atau semacamnya yang akan memasukkan cetakan yang sesuai size_t
untuk menghilangkan peringatan compiler palsu sambil tetap mempertahankan yang baik.
Ada ide?
Edit Untuk memperjelas mengapa saya menggunakan printf: Saya memiliki basis kode yang relatif besar yang saya bersihkan. Ini menggunakan pembungkus printf untuk melakukan hal-hal seperti "menulis peringatan, memasukkannya ke file, dan mungkin keluar dari kode dengan kesalahan". Saya mungkin dapat mengumpulkan cukup C ++ - foo untuk melakukan ini dengan pembungkus cout, tetapi saya lebih suka tidak mengubah setiap panggilan warn () dalam program hanya untuk menghilangkan beberapa peringatan kompiler.
"%l"
? Bukankah itu selalu dalam ukuran yang tepat? Atau apakah portabilitas itu penting?Jawaban:
Kebanyakan kompiler memiliki specifier
size_t
danptrdiff_t
argumennya sendiri, Visual C ++ misalnya menggunakan% Iu dan% Id masing-masing, saya pikir gcc akan memungkinkan Anda untuk menggunakan% zu dan% zd.Anda bisa membuat makro:
Pemakaian:
sumber
%z
didukung atau tidak tergantung pada runtime, tidak compiler. Menggunakan__GNUC__
karena itu sedikit masalah, jika Anda mencampur GCC / mingw dengan msvcrt (dan tanpa menggunakan printf augmented mingw ini).Penentu
printf
format%zu
akan bekerja dengan baik pada sistem C ++; tidak perlu membuatnya lebih rumit.sumber
C ++ 11
C ++ 11 mengimpor C99 sehingga
std::printf
harus mendukung penentu%zu
format C99 .C ++ 98
Pada sebagian besar platform,
size_t
danuintptr_t
setara, dalam hal ini Anda dapat menggunakanPRIuPTR
makro yang ditentukan di<cinttypes>
:Jika Anda benar - benar ingin aman, transmisikan ke
uintmax_t
dan gunakanPRIuMAX
:sumber
Pada Windows dan implementasi Visual Studio printf
bekerja untuk saya. lihat msdn
sumber
VS 2008
juga. Juga perlu diingat bahwa seseorang dapat menggunakan%Id
,%Ix
dan%IX
juga.Karena Anda menggunakan C ++, mengapa tidak menggunakan IOStreams? Itu harus dikompilasi tanpa peringatan dan melakukan hal yang benar-benar sadar jenis, selama Anda tidak menggunakan implementasi C ++ yang tidak mendefinisikan
operator <<
untuksize_t
.Ketika keluaran sebenarnya harus diselesaikan
printf()
, Anda masih dapat menggabungkannya dengan IOStreams untuk mendapatkan perilaku tipe-aman:Ini tidak super efisien, tetapi kasus Anda di atas berkaitan dengan file I / O, jadi itu hambatan Anda, bukan kode pemformatan string ini.
sumber
std::stringstream
alih-alih aliran IO.printf("x=%i, y=%i;\n", x, y);
vscout << "x=" << x << ", y=" << y << ";" << std::endl;
.inilah solusi yang mungkin, tetapi tidak cukup bagus ..
sumber
The perpustakaan fmt menyediakan portabel (dan aman) pelaksanaan cepat
printf
termasukz
pengubah untuksize_t
:Selain itu, ia mendukung sintaks string format seperti Python dan menangkap informasi tipe sehingga Anda tidak perlu menyediakannya secara manual:
Ini telah diuji dengan kompiler utama dan memberikan output yang konsisten di seluruh platform.
Penafian : Saya adalah pembuat perpustakaan ini.
sumber
Jenis efektif yang mendasari size_t bergantung pada implementasi . C Standar mendefinisikannya sebagai tipe yang dikembalikan oleh ukuran operator; Selain unsigned dan semacam tipe integral, size_t bisa menjadi apa saja yang ukurannya bisa menampung nilai terbesar yang diharapkan akan dikembalikan oleh sizeof ().
Akibatnya format string yang akan digunakan untuk size_t dapat bervariasi tergantung pada server. Itu harus selalu memiliki "u", tapi mungkin l atau d atau mungkin sesuatu yang lain ...
Triknya bisa dengan melemparkannya ke tipe integral terbesar di mesin, memastikan tidak ada kerugian dalam konversi, dan kemudian menggunakan string format yang terkait dengan tipe yang diketahui ini.
sumber
size_t
ke tipe integral terbesar pada mesin dan menggunakan format string yang terkait dengan tipe ini. Pertanyaan saya adalah: Apakah ada cara saya dapat melakukan ini sambil mempertahankan kode yang bersih (peringatan hanya untuk kesalahan string format printf yang sah, tidak ada pemeran yang jelek, dll.)? Saya bisa menulis pembungkus yang mengubah format string, tapi kemudian GCC tidak akan bisa memberi saya peringatan ketika saya secara sah mengacaukan format string saya.Nanti di kode:
my::printf("test ", 1, '\t', 2.0);
sumber