So I was talking a lynda course on learning the C language and this example was shown and barely explained so I was unable to understand why there results were what they were.Keep in mind the code isn't supposed to be correct, I'm just supposed to understand what happens.
#include <stdio.h>
#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
int increment() {
static int i = 42;
i += 5;
printf("increment returns %d\n", i);
return i;
}
int main( int argc, char ** argv ) {
int x = 50;
printf("max of %d and %d is %d\n", x,increment(), MAX(x, increment()));
printf("max of %d and %d is %d\n", x,increment(), MAX(x, increment()));
return 0;
}
and the result is:
increment returns 47
increment returns 52
max of 50 and 52 is 50
increment returns 57
increment returns 62
increment returns 67
max of 50 and 67 is 62
Can someone explain to me why increment returns 47 because if a is int x and int x = 50 and b is 47 because it executes MAX(x, increment()) . If I'm not reading the code wrong it should print 50 because 50 is greater than 47.
There are three issues at play here.
First is that your increment
function changes state every time you call it - it will always return a different value for each call. Second is that function arguments are not guaranteed to be evaluated left-to-right. Third is that after macro expansion, your printf
call looks like this:
printf("max of %d and %d is %d\n", x,increment(), (x) > (increment()) ? (x) : (increment()));
so it's possible for increment
to be called 3 times.
Based on your output, increment
is being called in this order:
printf("max of %d and %d is %d\n", x, increment(), (x) > (increment()) ? (x) : (increment()));
^ ^
| |
| +---- increment returns 47
+------------------------ increment returns 52
That is, the expression (x) > (increment()) ? (x) : (increment())
is being evaluated first - increment()
returns 47, which is not greater than x
(50), so the result of the expression is 50.
Sometime after that, the lone increment()
expression is called, which returns 52.
With the second printf
call, we get
printf("max of %d and %d is %d\n", x, increment(), (x) > (increment()) ? (x) : (increment()));
^ ^ ^
| | +---- increment returns 62
| +-------------------------- increment returns 57
+---------------------------------------------- increment returns 67
Again, (x) > (increment()) ? (x) : (increment())
is evaluated first. This time, increment()
is called twice, returning 57
in the test condition, then 62
in the result.
It's then called a third time when the expression increment()
is evaluated.
So...
The best way to deal with this is to assign the result of increment
to a temporary, and use that temporary in the printf
calls:
int tmp = increment();
printf( "max of %d and %d is %d\n", x, tmp, MAX(x, tmp) );
Most operators in C don't force left to right evaluation. The few that do are the logical &&
and ||
operators, the ?:
ternary operator, and the ,
comma operator (which is not the same as the commas used in parameter lists for function calls).