ฉันรู้ว่านี่เป็นเวลานานหลังจากข้อความค้นหาเดิม แต่อาจยังมีประโยชน์
สามารถทำได้ใน GCC โดยใช้ตัวดำเนินการ stringify "#" แต่ต้องใช้สองขั้นตอน
#define XSTR(x) STR(x)
#define STR(x) #x
จากนั้นค่าของมาโครสามารถแสดงด้วย:
#pragma message "The value of ABC: " XSTR(ABC)
โปรดดูที่ 3.4 สตริงในเอกสารออนไลน์ของ gcc
มันทำงานอย่างไร:
ตัวประมวลผลก่อนเข้าใจสตริงที่ยกมาและจัดการต่างจากข้อความปกติ การต่อสายอักขระเป็นตัวอย่างของการปฏิบัติพิเศษนี้ ข้อความ pragma ต้องการอาร์กิวเมนต์ที่เป็นสตริงที่ยกมา เมื่อมีองค์ประกอบมากกว่าหนึ่งในอาร์กิวเมนต์พวกเขาทั้งหมดจะต้องเป็นสตริงเพื่อให้สามารถใช้การต่อสตริงได้ ตัวประมวลผลก่อนไม่สามารถสันนิษฐานได้ว่าสตริงที่ไม่ได้ใส่เครื่องหมายคำพูดควรได้รับการปฏิบัติราวกับว่าถูกยกมา หากเป็นเช่นนั้น:
#define ABC 123
int n = ABC;
จะไม่รวบรวม
ตอนนี้พิจารณา:
#define ABC abc
#pragma message "The value of ABC is: " ABC
ซึ่งเทียบเท่ากับ
#pragma message "The value of ABC is: " abc
สิ่งนี้ทำให้เกิดคำเตือนก่อนตัวประมวลผลเนื่องจากไม่สามารถเชื่อม abc (ไม่ใส่เครื่องหมายคำพูด) กับสตริงที่อยู่ก่อนหน้า
ตอนนี้ให้พิจารณาการทำให้สตริงของตัวประมวลผลล่วงหน้า (ซึ่งครั้งหนึ่งเรียกว่าการทำให้เป็นสตริงลิงก์ในเอกสารประกอบได้รับการเปลี่ยนแปลงเพื่อให้สอดคล้องกับคำศัพท์ที่แก้ไขแล้ว (โดยบังเอิญทั้งสองคำมีความเกลียดชังเท่าเทียมกันคำที่ถูกต้องคือแน่นอนว่าเป็นสตริงที่พร้อมที่จะอัปเดต ลิงก์ของคุณ)) สิ่งนี้ทำหน้าที่เฉพาะกับอาร์กิวเมนต์ของมาโครและแทนที่อาร์กิวเมนต์ที่ไม่ได้ขยายด้วยอาร์กิวเมนต์ที่อยู่ในเครื่องหมายคำพูดคู่ ดังนั้น:
#define STR(x) #x
char *s1 = "abc";
char *s2 = STR(abc);
จะกำหนดค่าที่เหมือนกันให้กับ s1 และ s2 หากคุณเรียกใช้ gcc -E คุณจะเห็นสิ่งนี้ในเอาต์พุต บางที STR อาจจะดีกว่าชื่อ ENQUOTE
วิธีนี้ช่วยแก้ปัญหาในการใส่เครื่องหมายคำพูดรอบ ๆ รายการที่ไม่ได้ใส่เครื่องหมายคำพูดปัญหาตอนนี้คือถ้าอาร์กิวเมนต์เป็นมาโครมาโครจะไม่ถูกขยาย นี่คือสาเหตุที่ต้องใช้มาโครตัวที่สอง XSTR ขยายอาร์กิวเมนต์จากนั้นเรียก STR เพื่อใส่ค่าที่ขยายลงในเครื่องหมายคำพูด