Bạn không thể làm điều đó nếu USER được định nghĩa là một chuỗi được trích dẫn.
Nhưng bạn có thể làm điều đó nếu USER chỉ là JACK hoặc QUEEN hoặc Joker hoặc bất cứ điều gì.
Có hai thủ thuật để sử dụng:
- Ghép mã thông báo, nơi bạn kết hợp một số nhận dạng với một số nhận dạng khác bằng cách chỉ nối các ký tự của chúng. Điều này cho phép bạn so sánh với JACK mà không cần phải
#define JACK
làm gì đó
- mở rộng macro variadic, cho phép bạn xử lý macro với số lượng đối số thay đổi. Điều này cho phép bạn mở rộng các số nhận dạng cụ thể thành các số dấu phẩy khác nhau, chúng sẽ trở thành phép so sánh chuỗi của bạn.
Vì vậy, hãy bắt đầu với:
#define JACK_QUEEN_OTHER(u) EXPANSION1(ReSeRvEd_, u, 1, 2, 3)
Bây giờ, nếu tôi viết JACK_QUEEN_OTHER(USER)
và USER là JACK, bộ tiền xử lý sẽ biến điều đó thànhEXPANSION1(ReSeRvEd_, JACK, 1, 2, 3)
Bước hai là nối:
#define EXPANSION1(a, b, c, d, e) EXPANSION2(a##b, c, d, e)
Bây giờ JACK_QUEEN_OTHER(USER)
trở thànhEXPANSION2(ReSeRvEd_JACK, 1, 2, 3)
Điều này tạo cơ hội để thêm một số dấu phẩy tùy theo việc một chuỗi có khớp hay không:
#define ReSeRvEd_JACK x,x,x
#define ReSeRvEd_QUEEN x,x
Nếu USER bị JACK, JACK_QUEEN_OTHER(USER)
trở thànhEXPANSION2(x,x,x, 1, 2, 3)
Nếu USER là QUEEN, JACK_QUEEN_OTHER(USER)
trở thànhEXPANSION2(x,x, 1, 2, 3)
Nếu USER khác, JACK_QUEEN_OTHER(USER)
trở thànhEXPANSION2(ReSeRvEd_other, 1, 2, 3)
Tại thời điểm này, một điều gì đó quan trọng đã xảy ra: đối số thứ tư cho macro EXPANSION2 là 1, 2 hoặc 3, tùy thuộc vào việc đối số ban đầu được truyền là jack, queen hay bất kỳ thứ gì khác. Vì vậy, tất cả những gì chúng ta phải làm là chọn nó ra. Vì lý do dài dòng, chúng ta sẽ cần hai macro cho bước cuối cùng; chúng sẽ là EXPANSION2 và EXPANSION3, mặc dù một cái có vẻ không cần thiết.
Kết hợp tất cả lại với nhau, chúng ta có 6 macro sau:
#define JACK_QUEEN_OTHER(u) EXPANSION1(ReSeRvEd_, u, 1, 2, 3)
#define EXPANSION1(a, b, c, d, e) EXPANSION2(a##b, c, d, e)
#define EXPANSION2(a, b, c, d, ...) EXPANSION3(a, b, c, d)
#define EXPANSION3(a, b, c, d, ...) d
#define ReSeRvEd_JACK x,x,x
#define ReSeRvEd_QUEEN x,x
Và bạn có thể sử dụng chúng như thế này:
int main() {
#if JACK_QUEEN_OTHER(USER) == 1
printf("Hello, Jack!\n");
#endif
#if JACK_QUEEN_OTHER(USER) == 2
printf("Hello, Queen!\n");
#endif
#if JACK_QUEEN_OTHER(USER) == 3
printf("Hello, who are you?\n");
#endif
}
Liên kết chốt chặn bắt buộc: https://godbolt.org/z/8WGa19