2012-06-14 29 views
10

VớiVề ## Preprocessor trong C

#define cat(x,y) x##y 

Cuộc gọi cat(a,1) lợi nhuận a1, nhưng cat(cat(1,2),3) là undefined. Tuy nhiên, nếu tôi cũng xác định #define xcat(x,y) cat(x,y) thì kết quả là xcat(xcat(1,2),3) hiện là 123. Ai có thể vui lòng giải thích chi tiết tại sao điều này là như vậy?

+0

Bạn có nghĩa là 'sau đó kết quả của xcat (xcat (1,2), 3) bây giờ là 123' không? –

+0

@notfed: Xin lỗi tôi đã nhầm lẫn khi viết câu hỏi. Kết quả của xcat (xcat (1,2), 3) là 123 – sourabh912

Trả lời

2

Tôi đã thử nghiệm điều này bằng cả GCC và Clang.

GCC cung cấp cho các lỗi:

test.c:6:1: error: pasting ")" and "3" does not give a valid preprocessing token 

Clang cung cấp cho các lỗi:

test.c:6:11: error: pasting formed ')3', an invalid preprocessing token 
    int b = cat(cat(1,2),3); 

gì dường như xảy ra là trình biên dịch kết thúc tốt đẹp là kết quả của cat(1,2) trong ngoặc đơn ngay sau khi nó được mở rộng ; vì vậy khi bạn gọi cat(1,2) trong mã của bạn, nó thực sự cung cấp cho bạn (12). Sau đó, gọi lại cat((12),3) sẽ dẫn đến ((12)3), đây không phải là mã thông báo hợp lệ và điều này dẫn đến lỗi biên dịch.

Ý kiến ​​chung là "khi sử dụng toán tử dán mã thông báo (##), bạn nên sử dụng hai cấp độ gián tiếp" (nghĩa là sử dụng giải pháp xcat của bạn). Xem Why do I need double layer of indirection for macros?What should be done with macros that need to paste two tokens together?.

+0

Trong câu hỏi của tôi sau khi thay thế xcat (x, y) bằng cat (x, y) nó một lần nữa trở thành mèo (cat (1,2), 3) sau đó ngay cả bây giờ nó sẽ trả về token không hợp lệ. Tôi không thể hiểu làm thế nào hai cấp độ của indirection đang làm việc. Tôi đã đọc URL trên nhưng vẫn không rõ ràng với tôi. – sourabh912

0

Tôi không nghĩ rằng nếu con mèo thực sự sẽ được mở rộng trong 2 lần liên tiếp. Đó là lý do tại sao tôi tự hỏi tại sao trình biên dịch lại tạo ra một thông điệp như vậy như 'pasting ")" and "3" does not give a valid preprocessing token'. Ngoài ra, tôi không nghĩ rằng con mèo bên trong sẽ được mở rộng trước. Vì vậy, tôi đoán đầu ra sẽ là cat(1,2)3. Điều đó hướng dẫn tôi để cogitate như thế nào trình biên dịch sẽ giải thích điều này.

1

Trong xcat (x, y), x và y không liền kề với toán tử ## và để chúng trải qua việc mở rộng macro trước khi được thay thế.

Vì vậy x được xác định là xcat (1,2) và y được xác định là 3. Nhưng trước để thay thế, x được mở rộng macro thành cat (1,2), biến thành 1 ## 2 biến thành 12. Vì vậy, cuối cùng, xcat (xcat (1,2), 3) sẽ mở rộng cho mèo (12,3), sẽ bật ra 123.

Tác phẩm này -> cat (xcat (1) , 2), 3) -> mèo (mèo (1,2), 3) -> mèo (12,3)

Hành vi này được xác định rõ ràng vì tất cả các thẻ dán mã thông báo dẫn đến hợp lệ các mã thông báo tiền xử lý tức là bất kỳ xpression mở rộng nào cũng nên một mã thông báo hợp lệ ở bất kỳ giai đoạn nào.

+0

Vâng, ví dụ của bạn không hoạt động, nhưng 'xcat (cat (1,2), 3)' vẫn làm. – Niloct

Các vấn đề liên quan