違反嚴格的別名規則

在下面的程式碼中,讓我們假設 floatuint32_t 具有相同的大小。

void fun(uint32_t* u, float* f) {
    float a = *f
    *u = 22;
    float b = *f;
    print("%g should equal %g\n", a, b);
}

uf 具有不同的基型別,因此編譯器可以假設它們指向不同的物件。在 ab 的兩次初始化之間*f 不可能發生變化,因此編譯器可能會將程式碼優化為相當於

void fun(uint32_t* u, float* f) {
    float a = *f
    *u = 22;
    print("%g should equal %g\n", a, a);
}

也就是說,*f 的第二次載入操作可以完全優化。

如果我們正常呼叫此函式

 float fval = 4;
 uint32_t uval = 77;
 fun(&uval, &fval);

一切順利,等等

4 應該等於 4

列印出來。但如果我們作弊並傳遞相同的指標,轉換後,

 float fval = 4;
 uint32_t* up = (uint32_t*)&fval;
 fun(up, &fval);

我們違反了嚴格的別名規則。然後行為變得不確定。輸出可以如上所述,如果編譯器優化了第二次訪問,或者完全不同的東西,那麼你的程式最終會處於完全不可靠的狀態。