繁体   English   中英

C中级联宏的规则

[英]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 ):

  1. 源文件被分解预处理令牌 (......)

  2. 执行预处理指令, 扩展宏调用 ,(...)

正如您所见,Tokenization 宏调用之前,因此-ALPHA将被视为2个单独的预处理令牌(* ie -ALPHA 1 ),而不是您认为的2个预处理令牌--1--1

在第7条之后:

  1. 分隔标记 的空白字符不再重要 每个预处理令牌都转换为令牌。

因此编译器将获得令牌并忽略空格。

如果使用gcc -E生成预处理文件gcc -E空格没有任何意义,而您所看到的仅用于格式化为用户,并且无法反映CPP的实际内部行为。

来自GCC CPP 5.4.0 1.3

令牌不必用空格分隔 ,但通常需要避免歧义 (...)

一旦输入文件被分解为令牌, 令牌边界永远不会改变 ,除非使用'##'预处理操作符将令牌粘贴在一起

编译器不会重新标记预处理器的输出 每个预处理令牌都成为一个编译器令牌。

总结:

如果你写-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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM