-1

I have switched from MS Visual Studio to gcc, and currently I am trying to recompile some of the codes I have written in VS by gcc. Now I come across something odd. Simply explained, consider the following code, but first, note that I already know it's a very bad code (which is not the point here)

#include <iostream>

int main()
{
    int i = 0,
        a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
        b[10] = { 6, 5, 4, 1, 3, 2, 9, 7, 10, 8 };

    while (i ^ 5)   a[i++] = a[i] + b[i];

    while (i ^ 10)  a[i++] = a[i] - b[i];

    for (int j = 0; j < 10; j++)
        std::cout << a[j] << ' ';
}

When I compile it with Visual Studio, it results in:

7 7 7 5 8 4 -2 1 -1 2 

as expected. With gcc v.4.3.6 I also get the same result (Live example).

But when I switch to gcc 5.3.0, it results in:

7 7 5 8 8 -2 1 -1 2 -4198061

after generating many warnings about undefined behavior.

The question is, why visual studio, even in its most recent version, doesn't care about the quality of code and undefined behaviors, and why earlier versions of gcc do the same? What has happened in recent versions of gcc?

polfosol ఠ_ఠ
  • 1,840
  • 26
  • 41
  • 4
    _"after generating many warnings"_ You should probably fix these first. – πάντα ῥεῖ Apr 09 '16 at 09:36
  • 7
    Isn't `a[i++] = a[i] + b[i]` undefined behaviour? – jdarthenay Apr 09 '16 at 09:37
  • I simply don't get why different versions of gcc give different results. Can someone please give a clear answer? – polfosol ఠ_ఠ Apr 09 '16 at 09:38
  • Ohwait.. 'while (i ^ 5) a[i++]' - it IS modified twice...:( – Martin James Apr 09 '16 at 09:40
  • Why does someone give a bad reputation instead of an answer? What's going on here? – polfosol ఠ_ఠ Apr 09 '16 at 09:40
  • Well, the: 'while (i ^ 10) a[i++] =' is just terrible code, to start with. It deserves a downvote on its own. – Martin James Apr 09 '16 at 09:44
  • 1
    Who would write code like that, (apart from some deranged prof)? – Martin James Apr 09 '16 at 09:45
  • This is a simplified version of some complex (or as you say, deranged) code\ – polfosol ఠ_ఠ Apr 09 '16 at 09:46
  • 1
    Rewrite to use more lines, less 'clever' complexity. Sanitize it! – Martin James Apr 09 '16 at 09:47
  • 1
    @AliRezaNameghi some may have down voted because they feel you answer your own question by ignoring the compiler warnings, or feel you should have listed the warnings in your question. Alternativly its a quirk of S/O that some will downvote questions for emotive reasons rather than following S/O's own guidelines. In this case the downvote is most likely a "why would you want to?". I don't agree that such cases *should* get down voted, but they do. – Philip Couling Apr 09 '16 at 11:36
  • @couling - questions with code like this is of zero, or negative, use to future SO users. It's a terrible example to those newbs who don't recognise its inherent nastiness. If this code is not something dreamed up by a prof, I will be amazed. – Martin James Apr 09 '16 at 12:50
  • 1
    @MartinJames I can't understand why you are so aggressive (or maybe I am too sensitive!). First of all, I am trying to write a compiler (just for fun), so I am interested in understanding how a compiler works. So I often write codes in their most rubbish form just to see how the compiler deals with them, or just to compare their execution speed. Secondly, again, it's just for fun. Why you take it so seriously? It's really no harm in learning new things even by trying rubbish methods. Be cool man! Life is short – polfosol ఠ_ఠ Apr 09 '16 at 13:52
  • @MartinJames thats good information to put in an *answer* not a downvote. It does no harm to ask a question containing bad code if the answer clearly highlights this. Further more the OP was looking to get the answer to this question and it is not the first time I've seen it asked but the first time I've seen it asked from this angle... If the OP ran into this, then why do you suppose nobody else will? – Philip Couling Apr 09 '16 at 20:01
  • @MartinJames Many people learn how a language or library works by testing its limits. To those who use this method it's an exceptionally quick way to learn and to get a very deep understanding. This inevitably leads asking a lot of "what if" questions which are way outside of normal usage. Asking "bad" questions is never harmfull to future readers, only giving bad answers! – Philip Couling Apr 09 '16 at 20:10
  • Some editions have been made to make the question more clear. Hope this helps – polfosol ఠ_ఠ Apr 11 '16 at 06:33

3 Answers3

4

This topic is discussed in §1.9/15 (Program execution) of the C++11 standard:

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [ Note: In an expression that is evaluated more than once during the execution of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations. — end note ] The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, and they are not potentially concurrent (1.10), the behavior is undefined. ...

void g(int i, int* v) {
    i = v[i++];       // the behavior is undefined
    i = 7, i++, i++;  // i becomes 9
    i = i++ + 1;      // the behavior is undefined
}

Undefined Behavior means: anything can happen, the program might behave as you expect or something (as you say) "strange" might happen.

See also: "Sequence point" on Wikipedia:

... depending on the order of expression evaluation, the increment may occur before, after, or interleaved with the assignment. ...

A quick-fix would be to change

while (i ^ 5)   a[i++] = a[i] + b[i];

to

while (i ^ 5)   a[i] = a[i] + b[i], i++;
sergej
  • 17,147
  • 6
  • 52
  • 89
1

This line of code seems to me to be undefined behavior:

a[i++] = a[i] + b[i];

It could means:

a[i] = a[i] + b[i];
i++;

Or :

a[i] = a[i + 1] + b[i + 1];
i++;

It seems the two first compilers use first interpretation while the third compiler uses second interpretation.

jdarthenay
  • 3,062
  • 1
  • 15
  • 20
-1

'while (i ^ 5) a[i++]' - i modified twice, no sequence point, so UB.

'Between evaluation of the left and right operands of the && (logical AND), || (logical OR) ' - no mention of XOR.

Maybe.......

Martin James
  • 24,453
  • 3
  • 36
  • 60