-4

The code below displays different results when compiled and run on Code::Blocks.

void sum(int a,int b){
    printf("a=%d b=%d\n",a,b);
}
int main(){
    int i=1;
    sum(i=5,++i);
    printf("i=%d\n\n",i);
    /***********************/
    i=2;
    sum(i=5,i++);
    printf("i=%d\n\n",i);
    /**********************/
    i=3;
    sum(i=5,i);
    printf("i=%d\n\n",i);
    return 0;
}

Output:

a=5 b=5
i=5

a=5 b=2
i=5

a=5 b=5
i=5

I think the answer to this question is related to sequence point and the sequence point is related to ++ operator here. GCC must be following an order to pass the value to stack in a fixed order but because of ++ the answers are different. I think for a beginner to write a function call like this is not very common, but the lesson about operators are general so one can try.

My questions are,what should be the exact answer of it and questions like it? During which phase of compilation these things are decided(made it clear or unclear)? Which particular algorithm(s) (either for optimization or in general) is involved? Can same compiler provide different result for such expression or statements? And the last on is, how a beginner will understand and figure out these problems? It is sometimes very surprising.

skyconfusion
  • 123
  • 8
  • Possible duplicate of [Why are these constructs (using ++) undefined behavior?](http://stackoverflow.com/questions/949433/why-are-these-constructs-using-undefined-behavior) – too honest for this site Mar 05 '16 at 17:34
  • 1
    The comma in `sum(i=5,++i);` is not a sequence point, it separates function arguments. The lesson is, if you want to use different values derived from a single variable, use for example `sum(i+5, i+1)` and update `i` afterwards. Or in this case, simply `sum(5, i+1)`. Apart from anything else, it is unclear what you intend the final value of `i` to be. Was it `5` or `6` or `2`? – Weather Vane Mar 05 '16 at 17:37
  • yes that is the better way to write. – skyconfusion Mar 05 '16 at 17:48
  • @Olaf it helped a little,thank you – skyconfusion Mar 05 '16 at 17:49

1 Answers1

1

The order of operations is decided during multiple phases of compilation, which is what causes the odd results you see. During the optimization phase in particular the compiler can reorder code in ways that aren't always obvious, and in this case it's affecting the result (which is fine, because you're doing something undefined and the compiler's explicitly allowed to do anything it wants to with that code). There isn't any specific algorithm involved, it's an interaction between several different algorithms applied at different points and the algorithm applied at each point can vary depending on what the compiler's decided is the best way to handle a particular bit of code.

When the documentation speaks of undefined behavior, it's not the behavior of a specific compiler that's undefined but the specification of what the compiler must or is allowed to do. The compiler's behavior is completely defined, but it's defined by detailed decisions buried deep in the design of it's parser, code generator and optimizer modules and it's complicated enough that not even the developers who wrote the compiler can tell you what it'll do without spending a lot of time analyzing how a given bit of code flows through the entire process.

A beginner won't be able to figure out the outcome. Even an expert developer may not be able to. That's why "undefined" is such an unwelcome word to developers, and why they try to avoid undefined behavior like the plague. To quote from a discussion of the language spec in question, "In short, you can't use sizeof() on a structure whose elements haven't been defined, and if you do, demons may fly out of your nose.".

Todd Knarr
  • 1,255
  • 1
  • 8
  • 14
  • "The compiler's behavior is completely defined" - This is not required to be true. The compiler can very well use heuristics with a random component. And the link (at least its text) implies something completely different. If the size of a `struct` is not know, it is just impossible to calc its its size. – too honest for this site Mar 05 '16 at 17:53
  • It's impossible to calculate, but because the result of trying to do it's undefined behavior the compiler's free to do anything from throwing an error to just assuming some arbitrary size and using that to crashing the machine or worse. Throwing an error because the calculation's impossible is merely the most common behavior (because most compiler devs are sensible and don't go out of their way to write malevolent behavior in even if they're allowed to). – Todd Knarr Mar 05 '16 at 18:06