c++中的常量摺疊

何謂常量摺疊?
常量摺疊就是將常量表達式計算求值,並用求得的值來替換表達式,放入常量表。可以算作一種編譯優化。(預編譯階段)

接下來我們通過一段代碼來分析一下了解一下常量摺疊及其特性:

int main()
{
    const int a = 10;
    int b = 2*a;
    int c = b;
    int *p = (int*)&a;
    *p = 100;
    cout << a << endl;//輸出10
    cout<< *p<<endl;//輸出100
    return 0;
}

1 編譯器會爲該常量在棧上分配一塊空間。

const int a = 10;
0099446E  mov         dword ptr [a],0Ah  

a是一個常量,按理說常量是存儲在代碼段的,可通過反彙編可以清楚地看到編譯器確實爲a在棧上分配了一塊空間。
在這一點上const常量和宏是有區別的,宏在預編譯階段就完成了替換,編譯器並不會爲宏分配空間。

2 代碼中遇上a的地方,直接替換爲a的值
下面我們來比較一下常量摺疊和正常變量的賦值

    int b = 2*a;//常量摺疊賦值
00994475  mov     dword ptr [b],14h//真正的實現形式是int b=2*10  
    int c = b;//正常變量賦值
0099447C  mov     eax,dword ptr [b]//藉助寄存器eax把b的值傳遞給c  
0099447F  mov     dword ptr [c],eax

3
大家是否對上面代碼中最後的輸出結果有疑惑?
指針p指向a在棧上的空間,而且明明通過*p=100對該空間上的內容作出了改變,爲什麼輸出的a依舊是10呢?
話不多說,我們來看反彙編:

    int *p = (int*)&a;
00994482  lea         eax,[a]  //通過寄存器eax把a的地址給指針p
00994485  mov         dword ptr [p],eax  
    *p = 100;
00994488  mov         eax,dword ptr [p]  
0099448B  mov         dword ptr [eax],64h//修改p指向的空間的內容 
    cout << a << endl;
00994491  mov         esi,esp  
00994493  push        99149Ch  
00994498  mov         edi,esp  
0099449A  push        0Ah//出現a的地方直接用10代替  
0099449C  mov         ecx,dword ptr ds:[9A00ECh]  
009944A2  call        dword ptr ds:[9A0094h]  
009944A8  cmp         edi,esp  
009944AA  call        __RTC_CheckEsp (0991325h)  
009944AF  mov         ecx,eax  
009944B1  call        dword ptr ds:[9A00F4h]  
009944B7  cmp         esi,esp  
009944B9  call        __RTC_CheckEsp (0991325h)  

從上面的彙編代碼中可以看到,a所在地址上的內容確實已經被p所修改,a的值已被改變,但是在輸出a的時候,編譯器輸出的並不是該空間上的內容,而是直接用10替換了。

發佈了49 篇原創文章 · 獲贊 11 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章