New to here: different results on PC and MAC. What for?

I am trying to learn the basics of C / C ++ right now. I am on course at Lynda.com

My questions are about the code sequence from Chapter 4, Macro Definitions from the Core C / C ++ Course. I followed all the setup procedures to properly configure Xcode and Eclipse on Mac and Eclipse on PC. When I run this code on MAC and PC, I get different results. Just trying to understand why this is happening, and what I can do to get the same result on both.

Here is the code:

// working.c by Bill Weinman <http://bw.org/> #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; } 

On PC, I get this result:

 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 

On the MAC (both Xcode and Eclipse) I get this result:

 increment returns 47 increment returns 52 increment returns 57 max of 50 and 47 is 57 increment returns 62 increment returns 67 increment returns 72 max of 50 and 62 is 72 

Why is this happening and what can I do to make sure the results are the same?

+5
source share
3 answers

You have unspecified results.

The order of evaluation within printf() not defined. When you have several increment() calls inside the same printf, you never know which ones are executed first and how they are evaluated.

+8
source

The order in which all the elements in the calculation of the full expression are evaluated is not defined. All that is required is that each subexpression fully checks the operands before evaluating it. In the case of a function call, the arguments can be evaluated in any order, and in fact, one argument can be partially evaluated at a time when another argument is fully evaluated.

First expand the macro:

 printf("max of %d and %d is %d\n", x, increment(), ((x) > (increment()) ? (x) : (increment())); 

(Unfortunately, there is another problem: if increment() greater than x , then it is called again. Make the MAX macro instead, so that the arguments are evaluated only once!)

All of the following sequences are possible. I omit the estimate of x here because it does not change.

  • The second argument to increment() calculated, followed by x > increment() , followed by any operand ?: . (This was probably the sequence you were expecting.)
  • x > increment() followed by some operand ?: followed by the second argument of increment() .
  • x > increment() , followed by the second argument of increment() , followed by any operand ?: .

All of them can give different results, and all of them are the correct interpretation of your code.

When you call several functions in one full expression, you must make sure that these functions either do not have side effects, or the side effects of each function do not change the behavior of any other function. Otherwise, compiling on another compiler (or another version of the same compiler!) Could have changed the result.

As an additional example, even the simply looking expression increment() > increment() has an unspecified result because the order in which the operands are evaluated is not defined; if the first operand is evaluated first, then the result will be false, otherwise it will be true.

In a more complex example ((a + b) * (c + d)) compiler can evaluate a , b , c and d in any order that he likes. All that is required is that a and b must be evaluated before a + b can be, c and d must be evaluated to c + d , and a + b and c + d must be evaluated to the final operator * .

+6
source

There are two problems here.

You rely on what the compiler chooses to evaluate printf () arguments. Expressed ratings first change the values ​​of later operators. Move increment () calls from the argument list. Save the results of increment () in variables instead and pass those variables to printf ().

Additionally, expanding the MAX macro may cause one argument to be evaluated once or twice. Thus, even on the same OS and compiler, you can get inconvenient results. To fix this, do the same as I suggested for storing the results of increment (). Pass these variables to MAX ().

+2
source

Source: https://habr.com/ru/post/1208450/


All Articles