【问题标题】:Strange behavior of Macro-expansion宏观扩张的奇怪行为
【发布时间】:2013-03-11 11:14:09
【问题描述】:

代码如下:

#include <stdio.h>
#include <stdio.h>
#define VAL1(a,b)    a*b
#define VAL2(a,b)    a/b
#define VAL3(a,b)    ++a%b
int main()
{
    int a = 1;
    int b = 2;
    int c = 3;
    int d = 3;
    int e = 5;

    int result = VAL2(a,d)/VAL1(e,b)+VAL3(c,d);  // result = 1
    //int result = a/d/e*b+++c%d;                // result = 0

    printf("%d\n", result);

    return 0;
}

为什么两个语句的结果不一样?

【问题讨论】:

    标签: c macros c-preprocessor


    【解决方案1】:

    在一种情况下,您拥有+ ++,而在另一种情况下,您拥有++ ++ ++++ + 是不同的令牌流。宏粘贴不会更改标记化,因为粘贴的是标记。

    如果你把你的程序打入一个 C 预处理器,你会为那一行得到这个:

    int result = a/d/e*b+ ++c%d;
    

    请注意,预处理器必须插入一个空格,因为在 + 令牌和 ++ 令牌之间必须有一个空格。

    【讨论】:

      【解决方案2】:

      我尝试用 GCC 4.7 编译它,两个表达式给出了相同的结果。

      如果你想看看宏是如何展开的,你可以使用cpp,它是C Preprossessor,它会在预处理器表达式执行后给你输出,这里的输出是

      int main()
      {
          int a = 1;
          int b = 2;
          int c = 3;
          int d = 3;
          int e = 5;
      
          int result = a/d/e*b+++c%d;  
          int result2 = a/d/e*b+++c%d;  
      
          printf("%d %d\n", result, result2);
      
          return 0;
      }
      

      【讨论】:

      • 错了。再仔细看看。它预处理到int result = a/d/e*b+ ++c%d;
      • 我用 GCC 4.7.0 用 Code::Blocks 编译,结果不一样!
      【解决方案3】:

      如果您确实认为有必要使用此类宏,则需要使用括号 () 以避免副作用:

      #define VAL1(a,b)    ((a)*(b))
      #define VAL2(a,b)    ((a)/(b))
      #define VAL3(a,b)    ((++a)%(b))
      

      【讨论】:

      • 我知道这是个好习惯。但是想知道为什么宏展开后VAL2(a,d)/VAL1(e,b)+VAL3(c,d)和a/d/e*b+++c%d不一样!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      相关资源
      最近更新 更多