【问题标题】:Incorrect answer from #define SQR(x) (x*x) [duplicate]#define SQR(x) (x*x) 的错误答案 [重复]
【发布时间】:2014-09-13 10:34:50
【问题描述】:

以下程序正在打印49

#include <stdio.h> 
#define SQR(x) (x*x) 
void main(void) { 
    int x, y; x = 5; 
    y = SQR(++x); 
    printf("y is %d\n", y); 
}

我不明白我错过了什么。
这是我所理解的它可能是如何工作的
SQR(++x) 中,++x 将被评估为6,在x*x 之后应返回36
因此y = 36
但答案是 49

【问题讨论】:

  • 想想宏是如何工作的以及表达式被计算了多少次。
  • @Matt:不,它本身不是未定义的。
  • @Matt:啊,我明白了——++x 的执行顺序未知...

标签: c


【解决方案1】:

阅读关于C preprocessor 的维基页面并了解C 预处理器在纯文本级别运行(作为编译器的第一阶段)。另请阅读GNU cpp 文档。您的 y = SQR(++x); 扩展为

y = ++x * ++x;

这不是您应该想要的。阅读undefined behavior(和this answer)。 用SQR(y+3) 想想发生的恐怖(使用你原来的SQR)。

查看源代码的预处理形式。使用GCC,使用

gcc -C -E foo.c > foo.i

获取foo.i(您应该使用编辑器或寻呼机检查)foo.c 的预处理形式

因此,至少,您应该将宏定义为

#define SQR(x) ((x)*(x))

否则SQR(y+3) 不会像你想要的那样扩展。一般来说,在使用宏时,您应该知道(并记录,例如在评论中,如果您正在编写宏)发生了什么。

事实上,在你的情况下,你根本不应该使用宏,而是定义一个inline function

static inline int square(int x) { return x*x; }

这将与您的宏一样快,但更安全,因为square(++x) 只会(正确地)增加一次x,而square(y+3) 正在做你想做的事!

【讨论】:

    【解决方案2】:

    请记住,宏几乎被逐字替换,这意味着您的

    SQR(++x);
    

    将被替换为

    ++x * ++x;
    

    而且,正如 dyp 所指出的,这是未定义的行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-02
      • 2014-03-09
      相关资源
      最近更新 更多