ฉันจะพิมพ์ประเภทเช่น off_t และ size_t ได้อย่างไร


148

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

หรือมีวิธีที่แตกต่างอย่างสิ้นเชิงในการพิมพ์ตัวแปรเหล่านั้น?


2
@devin: ฉันเชื่อว่าฉันพบว่าประเภทนั้นในขณะที่ใช้fopen, fseekและอื่น ๆ บน Mac OS X off_tใช้สำหรับการชดเชย
Georg Schölly

คำตอบ:


112

คุณสามารถใช้zsize_t และtptrdiff_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รูปแบบตามลำดับ


2
off_t เป็นระบบของฉันที่ใช้เวลานานนานมาก
Georg Schölly

2
ฉันคิดว่า man page ไม่สนับสนุนการใช้ Z (ตัวพิมพ์ใหญ่) ที่ libc5 ใช้ ดูเหมือนว่าจะไม่ย่อท้อ z (ตัวพิมพ์เล็ก)
Draemon

12
การใช้%zdกับ a size_tคือพฤติกรรมที่ไม่ได้กำหนดเนื่องจากความไม่ลงนามในลายเซ็น (C99 7.19.6.1 # 9) %zuมันจะต้องเป็น
Jens

7
ด้วยวิธีการพิมพ์ off_t แล้ว?
JohnyTex

3
@Jens ฉันไม่เห็นว่า%zdด้วยsize_tพฤติกรรมที่ไม่ได้กำหนดจากวรรคนั้นหรือจากอื่น ๆ ในความเป็นจริงคำจำกัดความของ%zใน # 7 อนุญาตอย่างชัดเจน%dด้วยsize_tและประเภทที่ลงนามที่สอดคล้องกันและ§6.2.5 # 9 อนุญาตการใช้ค่าของประเภทที่ไม่ได้ลงนามอย่างชัดเจนโดยที่คาดว่าจะเป็นประเภทที่ลงนามที่เกี่ยวข้องตราบใดที่ค่านั้นเป็นค่า ประเภทที่เซ็นชื่อ
Chortos-2

108

วิธีพิมพ์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ซึ่งจะล้มเหลวในการใช้งานอื่น ๆ เพราะมีขนาดเล็กเกินไป


3
นี่คือคำตอบที่ดีกว่าฉันจะลืมเกี่ยวกับการใช้% zu สำหรับ size_t ที่ไม่ได้ลงชื่อ และการส่งไปยัง intmax_t เป็นโซลูชันที่ยอดเยี่ยมสำหรับทุกสิ่งที่ off_t อยู่บนแพลตฟอร์มใด ๆ
Peter Cordes

2
POSIX ไม่รับประกันว่าssize_tมีขนาดเท่าsize_tกันดังนั้นรหัสแบบพกพาอย่างแท้จริงควรแปลงเป็นintmax_tและพิมพ์ด้วย%jdเหมือนoff_tกัน
nwellnhof

off_t อาจมีขนาดยาวเกินขนาดและสามารถเปลี่ยนแปลงได้ขึ้นอยู่กับการกำหนด ... Visual Studio เตือนด้วยสิ่งนี้ด้วย "คำเตือน C4477: '_snprintf_s': สตริงรูปแบบ '% jd' ต้องการอาร์กิวเมนต์ชนิด '__int64' แต่อาร์กิวเมนต์แบบแปรปรวน 1 มีประเภท 'off_t' "... วิธีแบบพกพาที่แท้จริงคือ printf ("% lld \ n ", (ยาว) x
ericcurtin

5

สำหรับ 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)
sourcejedi

3

คุณใช้ C รุ่นใด

ใน C90 การปฏิบัติมาตรฐานคือการส่งไปยังเซ็นชื่อหรือไม่ได้ลงนามนานตามความเหมาะสมและพิมพ์ตามนั้น ฉันเห็น% z สำหรับ size_t แล้ว แต่ Harbison และ Steele ไม่ได้พูดถึงมันใน printf () และในกรณีใด ๆ ที่ไม่ช่วยคุณด้วย ptrdiff_t หรืออะไรก็ตาม

ใน C99 ประเภท _t ต่างๆมาพร้อมกับมาโคร printf ของตัวเองดังนั้นบางอย่างที่"Size is " FOO " bytes." ฉันไม่ทราบรายละเอียด แต่นั่นเป็นส่วนหนึ่งของรูปแบบตัวเลขที่ค่อนข้างใหญ่รวมถึงไฟล์


3

คุณจะต้องใช้มาโครการจัดรูปแบบจาก inttypes.h

ดูคำถามนี้: สตริงรูปแบบข้ามแพลตฟอร์มสำหรับตัวแปรประเภท size_t?


สมมติว่า off_t เป็น int ขนาดตัวชี้ (ฉันไม่ทราบว่าคำจำกัดความที่แม่นยำคืออะไร) เช่น ptrdiff_t จากนั้นคุณจะใช้ PRIdPTR หรือ PRIiPTR
Michael Burr

11
off_tประเภทมีขนาดใหญ่กว่าตัวชี้บนระบบ 32 บิตที่สนับสนุนไฟล์ขนาดใหญ่ (ซึ่งเป็นส่วนใหญ่ระบบ 32 บิตวันนี้บริการ)
Dietrich Epp

1
@DietrichEpp: จริงๆแล้วมันแย่กว่านั้น ระบบ 32 บิตจำนวนมากมีทั้ง off_t และ off64_t และขึ้นอยู่กับคุณสมบัติของมาโคร off_t อาจหมายถึง off64_t
SamB

1

มองไปที่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- บิตระบบ)


