Tôi biết rằng đây là một thời gian dài sau truy vấn ban đầu, nhưng điều này có thể vẫn hữu ích.
Điều này có thể được thực hiện trong GCC bằng cách sử dụng toán tử stringify "#", nhưng nó yêu cầu hai giai đoạn.
#define XSTR(x) STR(x)
#define STR(x) #x
Giá trị của macro sau đó có thể được hiển thị bằng:
#pragma message "The value of ABC: " XSTR(ABC)
Xem: 3.4 Cấu trúc chuỗi trong tài liệu trực tuyến gcc.
Làm thế nào nó hoạt động:
Bộ tiền xử lý hiểu các chuỗi được trích dẫn và xử lý chúng khác với văn bản bình thường. Nối chuỗi là một ví dụ về cách xử lý đặc biệt này. Thông báo pragma yêu cầu một đối số là một chuỗi được trích dẫn. Khi có nhiều hơn một thành phần trong đối số thì tất cả chúng phải là chuỗi để có thể áp dụng nối chuỗi. Bộ tiền xử lý không bao giờ có thể cho rằng một chuỗi chưa được trích dẫn phải được coi như thể nó đã được trích dẫn. Nếu nó đã làm thì:
#define ABC 123
int n = ABC;
sẽ không biên dịch.
Bây giờ hãy xem xét:
#define ABC abc
#pragma message "The value of ABC is: " ABC
tương đương với
#pragma message "The value of ABC is: " abc
Điều này gây ra cảnh báo bộ xử lý trước vì abc (chưa được trích dẫn) không thể được nối với chuỗi trước đó.
Bây giờ hãy xem xét chuỗi tiền xử lý (Trước đây được gọi là chuỗi hóa, các liên kết trong tài liệu đã được thay đổi để phản ánh thuật ngữ sửa đổi. liên kết của bạn.)) toán tử. Điều này chỉ hoạt động trên các đối số của macro và thay thế đối số không được mở rộng bằng đối số được đặt trong dấu ngoặc kép. Như vậy:
#define STR(x) #x
char *s1 = "abc";
char *s2 = STR(abc);
sẽ gán các giá trị giống nhau cho s1 và s2. Nếu bạn chạy gcc -E, bạn có thể thấy điều này trong đầu ra. Có lẽ STR nên được đặt tên giống như ENQUOTE.
Điều này giải quyết vấn đề đặt dấu ngoặc kép xung quanh một mục không được trích dẫn, vấn đề bây giờ là, nếu đối số là một macro, thì macro sẽ không được mở rộng. Đây là lý do tại sao macro thứ hai là cần thiết. XSTR mở rộng đối số của nó, sau đó gọi STR để đặt giá trị được mở rộng vào dấu ngoặc kép.