6

我在一个网站上看到了下面的代码。我无法理解结果是如何来的11,而不是25or 13

为什么我在想25,因为SQ(5) 5*5

或者13因为

SQ(2) = 4;

SQ(3) = 9;

可能最终结果会是13 (9 + 4) ,但惊讶地看到结果11。结果如何11

using namespace std;
#define SQ(a) (a*a)
int main()
{
    int ans = SQ(2 + 3);
    cout << ans << endl;
system("pause");
}
4

6 回答 6

19

预处理器对源代码进行简单的文本替换。它对底层语言或其规则一无所知。

在您的示例中,SQ(2 + 3)扩展为(2 + 3*2 + 3),其计算结果为11

一种更稳健的定义方式SQ是:

#define SQ(a) ((a)*(a))

现在,SQ(2 + 3)将扩展为((2 + 3)*(2 + 3)),给予25

尽管这个定义是一种改进,但它仍然不是万无一失的。如果SQ()应用于具有副作用的表达式,这可能会产生不良后果。例如:

  • Iff()是一个向控制台打印内容并返回 , 的函数intSQ(f())将导致输出被打印两次。
  • 如果i是一个int变量,则SQ(i++)导致未定义的行为

有关使用宏的更多困难示例,请参阅宏陷阱

由于这些原因,通常最好使用函数而不是宏。

于 2012-12-05T07:29:34.263 回答
6

#define扩展在编译器看到源代码之前就开始了。这就是为什么它们被称为预处理器指令,这里的处理器是将 C 转换为机器可读代码的编译器。

因此,这就是宏预处理器传递给编译器的内容:

SQ(2 + 3)扩展为(2 + 3*2 + 3)

所以,这真的是2 + 6 + 3= 11

你怎样才能让它达到你期望的效果?

  1. 执行评估顺序。在宏定义或宏调用中使用 ()。或者
  2. 编写一个简单的函数来完成这项工作
于 2012-12-05T07:39:28.230 回答
3

C 预处理器在编译器通常解释表达式和 C 语法之前进行文本替换。因此,在此代码上运行 C 预处理器会转换:

SQ(2 + 3)

进入:

2 + 3*2 + 3

这简化为:

2 + 6 + 3

这是11。

于 2012-12-05T07:31:12.997 回答
1

只是编译前的替换

所以你应该试试这个:

#define SQ(a) ((a)*(a))

在您的情况下,SQ(2 + 3)相当于(2+3*2+3)which is 11

但是按照我上面写的那样更正它,((2+3)*(2+3))这就是5*5 = 25你想要的答案。

于 2012-12-05T07:30:30.093 回答
1

#定义预处理器

语法: #定义标识符替换

  1. 当预处理器遇到此指令时,它会通过替换替换其余代码中出现的任何标识符。
  2. 这种替换可以是表达式、语句、块或任何东西。
  3. 预处理器不理解 C,它只是通过替换替换任何出现的标识符。

#define 也可以使用参数来定义函数宏:

# define SQ(a) (a*a)

将在编译时将任何出现的 SQ(a) 替换为 a*a。因此,

SQ(2+3) 将被替换为 2+3*2+3 替换完成后进行计算。因此回答 2+3*2+3=11

于 2012-12-05T07:42:31.940 回答
1

对于您的实现,该值将扩展2+3 * 2+3为 2+6+3=11。

您应该将其定义为:

#define SQ(x) ({typeof(x) y=x; y*y;})

测试gcc,对于像这样的输入

  1. 常数,
  2. 多变的,
  3. 常数+常数
  4. 常量+变量
  5. 变量++ / ++变量
  6. 函数调用,包含 printf。

注意:typeof是 GNU 对标准 C 的补充。在某些编译器中可能不可用。

于 2012-12-05T08:22:32.367 回答