簡體   English   中英

修改const int時gcc -O2標志會產生影響

[英]gcc -O2 flag affect while modifying const int

我知道在C中我們可以通過指針修改'const int'。 但是在編譯程序時我在gcc中啟用了'-O2'標志,並且const int無法修改該值,所以只想知道gcc優化標志如何影響修改'const int'。

這是示例應用程序test.c

#include <stdio.h>
#include <stdlib.h>

int main(int ac, char *av[])
{
        const int i = 888;
        printf("i is %d \n", i);
        int *iPtr = &i;
        *iPtr = 100;
        printf("i is %d \n", i);
        return 0;
}

gcc -Wall -g -o test test.c
./test
i is 888 
i is 100

gcc -Wall -g -O2 -o test test.c
i is 888 
i is 888

這種好奇心讓我寫下這個問題。

修改聲明為const的變量是未定義的行為。 未定義的行為是......未定義的; 換句話說,編譯器可以做任何事情, 包括假設未實際發生未定義的行為。

在這種情況下,編譯器可以通過假設它永遠不會改變來優化對const int i的訪問; 允許編譯器在對printf的調用中插入i的已知初始值。 事實上,它可以預先計算在編譯時輸出的字符串,因為它知道printf應該做什么。

你可以通過指針繞過const聲明,這是不正確的。 如果變量最初聲明為const ,則嘗試修改它無效。 你可以做的是創建一個指向可變變量的const指針,然后通過將其拋棄來繞過指針的const 由於原始變量不是const ,這是合法的(雖然通常不是一個好主意。)

(強制性標准參考:§6.7.3/ 6:“如果嘗試通過使用具有非const限定類型的左值來修改使用const限定類型定義的對象,則行為是未定義的。”)

我知道在C中我們可以通過指針修改'const int'。

不,那是錯的。 C語言標准明確指出修改const對象是“未定義的行為”。 這意味着任何事情都可能發生 - 代碼可能會成功,它可能會崩潰,它可能會破壞你的硬盤,或讓惡魔飛出你的鼻子。 所有這些行為都被認為是合法的。 因此,行為根據編譯器的優化級別而變化的事實也是完全合法的。

任何有價值的編譯器都會警告你這件事。 使用默認的編譯器選項,GCC在我嘗試編譯代碼時有用地告訴我:

$ gcc test.c
test.c: In function 'main':
test.c:8:21: warning: initialization discards 'const' qualifier from pointer target type [enabled by default]

Clang類似:

$ clang test.c
test.c:8:14: warning: initializing 'int *' with an expression of type
      'const int *' discards qualifiers
      [-Wincompatible-pointer-types-discards-qualifiers]
        int *iPtr = &i;
             ^      ~~

此行是違反約束

int *iPtr = &i;

&i的類型是const int * 當前C標准(“簡單分配”)的6.5.16.1/1部分涵蓋了代碼的行為,其中列出了賦值的約束。

這些約束的一部分是左操作數不允許指向非限定類型的指針,而右操作數是指向限定類型​​的指針。

如果編譯器在標准兼容模式下運行,則必須提供診斷消息。 它可能無法生成可執行文件。 如果編譯器繼續執行任何其他操作,則標准不再涵蓋該行為。 (換句話說,該程序具有完整的未定義行為)。

NB。 其他答案提到“修改const對象”,但是這與在任何修改對象的嘗試之前發生約束違規無關; 並且在違反約束后所有投注均已關閉。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM