2012-03-24 51 views
0

我不明白为什么结果将是36.有人可以向我解释这里发生了什么,以及预处理器做了什么?C++宏的副作用

#include <iostream> 
#define QUADRAT(x) ((x) * (x)) 

using namespace std; 

int main() 
{ 
    double no = 4.0; 
    double result = QUADRAT(++no); 

    cout << result; 
    return 0; 
} 

非常感谢:>

回答

4

在该示例中,预处理器将用((++no) * (++no))代替QUADRAT(++no)

如果不是因为两个增量之间没有顺序点这一事实,会增加两次no,所以实际上会导致未定义的行为。你看到的任何输出都是有效的,因为没有人能够知道会发生什么。

+1

感谢奥利,现在它有道理:) – Max 2012-03-25 00:00:46

2

预处理是基本上是复制和粘贴引擎。注意一个宏是而不是的一个函数;相反,它是内嵌扩展的。考虑在扩展宏时代码会发生什么。

+2

塞思,我想他说了一个错误的答案。 – 2012-03-25 00:01:47

+0

我的意思是你的回答Seth,但奇怪的是Stackoverflow告诉我这是Oli的错误发布。现在你的名字是在它下面..:/ – Max 2012-03-25 00:09:50

0

会发生什么事是一种替代X的++没有文字替代的,这就像你写的:

double result = ((++no) * (++no)); 

的结果是什么?应该是不确定的行为(你36偶然),并且g ++与-Wall同意我的观点。

1

这条线:

double result = QUADRAT(++no); 

被扩大到这一点:

double result = ((++no) * (++no)); 

,这最终运行的方式是等价于:

no = no + 1; 
no = no + 1; 
result = no * no; 

它运行这种方式,因为增量在乘法之前执行:预处理器做一个你传递它的文本副本,所以它复制“++ no”,以便在最终代码中显示两次,并且在计算结果之前每个++的增量不发生。解决这个问题的方法是使用一个内联函数:

inline double QUADRAT(double x) { return x * x; } 

大多数现代编译器会出扩大这个代码,而不做一个文本替换 - 他们会给你的东西一样快,预处理器定义,但没有危险像你面临的问题一样。