C中级联宏的规则

C中级联宏的规则,c,c-preprocessor,C,C Preprocessor,我找不到处理以下情况的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)

我找不到处理以下情况的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;
}
#包括
#定义α-1
#定义β-α
内部主(空){
int a=β;
int b=-ALPHA;//这也可以编译,为什么呢?b=--1
printf(“%d\n”,a);//1
返回0;
}

首先您必须了解C预处理器不是编译过程的一部分。只是替换过程告诉编译器在实际编译之前进行所需的预处理


要了解更多信息,您必须阅读。

这是预处理完成后程序的外观

int main(void) {
    int a = - -1;
    int b = - -1;
    printf("%d\n",a);
    return 0;
}
您可以使用带有
gcc
-E
选项查看此输出


它绝对不是
--1
。注意额外的空间

预处理是编译之前的阶段,它生成一个预处理翻译单元,作为编译器的输入

其过程中的一些步骤是(从C99 5.1.1.2):

  • 源文件被分解成预处理标记。(……)

  • 执行预处理指令,宏调用展开,,(…)

  • 正如您所看到的,标记化在宏调用之前,因此
    -ALPHA
    将被视为2个独立的预处理标记(*即
    -
    ALPHA
    1),而不是您所认为的2个预处理标记
    --1
    --
    1

    在此之后,在第7条中:

  • 空格字符分隔标记不再有效。 每个预处理令牌都转换为一个令牌
  • 因此编译器将获取标记并忽略空白

    如果使用
    gcc-E
    生成预处理文件,则空格没有任何意义,您看到的空格仅用于对用户进行格式化,不能反映CPP的真实内部行为

    标记不必用空格分隔,但通常是 必要的以避免歧义(…)

    一旦输入文件被分解成令牌,令牌边界就永远不会出现 更改,除非使用“##”预处理运算符进行粘贴 标记在一起

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

    总结:

    如果您写入
    -ALPHA
    =>标记为:

    • -
      标点符号-二进制减号

    • -
      标点符号-二进制减号

    • 1
      常量-整数常量

    如果您写入
    --1
    =>令牌是:

    • --
      标点器-减量运算符

    • 1
      常量-整数常量

    减量运算符不应与常量一起使用,这就是为什么在编译过程中出现这种情况下的错误



    1:
    ALPHA
    标识符将替换为两个预处理令牌
    -
    1
    宏定义中已识别的

    请帮个忙。尽量少使用宏-它们不是类型安全的。它们是简单的文本替换,使用编译器的功能这实际上并没有回答问题。