說你做:CPU如何知道任何變量的地址?
void something()
{
int* number = new int(16);
int* sixteen = number;
}
怎樣的CPU知道我要分配給十六地址?
謝謝
說你做:CPU如何知道任何變量的地址?
void something()
{
int* number = new int(16);
int* sixteen = number;
}
怎樣的CPU知道我要分配給十六地址?
謝謝
在示例代碼中沒有什麼魔力。就拿這個片段中,例如:
int x = 5;
int y = x;
你使用指針的代碼是完全一樣的 - 電腦並不需要知道任何神奇的信息,它只是複製無論在number
到sixteen
。
至於下方您的評論:
但它是如何知道X或Y是在內存中。如果我要求將x複製到y中,它是如何知道其中哪一個是。
在實踐中,大多數機器上,這些天,大概都沒有會在內存中,他們將在寄存器中。但是,如果它們在內存中,那麼是的,編譯器會發出代碼來根據需要跟蹤所有這些地址。在這種情況下,它們將在堆棧中,所以機器代碼將訪問堆棧指針寄存器,並用一些編譯器決定的偏移量來引用它,這些偏移量指向每個特定變量的存儲量。
下面是一個例子。這個簡單的功能:
int f(void)
{
int x = 5;
int y = x;
return y;
}
當鐺並沒有優化編譯,讓我在我的機器上輸出如下:
_f:
pushq %rbp ; save caller's base pointer
movq %rsp,%rbp ; copy stack pointer into base pointer
movl $5,0xfc(%rbp) ; store constant 5 to stack at rbp-4
movl 0xfc(%rbp),%eax ; copy value at rbp-4 to register eax
movl %eax,0xf8(%rbp) ; copy value from eax to stack at rbp-8
movl 0xf8(%rbp),%eax ; copy value off stack to return value register eax
popq %rbp ; restore caller's base pointer
ret ; return from function
我加了一些註釋來解釋所生成的代碼的每一行呢。重要的是要看到堆棧中有兩個變量 - 一個是0xf8(%rbp)
(或rbp-8
更清晰),另一個是0xfc(%rbp)
(或rbp-4
)。基本算法就像原始代碼所示 - 常量5
被保存到x
的rbp-4
,然後該值被複制到y
在rbp-8
。
「但是堆棧來自哪裏??你可能會問。不過,這個問題的答案是依賴於操作系統和編譯器。在您的程序的main
函數被調用之前,這一切都已設置完畢,同時您的操作系統需要其他運行時設置。
CPU知道,因爲你的程序告訴它。這裏的魔力在編譯器中。首先,我在Visual Studio中建立這個節目2010年
這是生成(在調試模式)的拆卸:
void something()
{
003A13C0 push ebp
003A13C1 mov ebp,esp
003A13C3 sub esp,0E8h
003A13C9 push ebx
003A13CA push esi
003A13CB push edi
003A13CC lea edi,[ebp-0E8h]
003A13D2 mov ecx,3Ah
003A13D7 mov eax,0CCCCCCCCh
003A13DC rep stos dword ptr es:[edi]
int* number = new int(16);
003A13DE push 4
003A13E0 call operator new (3A1186h)
調用new運算符,EAX = 00097C58
之後是地址的內存管理器決定給我這個程序的運行。這是每當您解除引用號碼時將使用的地址。
003A13E5 add esp,4
003A13E8 mov dword ptr [ebp-0E0h],eax
003A13EE cmp dword ptr [ebp-0E0h],0
003A13F5 je something+51h (3A1411h)
003A13F7 mov eax,dword ptr [ebp-0E0h]
003A13FD mov dword ptr [eax],10h
003A1403 mov ecx,dword ptr [ebp-0E0h]
003A1409 mov dword ptr [ebp-0E8h],ecx
003A140F jmp something+5Bh (3A141Bh)
003A1411 mov dword ptr [ebp-0E8h],0
003A141B mov edx,dword ptr [ebp-0E8h]
003A1421 mov dword ptr [number],edx
int* sixteen = number;
003A1424 mov eax,dword ptr [number]
003A1427 mov dword ptr [sixteen],eax
在這裏,你只是確保十六個值是與數字相同的值。所以現在他們指向相同的地址。
}
您可以通過在局部變量調試窗口中檢查他們覈實:
+ number 0x00097c58 int *
+ sixteen 0x00097c58 int *
你可以做這個實驗,並通過拆卸步驟。它通常非常有啓發性。
我不知道你想知道什麼。但是,可能足以說C代碼被轉換爲機器代碼,該代碼準確地告訴CPU確切的位置。 – 2012-01-02 22:27:47
你真的在問一個問題的答案是「因爲編譯器在變量'number'中有地址嗎?」。只要確保我理解了這個問題...... – 2012-01-02 22:29:03
你的問題很混亂,因爲答案是「對於int int = 5; int five = number;'」的相同方式。除了'number'從哪裏獲得初始值,這些都是完全相同的。那麼,你是在問'new int(16)'從哪裏得到一個指針? – 2012-01-02 22:29:33