#define Square(x)(x *(x))

可能重复:
使用#define定义的数字的平方

你能解释为什么以下代码输出“29”?

#define Square(x) (x*(x)) void main() { int x = 5; printf("%d", Square(x+3)); } 

由于宏只进行文本替换,因此您最终得到:

 x + 3 * (x + 3) 

这是29。

你应该绝对总是在括号之间放置宏参数。

 #define Square(x) ((x)*(x)) 

更好的是,使用函数并信任编译器内联它。


编辑

正如leemes所指出的那样,宏评估x两次的事实可能是一个问题。 使用函数或更复杂的机制(如gcc语句表达式)可以解决此问题。 这是一个笨拙的尝试:

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

运算符优先级。 你看,因为Square是一个宏,而不是一个函数,这就是编译器实际看到的:

 (x+3*(x+3)) 

哪个运算符优先级最终为:

 5 + (3 * (8)) 

或29.解决问题:

 #define Square(x) ((x)*(x)) 

请注意,虽然宏

 #define Square(x) ((x)*(x)) 

似乎解决了问题, 但事实并非如此 。 考虑一下:

 int x = 5; printf("%d\n", Square(x++)); 

预处理器将其扩展为:

 ((x++)*(x++)) 

这是未定义的行为 。 一些编译器会将其评估为

 (5 * 5) 

这似乎与预期一样。 但之后x = 7 ,因为增量运算符已经应用了两次。 显然不是你想要的。

有关输出,请参见此处: http : //ideone.com/9xwyaP

这就是为什么宏*是邪恶的。

(*宏往往用作内联函数的替代品。)

您可以使用模板函数在C ++中解决这个问题,模板函数可以通过指定具体类型来处理所有类型和C(因为在C中不支持重载,最好的是带有后缀的不同函数):

 // C int SquareI(int x) { return x * x; } float SquareF(float x) { return x * x; } double SquareD(double x) { return x * x; } // C++ template T Square(T x) { return x * x; } 

特别是对于GCC,还有另一种解决方案,因为GCC提供了typeof运算符,所以我们可以在宏中引入一个临时值:

 #define Square(x) ({ typeof (x) _x = (x); _x * _x; }) 

Et voila: http : //ideone.com/OGu08W

预处理器用x *(x)替换Square(x)。

您的代码看起来像printf("%d", x+3*(x))

你应该使用#define Square(x) ((x)*(x))

#define square(X) (x*(x))是一个宏,因此编译器用代码替换宏:

 square(x+3) = x+3*(x+3) = 5+3*(5+3) = 5+3*(8) = 29