#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