[英]Rules for cascading macros in C
I cannot find rules for C preprocessor that handle the case below. 我无法找到处理下面案例的C预处理器的规则。 If you assume a straight substitution this case should not even compile because a=--1
. 如果你假设一个直接替换,这种情况甚至不应该编译,因为a=--1
。 But if you assume substitution with parenthesis then a=-(-1) = 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;
}
Preprocessing is the phase which precede compilation it generates a preprocessing translation unit which will be the input for compiler. 预处理是编译之前的阶段,它生成一个预处理转换单元,它将作为编译器的输入。
Some of those steps in its process are ( From C99 5.1.1.2 ): 其过程中的一些步骤是( 来自 C99 5.1.1.2 ):
The source file is decomposed into preprocessing tokens . 源文件被分解为预处理令牌 。 (...) (......)
Preprocessing directives are executed, macro invocations are expanded , (...) 执行预处理指令, 扩展宏调用 ,(...)
As you can see Tokenization precede macro invocation so -ALPHA
will be considered as 2 separate preprocessing tokens (*ie -
and ALPHA
1 ) and not as you thought by 2 preprocessing token --1
( --
and 1
) 正如您所见,Tokenization 在宏调用之前,因此-ALPHA
将被视为2个单独的预处理令牌(* ie -
和ALPHA
1 ),而不是您认为的2个预处理令牌--1
( --
和1
)
After that in rule 7: 在第7条之后:
- White-space characters separating tokens are no longer significant . 分隔标记 的空白字符不再重要 。 Each preprocessing token is converted into a token. 每个预处理令牌都转换为令牌。
So the compiler will get tokens and ignore whitespaces. 因此编译器将获得令牌并忽略空格。
If you generate the preprocessing file with gcc -E
whitespaces have no significance and those you are seeing are only for formatting to user and cannot reflect the real internal behavior of CPP. 如果使用gcc -E
生成预处理文件gcc -E
空格没有任何意义,而您所看到的仅用于格式化为用户,并且无法反映CPP的实际内部行为。
From GCC CPP 5.4.0 1.3 : 来自GCC CPP 5.4.0 1.3 :
Tokens do not have to be separated by white space , but it is often necessary to avoid ambiguities (...) 令牌不必用空格分隔 ,但通常需要避免歧义 (...)
Once the input file is broken into tokens, the token boundaries never change , except when the '##' preprocessing operator is used to paste tokens together 一旦输入文件被分解为令牌, 令牌边界永远不会改变 ,除非使用'##'预处理操作符将令牌粘贴在一起
The compiler does not re-tokenize the preprocessor's output . 编译器不会重新标记预处理器的输出 。 Each preprocessing token becomes one compiler token. 每个预处理令牌都成为一个编译器令牌。
Summarizing: 总结:
If you write -ALPHA
=> tokens are: 如果你写-ALPHA
=>令牌是:
-
punctuator - binary minus sign -
标点符号 - 二进制减号
-
punctuator - binary minus sign -
标点符号 - 二进制减号
1
constant - integer constant 1
常数 - 整数常量
If you write --1
=> tokens are: 如果你写--1
=>令牌是:
--
punctuator - Decrement operator --
punctuator - 递减运算符
1
constant - integer constant 1
常数 - 整数常量
Decrement operator should not be used with constant that's why you get error in this case during compilation. 递减运算符不应该与常量一起使用,这就是编译期间在这种情况下出错的原因。
1 : ALPHA
identifier will be replaced (in phase 4) by two preprocessing tokens -
and 1
already identified in macro definition 1: ALPHA
标识符将被两个预处理标记替换 (在第4阶段) -
并且已在宏定义中标识 1
This is how your program looks after pre-processing is completed. 这是您的程序在预处理完成后的样子。
int main(void) {
int a = - -1;
int b = - -1;
printf("%d\n",a);
return 0;
}
You can view this output using -E
option with gcc
. 您可以使用-E
选项和gcc
一起查看此输出。
It is definitely not --1
. 绝对不是--1
。 Notice the extra space. 注意额外的空间。
First thing you have to understand that C Preprocessors is not a part of compilation process. 首先要了解C预处理器不是编译过程的一部分。 It's just the substitution process which tells the compiler to do required pre-processing before the actual compilation. 它只是替换过程,它告诉编译器在实际编译之前进行必要的预处理。
To understand much you have to read the Macro Pitfalls . 要了解很多,你必须阅读宏观陷阱 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.