ตัวระบุรูปแบบ printf สำหรับ uint32_t และ size_t


101

ฉันมีดังต่อไปนี้

size_t   i = 0;
uint32_t k = 0;

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

ฉันได้รับคำเตือนต่อไปนี้เมื่อคอมไพล์:

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

เมื่อฉันวิ่งโดยใช้เฝือกฉันได้รับสิ่งต่อไปนี้:

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

ขอบคุณมากสำหรับคำแนะนำใด ๆ


2
C89 ไม่สนับสนุนuint32_tจาก<stdint.h>หรือ<inttypes.h>; หากคุณต้องการใช้ประเภทเหล่านั้นคุณควรอัปเกรดเป็น C89 ในฐานะที่เป็นส่วนเสริมมีแนวโน้มว่า GCC จะอนุญาตให้คุณใช้งานได้ แต่ C89 ไม่มีการสนับสนุนดังกล่าว
Jonathan Leffler

10
และตัวปรับรูปแบบ C99 อย่างเป็นทางการสำหรับsize_tคือ 'z' เช่นเดียวกับใน"%zu".
Jonathan Leffler


ผมเชื่อว่าคำตอบ @ เคนนีที่ดีที่สุดสำหรับแต่ขาดuint32_t size_tคำตอบของ @ u0b34a0f6ae มีทั้งสองอย่าง
jww

การกล่าวถึง C89 ครั้งที่ 2 ในความคิดเห็นที่ 1 โดย Jonathan Leffler ควรเป็น C99
bph

คำตอบ:


28

ดูเหมือนว่าคุณคาดหวังว่าsize_tจะเหมือนกับunsigned long(อาจเป็น 64 บิต) เมื่อเป็นunsigned int(32 บิต) ลองใช้%zuในทั้งสองกรณี

ฉันไม่แน่ใจทั้งหมด


1
ไม่มีคำเตือนเมื่อรวบรวม อย่างไรก็ตามการใช้เฝือกฉันได้รับสิ่งต่อไปนี้: 1) printf (% u) คาดว่า int ที่ไม่ได้ลงชื่อจะได้รับ uint32_t: i 2) printf (% u) คาดว่า int ที่ไม่ได้ลงชื่อจะได้รับ size_t: k
ant2009

ดูเหมือนว่าการเข้าเฝือกเป็นเพียงการอวดดี อาจเป็นการปิดชื่อประเภทในซอร์สโค้ดและไม่ทราบว่าเทียบเท่ากัน ฉันสงสัยว่ามันจะทำอย่างไรกับคำตอบของ @ Kenny ™ ... มันน่าจะพกพาได้มากกว่านี้
Cogwheel

3
เฝือกทำในสิ่งที่ถูกต้องจริงๆ เพียงเพราะสิ่งที่int32_tเกิดขึ้นintบนคอมไพเลอร์ / แพลตฟอร์มของคุณไม่ได้หมายความว่ามันอาจจะไม่อยู่longบนอื่น เหมือนกันสำหรับsize_t. จริงๆแล้วมันกำลังจะออกไปและทำงานได้มากขึ้นเพื่อตรวจจับข้อผิดพลาดในการพกพานี้เนื่องจากการตรวจสอบที่ง่ายและเป็นธรรมชาติคือการให้เกียรติ typedef เหมือนที่คอมไพเลอร์ทำ
R .. GitHub STOP HELPING ICE

4
-1 ขออภัยมันไม่สามารถพกพาได้ สิ่งที่จำเป็นก็คือตัวระบุรูปแบบและประเภทที่เห็นด้วยและคุณสามารถแคสต์เพื่อทำให้เป็นจริงได้ตลอดเวลา ยาวที่ 32bits อย่างน้อยเพื่อให้%luพร้อมกับการ(unsigned long)kเป็นที่ถูกต้องเสมอ size_tยากกว่าซึ่งเป็นสาเหตุที่%zuเพิ่มเข้ามาใน C99 หากคุณไม่สามารถใช้สิ่งนั้นได้ให้ปฏิบัติเช่นนั้นk( longเป็นประเภทที่ใหญ่ที่สุดใน C89 size_tไม่น่าจะใหญ่กว่านี้มาก)
u0b34a0f6ae

139

ลอง

#include <inttypes.h>
...

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

zหมายถึงจำนวนเต็มของความยาวเช่นเดียวกับsize_tและPRIu32แมโครที่กำหนดไว้ในส่วนหัว C99inttypes.hหมายถึงจำนวนเต็ม 32 บิต


3
@robUK: หึหึ ฉันขอแนะนำให้คุณยื่นข้อบกพร่องสำหรับการเข้าเฝือก
kennytm

8
นี่คือคำตอบที่ใช่ printf( "%lu", (unsigned long )i )แม้ว่าคำแนะนำส่วนตัวของฉันคือการโยนก็เช่น มิฉะนั้นจะจบลงในภายหลังด้วยกองคำเตือนทั่วทั้งรหัสเนื่องจากการเปลี่ยนแปลงประเภท
Dummy00001

1
นี่คือคำตอบที่ถูกต้อง ฉันเห็นด้วยกับ Kenny ™เกี่ยวกับการยื่นข้อบกพร่องสำหรับการเข้าเฝือก อย่างไรก็ตาม "% zu" เป็นรูปแบบที่เหมาะสมสำหรับ size_t คุณไม่จำเป็นต้องมีมาโคร PRI * สำหรับการพิมพ์ size_t
R .. GitHub STOP HELPING ICE

1
ถ้าจำไม่ผิด% zu คือ C99 และในคำถามเขาเขียนว่า 'C89'
alcor

8
@alcor ใช่เขาใส่ C89 (เห็นได้ชัดว่าเป็นแฟล็กคอมไพเลอร์ gcc ที่เขาใช้) แต่เขาใช้uint32_tจริง ๆ แล้วมันคือรหัส C99 และควรคอมไพล์เช่นนี้
Colin D Bennett

28

สิ่งที่จำเป็นก็คือตัวระบุรูปแบบและประเภทที่เห็นด้วยและคุณสามารถแคสต์เพื่อทำให้เป็นจริงได้ตลอดเวลา longเป็นอย่างน้อย 32 บิตเพื่อให้%luพร้อมกับการ(unsigned long)kเป็นเสมอที่ถูกต้อง:

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

size_tยากกว่าซึ่งเป็นสาเหตุที่%zuเพิ่มเข้ามาใน C99 หากคุณไม่สามารถใช้สิ่งนั้นได้ให้ปฏิบัติเช่นนั้นk( longเป็นประเภทที่ใหญ่ที่สุดใน C89 size_tไม่น่าจะใหญ่กว่านี้มาก)

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

หากคุณไม่ได้รับตัวระบุรูปแบบที่ถูกต้องสำหรับประเภทที่คุณกำลังส่งก็printfจะเทียบเท่ากับการอ่านหน่วยความจำมากเกินไปหรือน้อยเกินไปจากอาร์เรย์ ตราบใดที่คุณใช้การร่ายอย่างโจ่งแจ้งเพื่อจับคู่ประเภทมันก็พกพาได้


17

หากคุณไม่ต้องการใช้มาโคร PRI * อีกวิธีหนึ่งในการพิมพ์จำนวนเต็มชนิดใดก็ได้คือการส่งไปยังintmax_tหรือuintmax_tและใช้"%jd"หรือ%juตามลำดับ นี้จะเป็นประโยชน์อย่างยิ่งสำหรับ POSIX (หรือระบบปฏิบัติการอื่น ๆ ) ประเภทที่ไม่ได้มี PRI * off_tแมโครที่กำหนดไว้เช่น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.