มีปัญหาที่รู้จักกันดี กับ args ที่ว่างเปล่าสำหรับแมโคร variadic ใน C99
ตัวอย่าง:
#define FOO(...) printf(__VA_ARGS__)
#define BAR(fmt, ...) printf(fmt, __VA_ARGS__)
FOO("this works fine");
BAR("this breaks!");
การใช้งานBAR()
ด้านบนนั้นไม่ถูกต้องตามมาตรฐาน C99 เนื่องจากจะขยายเป็น:
printf("this breaks!",);
สังเกตเครื่องหมายจุลภาคต่อท้าย - ใช้งานไม่ได้
คอมไพเลอร์บางตัว (เช่น: Visual Studio 2010) จะกำจัดเครื่องหมายจุลภาคที่ต่อท้ายให้คุณอย่างเงียบ ๆ คอมไพเลอร์อื่น ๆ (เช่น: GCC) รองรับการวางไว้##
ด้านหน้า__VA_ARGS__
เช่น:
#define BAR(fmt, ...) printf(fmt, ##__VA_ARGS__)
แต่มีวิธีที่เป็นไปตามมาตรฐานในการรับพฤติกรรมนี้หรือไม่? บางทีใช้มาโครหลายตัว?
ตอนนี้##
รุ่นดูเหมือนจะได้รับการสนับสนุนอย่างดี (อย่างน้อยบนแพลตฟอร์มของฉัน) แต่ฉันควรใช้โซลูชันที่ได้มาตรฐาน
การจองล่วงหน้า: ฉันรู้ว่าฉันสามารถเขียนฟังก์ชันเล็ก ๆ ได้ ฉันพยายามทำสิ่งนี้โดยใช้มาโคร
แก้ไข : นี่คือตัวอย่าง (แต่ง่าย ๆ ) ว่าทำไมฉันถึงต้องการใช้ BAR ():
#define BAR(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
BAR("here is a log message");
BAR("here is a log message with a param: %d", 42);
สิ่งนี้จะเพิ่มบรรทัดใหม่ให้กับคำสั่งการบันทึก BAR () ของฉันโดยอัตโนมัติโดยถือว่าfmt
เป็นสตริง C สองครั้ง มันไม่ได้พิมพ์ขึ้นบรรทัดใหม่เป็น printf () แยกต่างหากซึ่งเป็นข้อได้เปรียบหากการบันทึกถูกแบ่งบรรทัดและมาจากหลายแหล่งพร้อมกัน
__VA_OPT__
คำหลัก สิ่งนี้ได้ถูก "นำไปใช้"โดย C ++ ดังนั้นฉันคาดว่า C จะเป็นไปตามความเหมาะสม (ไม่ทราบว่านั่นหมายความว่ามีการติดตามอย่างรวดเร็วใน C ++ 17 หรือถ้าตั้งไว้สำหรับ C ++ 20)
BAR
แทนที่จะFOO
เป็นที่แรก?