说你做: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