Different versions of gcc differently compile the same code [duplicate]

两盒软妹~` 提交于 2019-12-13 08:20:00

问题


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?


回答1:


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++;



回答2:


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.




回答3:


'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.......



来源:https://stackoverflow.com/questions/36515046/different-versions-of-gcc-differently-compile-the-same-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!