วิธีการพิมพ์“ ไม่ได้ลงนามนาน” ใน C?


344

ฉันไม่สามารถเข้าใจวิธีการพิมพ์ unsigned longประเภทข้อมูลใน C

สมมติว่าunsigned_fooเป็นunsigned longแล้วฉันลอง:

  • printf("%lu\n", unsigned_foo)
  • printf("%du\n", unsigned_foo)
  • printf("%ud\n", unsigned_foo)
  • printf("%ll\n", unsigned_foo)
  • printf("%ld\n", unsigned_foo)
  • printf("%dl\n", unsigned_foo)

และพวกเขาทั้งหมดพิมพ์-123123123หมายเลขบางชนิดแทนที่unsigned longฉันมี

คำตอบ:


499

%luunsigned longเป็นรูปแบบที่ถูกต้องสำหรับ ดูเหมือนว่ามีปัญหาอื่น ๆ ที่เล่นที่นี่เช่นความเสียหายของหน่วยความจำหรือตัวแปรที่ไม่ได้กำหนดค่าเริ่มต้น บางทีแสดงให้เราเห็นภาพใหญ่ขึ้น?


12
โอ๊ะ%luทำงานครั้งนี้ ขอบคุณ ต้องมีอย่างอื่นเกิดขึ้นก่อนหน้านี้และใช้งานไม่ได้
bodacydo

1
@bodacydo: หากคุณมีข้อผิดพลาดมันอาจปรากฏขึ้นแบบกึ่งสุ่ม ... ตรวจสอบว่าตัวแปรของคุณมีค่าที่ถูกต้องก่อนที่จะลองพิมพ์
Thanatos

1
แม้ว่าตัวแปร uninitialized ควรจะมีไม่ถึงวิธี printf %luจุดที่มันสามารถพิมพ์เครื่องหมายลบเมื่อระบุรูปแบบเป็น ในทางเทคนิคแล้วมันเป็นพฤติกรรมที่ไม่ได้กำหนด แต่ในความเป็นจริงแล้วตัวแปรมีค่าที่คาดเดาไม่ได้ซึ่งจะถูกส่งผ่านไปยัง printf ซึ่ง printf แปลความหมายนั้นเป็น unsigned ฉันเดาว่าปัญหาดั้งเดิมของ bodacydo คือการส่งสายเรียกไปยัง printf ที่ไม่ถูกต้องแทนที่จะเป็นที่ตั้งใจไว้ ...
R. GitHub หยุดช่วยน้ำแข็ง

8
@Anisha Kaul:% lu เป็นข้อกำหนดการแปลงที่ถูกต้อง% ul ไม่ใช่ %luแยกออกเป็น: %- เริ่ม "ข้อกำหนดการแปลง"; l- ตัวปรับความยาวlหมายถึง "[ไม่ได้ลงนาม] long int"; u- ตัวระบุการแปลงuสำหรับการunsigned intที่จะพิมพ์ออกมาเป็นทศนิยม เพราะเราให้ปรับปรุงความยาวมันก็ยอมรับl unsigned long intตัวอักษรจะต้องอยู่ในลำดับนั้น: เปอร์เซ็นต์, ความยาว, การแปลง (มีตัวเลือกเพิ่มเติมอีกสองสามอย่างเช่นความกว้างและความแม่นยำที่คุณสามารถเพิ่มดูหน้าเอกสารได้อย่างแม่นยำ!)
Thanatos

1
% ul จะพิมพ์ออกมาโดยไม่ได้ลงชื่อ (ด้วย% u) จากนั้นตามด้วยตัวอักษร "l" คำต่อคำ เช่นเดียวกับ "% uw" จะพิมพ์แบบไม่ลงนามตามด้วยตัวอักษร "w" % เริ่ม convspec, u (หรือตัวละครอื่น ๆ เช่น d, s, c ... ) จบลง
Veky

30
  • %luสำหรับยาวไม่ได้ลงนาม
  • %lluสำหรับยาวไม่ได้ลงนาม

13
แบบแผนของ Yoda: "long ที่ไม่ได้ลงนาม" "(l) ong (u) nsigned" คือ
Reb.Cabin

28

สำหรับint %d

สำหรับint นาน %ld

สำหรับint ที่ยาวนาน %lld

สำหรับint long long ที่ไม่ได้ลงชื่อ %llu


23

จากชุดค่าผสมทั้งหมดที่คุณลอง%ldและ%luเป็นชุดเดียวที่เป็นตัวระบุรูปแบบการพิมพ์ที่ถูกต้องเลย %lu(ทศนิยมที่ไม่ได้ลงชื่อยาว) %lxหรือ%lX(hex ยาวที่มีตัวพิมพ์เล็กหรือตัวพิมพ์ใหญ่) และ%lo(long octal) เป็นตัวระบุรูปแบบที่ถูกต้องเพียงตัวเดียวสำหรับตัวแปรประเภทที่ไม่ได้ลงชื่อยาว (แน่นอนว่าคุณสามารถเพิ่มความกว้างของฟิลด์ความแม่นยำ ฯลฯ%และl)


1
% ld จะทำงานได้ดีจนถึงค่า std :: numeric_limits <unsigned long> :: max () / 2 เหนือกว่านั้น% ld จะพิมพ์ค่าผิด (ค่าลบ)
Kaushik Acharya

1
@KaushikAcharya: ไม่เหนือกว่านั้นคือ UB และมันก็เป็นเนื้อหาที่แม้ UB ก่อนว่าตั้งแต่printfมีการระบุจะต้องตรงกับประเภทอาร์กิวเมนต์ที่ถูกต้องโดยไม่ต้องตั้งค่าเผื่อที่va_argจะมี
.. GitHub หยุดช่วยเหลือน้ำแข็ง


9

%luรูปแบบคือ

โปรดตรวจสอบประเภทข้อมูลอื่น ๆ และการใช้งานใน printf ที่นี่


2
พฤติกรรมที่ไม่เป็นมาตรฐานต่าง ๆ มีการบันทึกไว้ที่นั่นโดยไม่ทำเครื่องหมายว่าไม่เป็นมาตรฐาน POSIX เป็นมาตรฐานออนไลน์ที่ง่ายที่สุดในการเข้าถึงสำหรับ printf; ส่วนขยายที่เกิน ISO C จะถูกทำเครื่องหมายด้วยแท็ก "CX": opengroup.org/onlinepubs/9699919799/functions/fprintf.html
R .. GitHub STOP ช่วย ICE

8

ตัวระบุที่ถูกต้องสำหรับ long ที่ไม่ได้ลงชื่อคือ %luตัวระบุที่ถูกต้องเป็นเวลานานไม่ได้ลงนามเป็น

หากคุณไม่ได้รับค่าที่แน่นอนที่คุณคาดหวังอาจมีปัญหาบางอย่างในรหัสของคุณ

กรุณาคัดลอกรหัสของคุณที่นี่ จากนั้นอาจมีคนบอกคุณได้ดีกว่าว่าปัญหาคืออะไร


-5

ผมมีปัญหาเหมือนกัน. ลอง "% ul" มันใช้งานได้สำหรับฉัน


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