咱們知道,棧做爲一種數據結構,是一種只能在一端進行插入和刪除操做的特殊線性表。它按照後進先出的原則存儲數據,先進入的數據被壓入棧底,最後的數據在棧頂,須要讀數據的時候從棧頂開始彈出數據(最後一個數據被第一個讀出來)。 數據結構
C++函數內的參數和局部變量都是存放在棧空間內,那麼具體是如何存放和利用的呢?讓咱們來一探究竟。 app
有以下測試代碼: 函數
void func(){ int a; char b; double c; a=97; b=a; c=7.2; } int main(int argc,char *argv[]) { //call func func(); return 0; }func函數內有三個類型不相同的變量a,b,c 而後對a,b,c分別賦值。
對應的彙編碼大體以下: 測試
void func(){ 00B013D0 push ebp 00B013D1 mov ebp,esp 00B013D3 sub esp,0E8h 00B013D9 push ebx 00B013DA push esi 00B013DB push edi 00B013DC lea edi,[ebp+FFFFFF18h] 00B013E2 mov ecx,3Ah 00B013E7 mov eax,0CCCCCCCCh 00B013EC rep stos dword ptr es:[edi] //上面的指令意思一樣是分配棧空間,只不過大小變成了3A*4=E8(232)字節 //若是沒有這三個局部變量和參數,那麼分配的空間應該是192字節,232-192=40, //也就是說多分配了40字節 int a; char b; double c; //a,b,c在棧中的位置以下圖所示,從彙編也能夠看到: //&a = ebp-8h //&b = ebp-11h //&c = ebp-24h //好像並非想像中的那樣相鄰存放的,可是依然符合棧的存放特色:從高地址往低地址 a=97; 00B013EE mov dword ptr [ebp-8],61h b=a; 00B013F5 mov al,byte ptr [ebp-8] 00B013F8 mov byte ptr [ebp-11h],al c=7.2; //這裏存7.2的時候是從前面某個內存區域經過雙字傳送指令實現的, //C語言中7.2默認是double(64位8字節)是一個32位寄存器存放不了的, //所以須要在編譯期先放到內存裏面,而後拷貝到棧內 00B013FB movsd xmm0,mmword ptr ds:[00B058A8h] 00B01403 movsd mmword ptr [ebp-24h],xmm0 } 00B01408 pop edi 00B01409 pop esi 00B0140A pop ebx 00B0140B mov esp,ebp 00B0140D pop ebp 00B0140E ret --- 無源文件 ----------------------------------------------------------------------- 00B0140F int 3 00B01410 int 3 00B01411 int 3 00B01412 int 3 00B01413 int 3 00B01414 int 3 00B01415 int 3 00B01416 int 3 00B01417 int 3 00B01418 int 3 00B01419 int 3 00B0141A int 3 00B0141B int 3 00B0141C int 3 00B0141D int 3 00B0141E int 3 00B0141F int 3 00B01420 int 3 00B01421 int 3 00B01422 int 3 00B01423 int 3 00B01424 int 3 00B01425 int 3 00B01426 int 3 00B01427 int 3 00B01428 int 3 00B01429 int 3 00B0142A int 3 00B0142B int 3 00B0142C int 3 00B0142D int 3 00B0142E int 3 00B0142F int 3 --- f:\cpp\clr\consoleapplication1\源.cpp --------------------------------------- int main(int argc,char *argv[]) { 00B01430 push ebp 00B01431 mov ebp,esp 00B01433 sub esp,0C0h 00B01439 push ebx 00B0143A push esi 00B0143B push edi 00B0143C lea edi,[ebp+FFFFFF40h] 00B01442 mov ecx,30h 00B01447 mov eax,0CCCCCCCCh 00B0144C rep stos dword ptr es:[edi] //call func func(); 00B0144E call 00B01082 return 0; 00B01453 xor eax,eax } 00B01455 pop edi 00B01456 pop esi 00B01457 pop ebx 00B01458 add esp,0C0h 00B0145E cmp ebp,esp 00B01460 call 00B01140 00B01465 mov esp,ebp 00B01467 pop ebp 00B01468 ret
func函數棧區內存分佈: 編碼
其中紅框部分是變量a被賦值以前, code
如今a被賦值爲十進制的97,換成16進制就是 0x0000 0061,和下圖一致,注意存放規則!
高八位存0000,低八位存0061 內存
如今a,b,c都被賦值: io
能夠看到佔用狀況: console
a是int 佔4字節;b是char佔1字節;c是double佔8字節;且a,b,c並未連續存放 編譯