Reputation: 187
The code below with the inputs 2, 3, 10 is intended to give the 12.5 as the result.([sum(2,3,10)(=15) + largest(2,3,10)(=10)] / smallest(2,3,10)(=2)) But it outputs 2.000 as the result, which is unwanted and wrong. Am I making a precedence error or what kind of a mistake am I making?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#define MIN( a, b ) ( ( a < b ) ? (a) : (b) ) // Why are the parantheses imporant?
#define MAX( a, b ) ( ( a < b ) ? (b) : (a) )
#define LARGEST( a, b, c ) ( MAX( a, b ) < c ) ? c : ( MAX( a, b ) )
#define SMALLEST( a, b, c ) ( a < MIN( b, c ) ) ? a : ( MIN( b, c ) )
#define SUM( a, b, c ) ( (a + b + c) )
#define EXPR( a, b, c ) ( (LARGEST( a, b, c ) + SUM( a, b, c ) ) / SMALLEST( a, b, c ) )
int main(){
float a, b, c;
printf("Enter three integers!\n");
scanf(" %f", &a);
scanf(" %f", &b);
scanf(" %f", &c);
printf("The result is %f.\n", EXPR(a, b, c));
return 0;
}
Upvotes: 3
Views: 169
Reputation: 6431
to see the actual code generated by the preprocessor merely execute this command
gcc -E main.c
we will get (just the last part of the output from the last command )
#include <stdio.h>
int main()
{
float a, b, c;
printf("Enter three integers!\n");
scanf(" %f", &a);
scanf(" %f", &b);
scanf(" %f", &c);
printf("The result is %f.\n", ( (( ( ( a < b ) ? (b) : (a) ) < c ) ? c : ( ( ( a < b ) ? (b) : (a) ) ) + ( (a + b + c) ) ) / ( a < ( ( b < c ) ? (b) : (c) ) ) ? a : ( ( ( b < c ) ? (b) : (c) ) ) ));
return 0;
}
This is a little bit complicated
( (( ( ( a < b ) ? (b) : (a) ) < c ) ? c : ( ( ( a < b ) ? (b) : (a) ) ) + ( (a + b + c) ) ) / ( a < ( ( b < c ) ? (b) : (c) ) ) ? a : ( ( ( b < c ) ? (b) : (c) ) ) )
My first guess was as I stated in the comment was precedence
so let's take the left operand in /
operator and ignore the rest for a moment to see the problem
(( ( ( a < b ) ? (b) : (a) ) < c ) ? c : ( ( ( a < b ) ? (b) : (a) ) ) + ( (a + b + c) ) )
|-----------------------------------------------|
the sum of the three operator will be added to the statement of the false condition ONLY (which is if a or b is the largest in this case) first and then we will evaluate the ?: because as you know the + is higher than ?: in table precedence
so let's call the left block just treated (just above) LeftBlock to make things simple for the next analysis
So combined with the right operand of /
operator (or what is left from the whole statement ) we will get
LeftBlock / ( a < ( ( b < c ) ? (b) : (c) ) ) ? a : ( ( ( b < c ) ? (b) : (c) ) )
now the /
is higher than the ?:
operator in precedence so this expression will be first evaluated
LeftBlock / ( a < ( ( b < c ) ? (b) : (c) ) ) ? a : ( ( ( b < c ) ? (b) : (c) ) )
|--------------------------------------------|
this is the condition for the ?: operator instead of only ( a < ( ( b < c ) ? (b) : (c) ) ) which is WRONG
As you can see the lack of parentheses leads to undesired result !!
There are many others pitfalls about macros that you should avoid you can check some of them from this link!
Finally I think I deobfuscated the problem !! :)
Upvotes: 9
Reputation: 53026
Because macro expansions substitute each ocurrence of the macro textualy, for example consider this simple macro
#define SQR(x) x * x
this macro when used like this
double x = SQR(1.0 + 2.0);
will expand to
double x = 1.0 + 2.0 * 1.0 + 2.0;
which yeilds 5.0
, if you add the parentheses, they will be inserted too
#define SQR(x) (x) * (x)
and then it would expand to
double x = (1.0 + 2.0) * (1.0 + 2.0);
which yields 9.0
.
Upvotes: 4