gcc編譯器優化給咱們帶來的麻煩???

今天看到一個頗有趣的程序,以下:優化

int main()
{
    const int a = 1;
    int *b = (int*)&a;
    *b = 21;

    printf("%d, %d", a, *b);
    return 0;
}

當我第一眼看到這個程序的時候,我想固然的認爲輸出結果是21, 21,可是我錯了blog

一時很難理解,因而我又輸出了它們的地址:內存

int main()
{
    const int a = 1;
    int *b = (int*)&a;
    *b = 21;

    printf("%d, %d", a, *b);
    printf("\n%p, %p", &a, &*b);
    return 0;
}

它們的地址是同樣的,看到這裏我更加的不解,因而我試着查看一下彙編代碼。編譯器

int main()
{
    const int a = 1;
    int *b = (int*)&a;
    *b = 21;

    printf("%d", a);
    return 0;
}

 對應彙編代碼以下:編譯

這裏獲得的是at&t的彙編代碼,與intel不一樣之處在於:class

1,指令格式爲:指令名稱 元操做數 目的操做數變量

2,寄存器前加%引用

3,操做數前加$程序

4,0x4(%esp)爲內存尋址,實際表示的是esp寄存器中的內容 + 4(若是不是很明白,望自行查找資料,本人知識有限)im

咱們首先看標號爲1的行,對應c語句爲const int a =1,這是把1放進地址爲0x18(%esp)的地方,再來看標號2的地方,對應的printf語句,發現並無引用地址爲0x18(%esp)的地方的值,而是把1直接放到了0x4(%esp),而後輸出。

因此我的認爲,之因此會出現最開始的結果,是由於編譯器給咱們作了一些優化致使的。爲了證實個人觀點,我修改了程序:

int main()
{
    int c = 1;
    const int a = c;
    int *b = (int*)&a;
    *b = 21;

    printf("%d, %d", a, *b);
    return 0;
}

 輸出結果爲:

對應的彙編代碼爲:

在標號1處,咱們能夠肯定a存放在0x14(%esp)的地方,在標號2處,對應的printf語句,此語句從右向左處理參數,2處理的是*b,3處理的是a,這時看到用的是地址,而不是直接用數值,同時看標號0處,咱們是將c賦值1,再給a賦值時編譯器用的是數值,並無引用地址。

因此,我的猜想,編譯器在這方面有一個優化功能:若是一個變量在定義時賦值常量,那麼在引用它的時候,編譯器會直接用該常量數值代替地址的引用來節省時間,可是也給咱們帶來了之外的麻煩。

這些都是我的的觀點,但願各位指教!!!

相關文章
相關標籤/搜索