1
ระบบของฉัน (OS X) มี 32 บิตunsigned intและ off_t64 ดังนั้นนักแสดงจะทำให้ข้อมูลสูญหาย
Dietrich Epp

-3

ฉันเห็นโพสต์นี้อย่างน้อยสองครั้งเพราะคำตอบที่ยอมรับนั้นยากสำหรับฉันที่จะจำ (ฉันไม่ค่อยได้ใช้zหรือตั้งjค่าสถานะและดูเหมือนว่าพวกเขาจะไม่เป็นอิสระจากแพลตฟอร์ม )

มาตรฐานไม่เคยพูดอย่างชัดเจนความยาวของข้อมูลที่แน่นอนของsize_tผมจึงขอแนะนำให้คุณควรตรวจสอบความยาวsize_tบนแพลตฟอร์มของคุณแล้วเลือกหนึ่งของพวกเขา:

if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64

และฉันขอแนะนำให้ใช้stdintประเภทแทนชนิดข้อมูลดิบเพื่อความสอดคล้อง


1
สำหรับ C99 และ C11 สถานะมาตรฐานอย่างชัดเจนที่%zuสามารถใช้เพื่อพิมพ์size_tค่า หนึ่งควรแน่นอนไม่หันไปใช้uint32_t/ uint64_tระบุรูปแบบการพิมพ์size_tเช่นไม่มีการรับประกันว่าประเภทที่เข้ากันได้
ออทิสติก

-4

ในฐานะที่ผมจำได้วิธีเดียวที่พกพาที่จะทำมันคือการโยนผลให้ "int ยาวไม่ได้ลงนาม" %luและการใช้งาน

printf("sizeof(int) = %lu", (unsigned long) sizeof(int));

1
ควรเป็น "% lu" เนื่องจากตัวปรับความยาวควรมาก่อนการแปลง
dwc

1
ตัวอย่างเช่น off_t เป็นแบบยาวที่ลงชื่อแล้ว
เฟรดSchölly

@ GeorgSchölly - จากนั้นคุณก็โดนปริศนาเพราะ long longไม่มีอยู่ในมาตรฐาน C ++ ดังนั้นจึงไม่ใช่แบบพกพา
James Curran

-9

ใช้ "% zo" เพื่อ off_t (ฐานแปด) หรือ "% zu" สำหรับทศนิยม


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