ตัวระบุรูปแบบ size_t อิสระของแพลตฟอร์มใน c?


86

ฉันต้องการพิมพ์ตัวแปรประเภทsize_tC แต่ปรากฏว่าsize_tมีการใช้นามแฝงเป็นตัวแปรประเภทต่างๆในสถาปัตยกรรมที่แตกต่างกัน ตัวอย่างเช่นในเครื่องเดียว (64 บิต) รหัสต่อไปนี้จะไม่แสดงคำเตือนใด ๆ :

แต่ในเครื่องอื่นของฉัน (32 บิต) รหัสด้านบนจะสร้างข้อความเตือนต่อไปนี้:

คำเตือน: รูปแบบ '% ld' คาดว่าจะเป็นประเภท 'long int *' แต่อาร์กิวเมนต์ 3 มีประเภท 'size_t *'

ฉันสงสัยว่านี่เป็นเพราะความแตกต่างของขนาดตัวชี้ดังนั้นบนเครื่อง 64 บิตของฉันsize_tจึงมีนามแฝงเป็น a long int( "%ld") ในขณะที่เครื่อง 32 บิตของฉันsize_tมีนามแฝงเป็นประเภทอื่น

มีตัวระบุรูปแบบสำหรับsize_tหรือไม่


1
ข้อความเตือนของคุณไม่ตรงกับรหัส คำเตือนกล่าวถึงตัวชี้รหัสของคุณไม่มีเลย คุณได้ลบบางส่วนออกไป&หรือไม่?
Jens

พอยน์เตอร์? ไม่ฉันไม่ได้รับคำเตือนใด ๆ เกี่ยวกับตัวชี้อันที่จริงขึ้นอยู่กับเครื่องที่ฉันเรียกใช้รหัสนั้นในบางครั้งฉันก็ไม่ได้รับคำเตือนเลย ลองใช้รหัสทดสอบต่อไปนี้: #include <stdio.h> int main () {size_t size = 1; printf ("ขนาดคือ% ld", ขนาด); กลับ 0; }
Ethan Heilman


1
@EthanHeilman เขาหมายถึงความจริงที่ว่าคำเตือนของคุณบอกว่าwarning: format '%ld' expects type 'long int *', but argument 3 has type 'size_t *'เมื่อมันอาจจะควรwarning: format '%ld' expects type 'long int', but argument 3 has type 'size_t'จะพูดว่า คุณอาจใช้scanf()แทนเมื่อได้รับคำเตือนเหล่านี้หรือไม่?
RastaJedi

คำตอบ:


123

ใช่: ใช้zตัวปรับความยาว:

ตัวปรับความยาวอื่น ๆ ที่พร้อมใช้งาน ได้แก่hh(สำหรับchar) h(สำหรับshort) l(สำหรับlong) ll(สำหรับlong long) j(สำหรับintmax_t) t(สำหรับptrdiff_t) และL(สำหรับlong double) ดู§7.19.6.1 (7) ของมาตรฐาน C99


อะไรคือความแตกต่างระหว่าง zd และ zu? ฉันได้ zd นั้นเป็นทศนิยม แต่มีการเซ็นชื่อแล้วถ้าเป็นเช่นนั้นการเซ็นชื่อ zd จะส่งผลอย่างไร
Ethan Heilman

1
มันคือความแตกต่างระหว่าง a size_tและ an ssize_t; หลังนี้ไม่ค่อยมีใครใช้
Adam Rosenfield

26
ถูกต้องดังนั้นในกรณีนี้คุณควรใช้%zuเนื่องจากอาร์กิวเมนต์ไม่ได้ลงนาม
คาเฟ่

ตัวเลือกอื่น ๆ ที่มีอยู่อธิบายไว้ในหน้าคู่มือ printf: linux.die.net/man/3/printf
INS

9
@detly: ไม่zตัวปรับความยาวไม่ได้เป็นส่วนหนึ่งของ C89 / C90 หากคุณกำลังตั้งเป้าหมายสำหรับรหัสที่สอดคล้องกับ C89 สิ่งที่ดีที่สุดที่คุณสามารถทำได้คือส่งunsigned longและใช้lตัวปรับความยาวแทนเช่นprintf("the size is %lu\n", (unsigned long)size);; รองรับทั้ง C89 และระบบที่มีsize_tขนาดใหญ่กว่าlongนั้นยากกว่าและจำเป็นต้องใช้มาโครตัวประมวลผลล่วงหน้าหลายตัว
Adam Rosenfield

45

ใช่มี. เป็น%zu(ตามที่ระบุใน ANSI C99)

โปรดทราบว่าไม่ได้size_tลงนามจึง%ldผิดสองครั้ง: ตัวปรับความยาวผิดและตัวระบุการแปลงรูปแบบที่ไม่ถูกต้อง ในกรณีที่คุณสงสัย%zdมีไว้สำหรับssize_t(ซึ่งลงชื่อ)


1

MSDNกล่าวว่า Visual Studio รองรับคำนำหน้า "I" สำหรับโค้ดพกพาบนแพลตฟอร์ม 32 และ 64 บิต


6
เป็น MS เฉพาะซึ่งไม่เป็นไปตามมาตรฐานดังนั้นจึงไม่เป็นอิสระจากแพลตฟอร์ม
phuclv

@phuclv แน่นอน. และถ้าเป็นไปตามคำตอบที่แนะนำ - 'แบบพกพา' มันแย่กว่าที่ฉันเคยรู้เกี่ยวกับ MS เสียอีก ไม่ใช่ว่าจะทำให้ฉันประหลาดใจ ... ฉันไม่ใช่คนที่จะโหวตลงคะแนนเพราะมีคนพยายามพยายามตอบอะไรบางอย่าง แต่คำตอบนี้ก็ยังผิดอยู่ดี อ่าฉันคิดว่าฉันเข้าใจไอเดียใน 'แบบพกพา' ต้องบอกว่าใช้ได้ทั้ง 32 บิตและ 64 บิต แต่แน่นอนมันจะ
Pryftan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.