1

I have the following C code:

#include <stdio.h>

int x = 2;
int f (int z) { int temp = x; x += 2*z; return temp; }

#define MIN(X,Y)  ((X) < (Y) ? (X) : (Y))  /* side effects may cause error */
int MIN_fix(X,Y) { if (X < Y) return X; else return Y; }

int main () {
unsigned char b = 0x3, c = 0x1;
printf("result> %d, %d\n", MIN(b+c, f(3)), MIN_fix(b+c, f(3)));
}

why did I get "result> 4, 2" should it be 8 instead of 4?

FL93
  • 29
  • 5
  • 4
    Did you notice the comment `/* side effects may cause error */`? – kdopen Oct 21 '16 at 18:07
  • 1
    Additionally, your program has undefined behavior because the evaluations of the second and third arguments to your `printf` call both have side effects on variable `x`, and these are not sequenced relative to each other. – John Bollinger Oct 21 '16 at 18:11
  • See http://stackoverflow.com/questions/376278/parameter-evaluation-order-before-a-function-calling-in-c Possibly a duplicate – kdopen Oct 21 '16 at 18:11
  • 1
    Even if the order of evaluation of the `printf` operands were defined, I see no reason to expect the program to print "result> 8, 2". The value of `b+c` is 4, so neither the `MIN()` macro expansion nor the `MIN_fix()` call would ever evaluate to anything larger than 4. – John Bollinger Oct 21 '16 at 18:15
  • Actually, I think it *could* return 8 .. expand MIN to `4 < f(3) ? 4 : f(3)` and evaluate it left to right: the first call returns 2, the second returns 8 so it becomes `4 < 2? 4 : 8` - if the arguments to `printf` are evaluated strictly left to right. But then I'd expect an output of "8,4" – kdopen Oct 21 '16 at 18:37
  • when compiling, always enable all the warnings, then fix those warnings. (for `gcc`, at a minimum use: `-Wall -Wextra -pedantic` I also use: `-Wconversion -std=gnu99` ) – user3629249 Oct 22 '16 at 06:40
  • for ease of readability and understanding: follow the axiom: *only one statement per line and (at most) one variable declaration per statement.* – user3629249 Oct 22 '16 at 06:42
  • the function: `MIN_fix` is missing the parameter types for each parameter. This will result in each parameter being assumed to be of type `int`. Probably not what you want. – user3629249 Oct 22 '16 at 06:44

1 Answers1

0

As this hasn't been downvoted or closed as a duplicate, I'll try and explain

Let's look at your printf call:

printf("result> %d, %d\n", MIN(b+c, f(3)), MIN_fix(b+c, f(3)));

Now b+c is effectively a constant value (4), so this turns into

printf("result> %d, %d\n", MIN(4, f(3)), MIN_fix(4, f(3)));

If we expand the MIN macro invokation, and remove unneeded parens, we get the following

printf("result> %d, %d\n", 4 < f(3)? 4 : f(3), MIN_fix(4, f(3)));

So we have 3 calls to f(3) in this line of code. The first three calls to that function return 2, 8, and 14 respectively. But there's no guarantee in which order those calls will be evaluated.

Let's let f1=2, f2=8, and f3=14. Your printf could be any of the following with their output in the comment

printf(..., 4<f1?4:f2, MIN_fix(4,f3)); //  8, 4
printf(..., 4<f1?4:f3, MIN_fix(4,f2)); // 14, 4
printf(..., 4<f2?4:f1, MIN_fix(4,f3)); //  4, 4
printf(..., 4<f2?4:f3, MIN_fix(4,f1)); //  4, 2
printf(..., 4<f3?4:f1, MIN_fix(4,f3)); //  4, 4 
printf(..., 4<f3?4:f2, MIN_fix(4,f1)); //  4, 2

Any of the outputs are valid - because you have undefined behavior

kdopen
  • 8,032
  • 7
  • 44
  • 52