乘法和除法:c中的奇怪输出

时间:2014-01-11 10:06:22

标签: c math

我读到*(乘法)具有比/(除法)更高的优先级。因此,如果同时存在*/的等式,则*必须首先发生。

但我看到一个输出奇怪的程序

#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; 

请问任何人解释一下吗?

3 个答案:

答案 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作为一个功能。