我读到*
(乘法)具有比/
(除法)更高的优先级。因此,如果同时存在*
和/
的等式,则*
必须首先发生。
但我看到一个输出奇怪的程序
#include<stdio.h>
#define SQUARE(x) x*x
int main()
{
float s=10, u=30, t=2, a;
a = 2*(s-u*t)/SQUARE(t);
printf("Result = %f", a);
return 0;
}
运行时,我认为输出为-25,但事实上它是-100。
当我寻找解释时,它是
Step 2: a = 2*(s-u*t)/SQUARE(t); becomes,
// Here SQUARE(t) is replaced by macro to t*t
=> a = 2 * (10 - 30 * 2) / t * t;
=> a = 2 * (10 - 30 * 2) / 2 * 2;
=> a = 2 * (10 - 60) / 2 * 2;
=> a = 2 * (-50) / 2 * 2 ;
/*till here it's OK*/
/*why it divided -50 by 2 before multiplying 2*2 and -50*2 */
=> a = 2 * (-25) * 2 ;
=> a = (-50) * 2 ;
=> a = -100;
请问任何人解释一下吗?
答案 0 :(得分:6)
括号偏执狂!你的宏应该是:
#define SQUARE(X) ((x)*(x))
否则优先规则和宏扩展会做奇怪的事情。你的宏:
100 / SQUARE(2)
将扩展为:
100 / 2*2
,读作:
(100/2) * 2
是100,而不是25。
其他异常,而不是在您的代码中,如果您尝试对表达式求平方:
SQUARE(2+2)
将扩展为
2+2*2+2
是8
,而不是预期的16
。
结论:在宏中写了很多括号。无处不在。
答案 1 :(得分:4)
除法和乘法具有相同的优先级,因此从左到右进行评估。 http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm
答案 2 :(得分:2)
它不会按照您的想法执行操作:在标记为/*till here it's OK*/
的步骤之后,操作按正常顺序进行乘法运算符,即从左到右:
=> a = 2 * (-50) / 2 * 2 ;
/*till here it's OK*/
=> a = -100 / 2 * 2 ; // Division
=> a = -50 * 2 ; // Multiplication
=> a = -100 ; // Done
您的代码是一个完美的例子,说明为什么需要非常小心宏:括号宏的参数可以解决这个特殊问题,但有些问题根本不可修复。例如,您的宏将不适用于具有副作用的表达式:
#define SQUARE(X) ((x)*(x))
// Still not good:
int a = 2;
// Undefined behavior, because ((a++)*(a++)) uses expressions with side effects without a sequence point
int b = SQUARE(a++);
出于这个原因,你最好将SQUARE
作为一个功能。