[英]Rules for cascading macros in C
我無法找到處理下面案例的C預處理器的規則。 如果你假設一個直接替換,這種情況甚至不應該編譯,因為a=--1
。 但如果你假設用括號替換,那么a=-(-1) = 1
。
#include <stdio.h>
#define ALPHA -1
#define BETA -ALPHA
int main(void) {
int a = BETA;
int b = -ALPHA; // this compiles too, why? b = --1
printf("%d\n",a); // 1
return 0;
}
預處理是編譯之前的階段,它生成一個預處理轉換單元,它將作為編譯器的輸入。
其過程中的一些步驟是( 來自 C99 5.1.1.2 ):
源文件被分解為預處理令牌 。 (......)
執行預處理指令, 擴展宏調用 ,(...)
正如您所見,Tokenization 在宏調用之前,因此-ALPHA
將被視為2個單獨的預處理令牌(* ie -
和ALPHA
1 ),而不是您認為的2個預處理令牌--1
( --
和1
)
在第7條之后:
- 分隔標記 的空白字符不再重要 。 每個預處理令牌都轉換為令牌。
因此編譯器將獲得令牌並忽略空格。
如果使用gcc -E
生成預處理文件gcc -E
空格沒有任何意義,而您所看到的僅用於格式化為用戶,並且無法反映CPP的實際內部行為。
令牌不必用空格分隔 ,但通常需要避免歧義 (...)
一旦輸入文件被分解為令牌, 令牌邊界永遠不會改變 ,除非使用'##'預處理操作符將令牌粘貼在一起
編譯器不會重新標記預處理器的輸出 。 每個預處理令牌都成為一個編譯器令牌。
總結:
如果你寫-ALPHA
=>令牌是:
-
標點符號 - 二進制減號
-
標點符號 - 二進制減號
1
常數 - 整數常量
如果你寫--1
=>令牌是:
--
punctuator - 遞減運算符
1
常數 - 整數常量
遞減運算符不應該與常量一起使用,這就是編譯期間在這種情況下出錯的原因。
1: ALPHA
標識符將被兩個預處理標記替換 (在第4階段) -
並且已在宏定義中標識 1
這是您的程序在預處理完成后的樣子。
int main(void) {
int a = - -1;
int b = - -1;
printf("%d\n",a);
return 0;
}
您可以使用-E
選項和gcc
一起查看此輸出。
絕對不是--1
。 注意額外的空間。
首先要了解C預處理器不是編譯過程的一部分。 它只是替換過程,它告訴編譯器在實際編譯之前進行必要的預處理。
要了解很多,你必須閱讀宏觀陷阱 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.