程序中的陣列打破程序引數對齊。有以下代碼:
void _func(unsigned long cnt, int* adr, ...){
char a[1];
printf("cnt: %p, adr: %p\n", &cnt, &adr);
}
int main(void){
_func(0, (int*)1, 2, 3, 4, 5);
return 0;
}
...編譯為
gcc -m32 -O0 main.c
它輸出這個:
cnt: 0xff911960, adr: 0xff91193c
這是 36 (0x24) 位元組的差異。問題是為什么會這樣?不是應該sizeof(cnt)嗎?
但是如果我洗掉char a[1]或添加-O2標志,差異將是 4 個位元組(像往常一樣)。
是什么導致了這種行為?
PS:在編譯器資源管理器網站上,偏移量一直是 4 個位元組。
uj5u.com熱心網友回復:
&cnt和&adr是引數的地址。引數是函式的區域變數,初始化為呼叫者傳遞的引數值。編譯器不需要為用于傳遞引數的引數使用相同的空間。
當引數在堆疊上傳遞時,編譯器可能會或可能不會將其堆疊空間用于引數。當引數傳入處理器暫存器并且需要地址時,因為程式獲取地址并列印它,那么編譯器必須在堆疊上為引數保留空間,將值從暫存器復制到堆疊空間(與存盤指令一樣),并使用堆疊空間的地址。
當編譯器為此布局堆疊空間時,它不需要關心它cnt并且adr是連續的引數。它可以組織有關它需要的所有堆疊空間的資料——用于引數、區域變數、回傳地址、用于它自己的目的等等——然后以任何順序為這些東西分配堆疊空間。因此,您不應期望 和 的地址之間存在任何密切cnt關系adr。
(對于具有可變引數的函式,編譯器需要以某種方式實作可變引數串列功能。這通常涉及在最后一個固定引數之后的記憶體中連續的可變引數,這將adr在示例中。這不會在cnt和之間強加任何關系adr.)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/484007.html
