默認情況下,編譯器幾乎總是在堆棧上放置自動生存期的變量(例如int b=0;
)。
例如,如果我與海灣合作委員會這個片段中,這是接近你寫的編譯,但多一點點正確的:
int main()
{
int b = 0;
int i;
for (i = 0; i < 100000; i++) {
b++;
b++;
b++;
b++;
b++;
b++;
b++;
b++;
b++;
b++;
}
return b;
}
我得到以下編譯代碼:
00000000004004b6 <main>:
4004b6: 55 push %rbp
4004b7: 48 89 e5 mov %rsp,%rbp
4004ba: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
4004c1: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp)
4004c8: eb 2c jmp 4004f6 <main+0x40>
4004ca: 83 45 fc 01 addl $0x1,-0x4(%rbp)
4004ce: 83 45 fc 01 addl $0x1,-0x4(%rbp)
4004d2: 83 45 fc 01 addl $0x1,-0x4(%rbp)
4004d6: 83 45 fc 01 addl $0x1,-0x4(%rbp)
4004da: 83 45 fc 01 addl $0x1,-0x4(%rbp)
4004de: 83 45 fc 01 addl $0x1,-0x4(%rbp)
4004e2: 83 45 fc 01 addl $0x1,-0x4(%rbp)
4004e6: 83 45 fc 01 addl $0x1,-0x4(%rbp)
4004ea: 83 45 fc 01 addl $0x1,-0x4(%rbp)
4004ee: 83 45 fc 01 addl $0x1,-0x4(%rbp)
4004f2: 83 45 f8 01 addl $0x1,-0x8(%rbp)
4004f6: 81 7d f8 9f 86 01 00 cmpl $0x1869f,-0x8(%rbp)
4004fd: 7e cb jle 4004ca <main+0x14>
4004ff: 8b 45 fc mov -0x4(%rbp),%eax
400502: 5d pop %rbp
400503: c3 retq
400504: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40050b: 00 00 00
40050e: 66 90 xchg %ax,%ax
請注意0指令,這些指令正在遞增我們的變量,相當於源代碼中的b++
。我們可以看到它在堆棧中(-0x4(%rbp)
),因此這些指令中的每一條都將作爲加載和存儲進行計數。這就是爲什麼你看到這麼多的加載/存儲。
如果您不希望您的變量進入堆疊,您可以啓用優化和希望,編譯器會做正確的事情,也可以通過一個暗示與register
關鍵字,像這樣:
int main()
{
register int b = 0;
int i;
for (i = 0; i < 100000; i++) {
b++;
b++;
b++;
b++;
b++;
b++;
b++;
b++;
b++;
b++;
}
return b;
}
,你會得到下面的編譯代碼:
00000000004004b6 <main>:
4004b6: 55 push %rbp
4004b7: 48 89 e5 mov %rsp,%rbp
4004ba: 53 push %rbx
4004bb: bb 00 00 00 00 mov $0x0,%ebx
4004c0: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%rbp)
4004c7: eb 22 jmp 4004eb <main+0x35>
4004c9: 83 c3 01 add $0x1,%ebx
4004cc: 83 c3 01 add $0x1,%ebx
4004cf: 83 c3 01 add $0x1,%ebx
4004d2: 83 c3 01 add $0x1,%ebx
4004d5: 83 c3 01 add $0x1,%ebx
4004d8: 83 c3 01 add $0x1,%ebx
4004db: 83 c3 01 add $0x1,%ebx
4004de: 83 c3 01 add $0x1,%ebx
4004e1: 83 c3 01 add $0x1,%ebx
4004e4: 83 c3 01 add $0x1,%ebx
4004e7: 83 45 f4 01 addl $0x1,-0xc(%rbp)
4004eb: 81 7d f4 9f 86 01 00 cmpl $0x1869f,-0xc(%rbp)
4004f2: 7e d5 jle 4004c9 <main+0x13>
4004f4: 89 d8 mov %ebx,%eax
4004f6: 5b pop %rbx
4004f7: 5d pop %rbp
4004f8: c3 retq
4004f9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
注意,遞增的說明現在add $0x1,%ebx
,我們可以看到,我們的變量確實存儲在寄存器(此處ebx
),作爲reque STED。
我以爲b是一個局部變量,因此,沒有存儲在內存中,而是存儲在堆棧中或緩存中。爲什麼會發生?
局部變量通常存儲在內存中(在堆棧上)。但是你可以改變這種行爲。隨着我發佈的第二個片段,您會看到更少的內存讀取/寫入操作,因爲b
不再存儲在主內存中,而是存儲在寄存器中。
「只是堆棧」,不在內存中?你的計算機上是否有一個不需要內存的魔術「附加組件」? –
嘗試將'b'更改爲'double'。 –