ฉันพยายามที่จะพิมพ์ประเภทเช่นและoff_t
size_t
ตัวยึดตำแหน่งที่ถูกต้องสำหรับprintf()
อุปกรณ์พกพาคืออะไร
หรือมีวิธีที่แตกต่างอย่างสิ้นเชิงในการพิมพ์ตัวแปรเหล่านั้น?
ฉันพยายามที่จะพิมพ์ประเภทเช่นและoff_t
size_t
ตัวยึดตำแหน่งที่ถูกต้องสำหรับprintf()
อุปกรณ์พกพาคืออะไร
หรือมีวิธีที่แตกต่างอย่างสิ้นเชิงในการพิมพ์ตัวแปรเหล่านั้น?
คำตอบ:
คุณสามารถใช้z
size_t และt
ptrdiff_t ได้เช่นกัน
printf("%zu %td", size, ptrdiff);
แต่ manpage ของฉันบอกว่าไลบรารี่เก่าบางตัวใช้ตัวละครที่แตกต่างกว่าz
และกีดกันการใช้มัน อย่างไรก็ตามมันเป็นมาตรฐาน (ตามมาตรฐาน C99) สำหรับผู้intmax_t
และint8_t
ของstdint.h
และอื่น ๆ มีแมโครคุณสามารถใช้เช่นคำตอบอื่นกล่าวว่า:
printf("value: %" PRId32, some_int32_t);
printf("value: %" PRIu16, some_uint16_t);
พวกเขามีการระบุไว้ใน manpage inttypes.h
ของ
โดยส่วนตัวแล้วฉันแค่จะโยนค่าunsigned long
หรือlong
ชอบคำตอบอื่นแนะนำ ถ้าคุณใช้ C99 แล้วคุณสามารถ (และควรของหลักสูตร) โยนไปunsigned long long
หรือlong long
และใช้%llu
หรือ%lld
รูปแบบตามลำดับ
%zd
กับ a size_t
คือพฤติกรรมที่ไม่ได้กำหนดเนื่องจากความไม่ลงนามในลายเซ็น (C99 7.19.6.1 # 9) %zu
มันจะต้องเป็น
%zd
ด้วยsize_t
พฤติกรรมที่ไม่ได้กำหนดจากวรรคนั้นหรือจากอื่น ๆ ในความเป็นจริงคำจำกัดความของ%z
ใน # 7 อนุญาตอย่างชัดเจน%d
ด้วยsize_t
และประเภทที่ลงนามที่สอดคล้องกันและ§6.2.5 # 9 อนุญาตการใช้ค่าของประเภทที่ไม่ได้ลงนามอย่างชัดเจนโดยที่คาดว่าจะเป็นประเภทที่ลงนามที่เกี่ยวข้องตราบใดที่ค่านั้นเป็นค่า ประเภทที่เซ็นชื่อ
วิธีพิมพ์off_t
:
printf("%jd\n", (intmax_t)x);
วิธีพิมพ์size_t
:
printf("%zu\n", x);
วิธีพิมพ์ssize_t
:
printf("%zd\n", x);
ดู 7.19.6.1/7 ในมาตรฐาน C99 หรือเอกสาร POSIX ที่สะดวกยิ่งขึ้นของรหัสการจัดรูปแบบ:
http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
หากการใช้งานของคุณไม่สนับสนุนรหัสการจัดรูปแบบเหล่านั้น (เช่นเนื่องจากคุณใช้ C89) แสดงว่าคุณมีปัญหาเล็กน้อยเนื่องจาก AFAIK ไม่มีประเภทจำนวนเต็มใน C89 ที่มีรหัสการจัดรูปแบบและรับประกันว่าจะใหญ่ เป็นประเภทเหล่านี้ ดังนั้นคุณต้องทำอะไรบางอย่างเฉพาะการใช้งาน
ตัวอย่างเช่นถ้าคุณมีคอมไพเลอร์long long
และสนับสนุนห้องสมุดมาตรฐานของคุณคุณมั่นใจสามารถคาดหวังที่จะให้บริการในสถานที่ของ%lld
intmax_t
แต่ถ้าไม่คุณจะต้องถอยกลับlong
ซึ่งจะล้มเหลวในการใช้งานอื่น ๆ เพราะมีขนาดเล็กเกินไป
ssize_t
มีขนาดเท่าsize_t
กันดังนั้นรหัสแบบพกพาอย่างแท้จริงควรแปลงเป็นintmax_t
และพิมพ์ด้วย%jd
เหมือนoff_t
กัน
สำหรับ Microsoft คำตอบนั้นแตกต่างกัน VS2013 นั้นรองรับ C99 เป็นส่วนใหญ่ แต่ "ไม่สนับสนุนส่วนนำหน้า hh, j, z และ t ความยาว t" สำหรับ size_t "นั่นคือ __int32 ที่ไม่ได้ลงชื่อบนแพลตฟอร์ม 32 บิตที่ไม่ได้ลงนาม __int64 บนแพลตฟอร์ม 64 บิต" ให้ใช้คำนำหน้า I (ตัวอักษรตัวใหญ่) พร้อมตัวระบุประเภท o, u, x หรือ X ดูข้อกำหนดขนาด VS2013
สำหรับ off_t มันถูกกำหนดไว้นานใน VC \ include \ sys \ types.h
off_t
เป็นแบบนั้นเสมอlong
จะทำให้เป็นแบบ 32 บิต (แม้แต่ Windows แบบ 64 บิตก็ใช้แบบ 32 บิตสำหรับlong
)
คุณใช้ C รุ่นใด
ใน C90 การปฏิบัติมาตรฐานคือการส่งไปยังเซ็นชื่อหรือไม่ได้ลงนามนานตามความเหมาะสมและพิมพ์ตามนั้น ฉันเห็น% z สำหรับ size_t แล้ว แต่ Harbison และ Steele ไม่ได้พูดถึงมันใน printf () และในกรณีใด ๆ ที่ไม่ช่วยคุณด้วย ptrdiff_t หรืออะไรก็ตาม
ใน C99 ประเภท _t ต่างๆมาพร้อมกับมาโคร printf ของตัวเองดังนั้นบางอย่างที่"Size is " FOO " bytes."
ฉันไม่ทราบรายละเอียด แต่นั่นเป็นส่วนหนึ่งของรูปแบบตัวเลขที่ค่อนข้างใหญ่รวมถึงไฟล์
คุณจะต้องใช้มาโครการจัดรูปแบบจาก inttypes.h
ดูคำถามนี้: สตริงรูปแบบข้ามแพลตฟอร์มสำหรับตัวแปรประเภท size_t?
off_t
ประเภทมีขนาดใหญ่กว่าตัวชี้บนระบบ 32 บิตที่สนับสนุนไฟล์ขนาดใหญ่ (ซึ่งเป็นส่วนใหญ่ระบบ 32 บิตวันนี้บริการ)
มองไปที่man 3 printf
บน Linux OS X และ OpenBSD แสดงการสนับสนุนทั้งหมด%z
สำหรับsize_t
และ%t
สำหรับptrdiff_t
(สำหรับ C99) off_t
แต่ไม่มีการกล่าวถึงผู้ที่ ข้อเสนอแนะในป่ามักจะเสนอการ%u
แปลงสำหรับoff_t
ซึ่งเป็น "ถูกต้องพอ" เท่าที่ฉันสามารถบอกได้ (ทั้งสองunsigned int
และoff_t
แตกต่างกันระหว่าง 64- บิตและ 32- บิตระบบ)
unsigned int
และ off_t
64 ดังนั้นนักแสดงจะทำให้ข้อมูลสูญหาย
ฉันเห็นโพสต์นี้อย่างน้อยสองครั้งเพราะคำตอบที่ยอมรับนั้นยากสำหรับฉันที่จะจำ (ฉันไม่ค่อยได้ใช้z
หรือตั้งj
ค่าสถานะและดูเหมือนว่าพวกเขาจะไม่เป็นอิสระจากแพลตฟอร์ม )
มาตรฐานไม่เคยพูดอย่างชัดเจนความยาวของข้อมูลที่แน่นอนของsize_t
ผมจึงขอแนะนำให้คุณควรตรวจสอบความยาวsize_t
บนแพลตฟอร์มของคุณแล้วเลือกหนึ่งของพวกเขา:
if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64
และฉันขอแนะนำให้ใช้stdint
ประเภทแทนชนิดข้อมูลดิบเพื่อความสอดคล้อง
%zu
สามารถใช้เพื่อพิมพ์size_t
ค่า หนึ่งควรแน่นอนไม่หันไปใช้uint32_t
/ uint64_t
ระบุรูปแบบการพิมพ์size_t
เช่นไม่มีการรับประกันว่าประเภทที่เข้ากันได้
ในฐานะที่ผมจำได้วิธีเดียวที่พกพาที่จะทำมันคือการโยนผลให้ "int ยาวไม่ได้ลงนาม" %lu
และการใช้งาน
printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
long long
ไม่มีอยู่ในมาตรฐาน C ++ ดังนั้นจึงไม่ใช่แบบพกพา
ใช้ "% zo" เพื่อ off_t (ฐานแปด) หรือ "% zu" สำหรับทศนิยม
fopen
,fseek
และอื่น ๆ บน Mac OS Xoff_t
ใช้สำหรับการชดเชย