它是 gcc -O2 优化错误(与 -O1 不同的结果)吗?

sky*_*000 2 c c++ optimization gcc

我编写了一个非常简单的程序,它在没有-O2以下情况下正常运行:

#include <stdio.h>
#include <stdint.h>

int main()
{
    uint32_t A[4] = { 1, 2, 3, 4 };
    float B[4] = { 0, 0, 0, 0 };
    float C[4] = { 5, 6, 7, 8 };
    int i;

    // convert integer A to float B
    for (i = 0; i < 4; i++) 
        B[i] = (float)A[i];

    // memory copy from B to C
    uint32_t *src = (uint32_t*)(B);
    uint32_t *dst = (uint32_t*)(C);
    dst[0] = src[0];
    dst[1] = src[1];
    dst[2] = src[2];
    dst[3] = src[3];

#if 0
    // open this to correct the error
    __asm__("":::"memory");
#endif

    // print C, C should be [1.0, 2.0, 3.0, 4.0]
    for (i = 0; i < 4; i++) 
        printf("%f\n", C[i]);

    return 0;
}

Run Code Online (Sandbox Code Playgroud)

编译没有-O2

$ gcc error.c -o error
$ ./error
1.0000
2.0000
3.0000
4.0000
Run Code Online (Sandbox Code Playgroud)

它按预期工作。但是如果我添加了一个-O2

$ gcc -O2 error.c -o error
$ ./error
-6169930235904.000000
0.000000
-6169804406784.000000
0.000000
Run Code Online (Sandbox Code Playgroud)

此外,如果您切换#if 0#if 1,它会再次正常工作。本asm ("":::"memory")应该是在同一个线程不必要的。

-O2优化bug吗??

有什么我可以告诉编译器来处理它的事情吗??我有一个函数可以将 xmm 寄存器存储到 (void*) 指针,例如:

$ gcc -O2 error.c -o error
$ ./error
-6169930235904.000000
0.000000
-6169804406784.000000
0.000000
Run Code Online (Sandbox Code Playgroud)

dstC在上面的代码,任何方式,使其正确不修改函数签名。

Bat*_*eba 9

不,这不是编译器错误的表现。

相反,由于您使用了强制转换&c的结果,您的代码的行为是未定义的(uint32_t*)(B)。这违反了严格别名

编译器——尤其是 gcc——在处理未定义的构造时变得越来越积极。标准允许它们假设未定义的行为不会发生,并且可以删除包含它的任何分支。

  • @skywind3000 `std::copy` 来救援! (2认同)
  • 或“memcpy”,因为尽管有 C++ 标签,但这似乎是 C 代码。 (2认同)