[英]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.