วิธีการพิมพ์ uint64_t? ล้มเหลวกับ: "ต่อท้ายปลอม"% "ในรูปแบบ"


134

ฉันเขียนรหัสทดสอบที่ง่ายมากของ printf uint64_t:

#include <inttypes.h>
#include <stdio.h>

int main()
{
  uint64_t ui64 = 90;
  printf("test uint64_t : %" PRIu64 "\n", ui64);
  return 0;
}

ฉันใช้ ubuntu 11.10 (64 บิต) และ gcc เวอร์ชัน 4.6.1 เพื่อคอมไพล์ แต่ล้มเหลว:

main.cpp: In functionint main()’:
main.cpp:9:30: error: expected ‘)’ beforePRIu64main.cpp:9:47: warning: spurious trailing ‘%’ in format [-Wformat]

1
ดูเหมือนว่าคุณกำลังรวบรวมรหัส C เป็น C ++ นั่นเป็นข้อผิดพลาดของคุณ หากคุณเปลี่ยนชื่อไฟล์main.cและคอมไพล์ด้วย gcc ทุกอย่างจะทำงานได้ดี
Jens Gustedt

เหมือนกันโดยไม่มีข้อผิดพลาด: stackoverflow.com/questions/9225567/…
Ciro Santilli 郝海东冠状病六四事件法轮功

ด้วย gcc หรือ clang คุณควรระบุ-std=c11หรือเวอร์ชันของมาตรฐานที่คุณใช้ ที่ตรวจจับข้อผิดพลาดนี้และข้อผิดพลาดอื่น ๆ ฉันยังแนะนำ-Wall -Wextra -Wpedantic -Wconversionอย่างน้อย
Davislor

คำตอบ:


166

มาตรฐาน ISO C99 ระบุว่าต้องกำหนดมาโครเหล่านี้หากมีการร้องขออย่างชัดเจนเท่านั้น

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

... now PRIu64 will work

@ แดนอย่าลืมทำเครื่องหมายคำตอบว่ายอมรับ (คลิกภาพเครื่องหมายถูกทางด้านซ้าย) ถ้ามันแก้ปัญหาของคุณได้
zneak

9
อืมแค่รวมส่วนหัวก็น่าจะเพียงพอแล้ว __STDC_FORMAT_MACROSแมโครจะต้องเฉพาะสำหรับการรวมใน C ++
Jens Gustedt

15
@ เจนส์: แน่นอน; __STDC_FORMAT_MACROSจะปรากฏเฉพาะในเชิงอรรถใน C99 โดยบอกว่า C ++ กำหนดเฉพาะมาโครเหล่านี้ต่อหน้าคำขอเท่านั้น อย่างไรก็ตามคณะกรรมการ C ++ เลือกที่จะเพิกเฉยต่อข้อเสนอแนะ: เช่นในร่าง n3242 27.9.2 / 3: หมายเหตุ: มาโครที่กำหนดโดย <cinttypes> มีให้โดยไม่มีเงื่อนไข โดยเฉพาะอย่างยิ่งสัญลักษณ์ __STDC_FORMAT_MACROS ที่กล่าวถึงในเชิงอรรถ 182 ของมาตรฐาน C ไม่มีบทบาทใน C ++ ดังนั้นเมื่อคอมไพเลอร์ตามทันเราก็ไม่จำเป็นต้อง__STDC_FORMAT_MACROSใช้ C หรือ C ++
John Marshall

3
@John Marshall g ++ 4.7.3 ดูเหมือนจะต้องการมาโครแม้ว่าจะรวม <inttypes.h> แล้วก็ตาม
crockeea

4
@ เอริก: เห็นได้ชัดว่า g ++ 4.7.3 ตามไม่ทัน! อันที่จริงคุณอาจใช้มันกับเวอร์ชัน glibc ที่มาก่อนการแก้ไขข้อบกพร่องนี้ ตามที่กล่าวไว้ในรายงาน glibc นั้น libstdc ++ ของ g ++ 4.7.3 ของคุณมีโค้ดที่จะแก้ไขปัญหานี้ หากคุณมีการรวบรวม-std=c++0xและบางทีอาจจะ #include <cinttypes> มากกว่า <inttypes.h> __STDC_FORMAT_MACROSผมเชื่อว่ามันต้องการให้แมโครรูปแบบโดยที่คุณไม่จัดหา
John Marshall

4

เมื่อรวบรวม memcached ภายใต้ Centos 5.xi ก็พบปัญหาเดียวกัน

วิธีแก้ปัญหาคือการอัปเกรด gcc และ g ++ เป็นเวอร์ชัน 4.4 เป็นอย่างน้อย

ตรวจสอบให้แน่ใจว่า CC / CXX ของคุณตั้งค่า (ส่งออก) เป็นไบนารีที่ถูกต้องก่อนที่จะคอมไพล์


1

เนื่องจากคุณได้รวมแท็ก C ++ ไว้แล้วคุณสามารถใช้ไลบรารี {fmt}และหลีกเลี่ยงPRIu64มาโครและprintfปัญหาอื่น ๆโดยสิ้นเชิง:

#include <fmt/core.h>

int main() {
  uint64_t ui64 = 90;
  fmt::print("test uint64_t : {}\n", ui64);
}

สิ่งอำนวยความสะดวกรูปแบบขึ้นอยู่กับห้องสมุดนี้มีการเสนอสำหรับมาตรฐานใน C ++ 20: P0645

ข้อจำกัดความรับผิดชอบ : ฉันเป็นผู้เขียน {fmt}


เย็น! มันมาคล้ายกับsscanf?
ceztko

อาจเป็นไปได้ scanfเรากำลังตรวจสอบความเป็นไปได้ของการแทนที่
vitaut

เยี่ยมมาก! นอกจากนี้ฉันสงสัยว่ามีความคืบหน้าไปสู่เวอร์ชันที่เป็นอิสระและ / หรือโลแคลที่เลือกได้ของstd::to_string(). หน้า cppreference ยังคงลิงก์ไปเท่านั้นstd::to_chars()ซึ่งไม่ใช่สิ่งที่ผู้คนต้องการจริงๆ ฉันสงสัยว่าfmtและ / หรือ c ++ 20 จัดการกับมันหรือยัง
ceztko

std::to_stringอาจจะยังคงเป็นอยู่ แต่std::formatช่วยให้คุณสามารถควบคุมได้ว่าจะใช้ภาษาหรือไม่ (และโดยค่าเริ่มต้นจะไม่ใช้ภาษา)
vitaut
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.