Salahuddin
Salahuddin

Reputation: 1719

Multiplication and division: weird output in c

I read that * (multiplication) has has higher presedence than / (division). Thus if there is an equation with both * and /, then * must take place first.

But I've seen a program that output something strange

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

When running this, I thought that the output would be -25, but in fact it was -100.

When I looked for the explanation it was

 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; 

Can any one explain please?

Upvotes: 1

Views: 251

Answers (3)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726499

It does not do what you think it does: after the step marked /*till here it's OK*/, the operations proceed in their regular order for multiplicative operators, i.e. left to right:

=> a = 2 * (-50) / 2 * 2 ;
/*till here it's OK*/
=> a = -100 / 2 * 2 ; // Division
=> a = -50 * 2 ;      // Multiplication
=> a = -100 ;         // Done

Your code is a perfect example of why one needs to be very careful with macros: parenthesizing macro's parameters would fix this particular problem, but some problems are simply non-fixable. For example, your macro would remain unsuitable for expressions with side effects:

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

For this reason, you would be better off making SQUARE a function.

Upvotes: 2

chtenb
chtenb

Reputation: 16184

Division and muliplication have the same precedence, and are thus evaluated from left to right. http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm

Upvotes: 3

rodrigo
rodrigo

Reputation: 98348

Parenthesis paranoia! Your macro should be:

#define SQUARE(X) ((x)*(x))

Or else precedence rules and macro expansion will do weird things. Your macro:

100 / SQUARE(2)

will expand to:

100 / 2*2

and that is read as:

(100/2) * 2

which is 100, not 25.

Other anomaly, not in your code is if you try to square an expression:

SQUARE(2+2)

will expand to

2+2*2+2

which is 8, not the expected 16.

Conclusion: in macros write a lot of parentheses. Everywhere.

Upvotes: 5

Related Questions