penentu format printf untuk uint32_t dan size_t

101

Saya memiliki yang berikut ini

size_t   i = 0;
uint32_t k = 0;

printf("i [ %lu ] k [ %u ]\n", i, k);

Saya mendapatkan peringatan berikut saat menyusun:

format ‘%lu expects type long unsigned int’, but argument has type uint32_t

Ketika saya menjalankan ini menggunakan belat, saya mendapatkan yang berikut:

Format argument 1 to printf (%u) expects unsigned int gets size_t: k

Terima kasih banyak atas sarannya,

ant2009
sumber
2
C89 tidak mendukung uint32_tdari <stdint.h>atau <inttypes.h>; jika Anda ingin menggunakan tipe tersebut, Anda harus meningkatkan ke C89. Sebagai ekstensi, GCC mungkin mengizinkan Anda untuk menggunakannya, tetapi C89 tidak memiliki dukungan semacam itu.
Jonathan Leffler
10
Dan pengubah format C99 resmi untuk size_tadalah 'z', seperti pada "%zu".
Jonathan Leffler
1
stackoverflow.com/questions/1401526/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Saya percaya jawaban @ kenny adalah yang terbaik untuk uint32_t, tetapi kurang size_t. Jawaban @ u0b34a0f6ae mencakup keduanya.
jww
Penyebutan kedua C89 dalam komentar pertama oleh Jonathan Leffler seharusnya C99
bph

Jawaban:

28

Kedengarannya seperti Anda mengharapkan size_tuntuk menjadi sama dengan unsigned long(mungkin 64 bit) padahal sebenarnya unsigned int(32 bit). Coba gunakan %zudalam kedua kasus.

Saya tidak sepenuhnya yakin.

Cogwheel
sumber
1
Tidak ada peringatan saat kompilasi. Namun, menjalankan bidai saya mendapatkan yang berikut: 1) printf (% u) mengharapkan unsigned int mendapat uint32_t: i 2) printf (% u) mengharapkan unsigned int mendapat size_t: k
ant2009
Kedengarannya seperti belat hanya bertele-tele saja. Ini mungkin menyebutkan nama jenis dalam kode sumber dan tidak menyadari bahwa mereka setara. Saya ingin tahu apa yang akan dilakukannya dengan jawaban @ KennyTM ... Ini tentunya harus lebih portabel.
Cogwheel
3
belat sebenarnya melakukan hal yang benar. Hanya karena int32_tkebetulan ada intdi kompiler / platform Anda tidak berarti itu mungkin tidak ada longdi kompiler lain. Sama untuk size_t. Ini sebenarnya akan keluar dari jalannya dan melakukan lebih banyak pekerjaan untuk mendeteksi bug portabilitas ini karena pemeriksaan yang mudah dan alami adalah hanya menghormati typedef seperti yang dilakukan kompiler.
R .. GitHub STOP HELPING ICE
4
-1, maaf itu tidak portabel. Yang diperlukan hanyalah penentu format dan jenisnya setuju, dan Anda selalu dapat melakukan transmisi untuk membuatnya benar. panjang setidaknya 32 bit, jadi %lubersama-sama (unsigned long)kselalu benar. size_tlebih rumit, itulah sebabnya %zuditambahkan di C99. Jika Anda tidak dapat menggunakan itu, maka perlakukan seperti itu k( longadalah tipe terbesar di C89, size_tsangat tidak mungkin lebih besar).
u0b34a0f6ae
139

Mencoba

#include <inttypes.h>
...

printf("i [ %zu ] k [ %"PRIu32" ]\n", i, k);

The zmewakili bilangan bulat panjang yang sama seperti size_t, dan PRIu32makro, didefinisikan dalam header C99inttypes.h , merupakan 32-bit unsigned integer.

kennytm
sumber
3
@robUK: Heh. Saya sarankan Anda melaporkan bug untuk belat.
kennytm
8
Ini adalah jawaban yang benar. Meskipun rekomendasi pribadi saya adalah melakukan cast, mis printf( "%lu", (unsigned long )i ). Jika tidak, seseorang akan berakhir dengan tumpukan peringatan di seluruh kode karena perubahan jenis.
Dummy00001
1
Ini jawaban yang benar. Saya setuju dengan KennyTM tentang melaporkan bug untuk belat. Omong-omong, "% zu" adalah format yang tepat untuk size_t. Anda tidak memerlukan makro PRI * apa pun untuk mencetak size_t.
R .. GitHub STOP HELPING ICE
1
Jika saya ingat dengan benar% zu adalah C99, dan dalam pertanyaan dia menulis 'C89'.
alcor
8
@alcor ya dia meletakkan C89 (rupanya bendera kompilator gcc yang dia gunakan) tetapi dia menggunakan uint32_tjadi sebenarnya itu adalah kode C99, dan harus dikompilasi seperti itu.
Colin D Bennett
28

Yang diperlukan hanyalah penentu format dan jenisnya setuju, dan Anda selalu dapat melakukan transmisi untuk membuatnya benar. longsetidaknya 32 bit, jadi %lubersama-sama dengan (unsigned long)kselalu benar:

uint32_t k;
printf("%lu\n", (unsigned long)k);

size_tlebih rumit, itulah sebabnya %zuditambahkan di C99. Jika Anda tidak dapat menggunakan itu, maka perlakukan seperti itu k( longadalah tipe terbesar di C89, size_tsangat tidak mungkin lebih besar).

size_t sz;
printf("%zu\n", sz);  /* C99 version */
printf("%lu\n", (unsigned long)sz);  /* common C89 version */

Jika Anda tidak mendapatkan penentu format yang benar untuk tipe yang Anda lewati, maka printfakan melakukan hal yang sama dengan membaca terlalu banyak atau terlalu sedikit memori yang keluar dari larik. Selama Anda menggunakan cast eksplisit untuk mencocokkan tipe, ini portabel.

u0b34a0f6ae
sumber
17

Jika Anda tidak ingin menggunakan makro PRI *, pendekatan lain untuk mencetak jenis bilangan bulat APA PUN adalah dengan mentransmisikan ke intmax_tatau uintmax_tdan menggunakan "%jd"atau %ju, masing-masing. Ini sangat berguna untuk jenis POSIX (atau OS lain) yang tidak memiliki makro PRI * yang ditentukan, misalnya off_t.

R .. GitHub BERHENTI ICE BANTUAN
sumber