最近在面试中被问到以下几个问题:谁实际决定寄存器变量将存储在哪里(RAM或寄存器)。
我在谷歌上搜索过,然后我得到了编译器的决定。但是编译器如何决定呢?根据我的理解,这应该在运行时决定。
如果我们在不同的机器上编译和运行程序,那么编译器如何决定在哪里存储寄存器的存储类值
register
存储类说明符是对编译器的一个提示,对变量的访问应该"尽可能快",这意味着(在寄存器体系结构上)它的存储应该分配给寄存器。这禁止了一些事情,比如获取变量寄存器的地址——寄存器没有地址。然而,编译器可以自由地忽略这个提示(§6.7.1¶5):
使用存储类说明符
register
声明对象的标识符表明对该对象的访问尽可能快。这些建议的有效程度是由实现定义的。
编译代码时,编译器必须选择如何将局部变量和算术运算映射到CPU寄存器和堆栈内存上的操作。这被称为寄存器分配;这些决定是在编译时做出的,并被写入函数的编译代码中。
假设我们有一个非常naïve的编译器,它完全按照我们说的做,不优化任何东西。如果我们给它这样的代码:
int x;
x = 2;
x += 5;
在x86机器上,我们可以看到这样的输出:
sub esp, 4 ; allocate stack space for an integer
mov dword [esp], 2
add dword [esp], 5
但是如果我们写:
register int x;
x = 2;
x += 5;
那么我们可能会看到:
mov eax, 2
add eax, 5
后者更有效,因为它更喜欢寄存器访问而不是内存访问。在实践中,现代编译器具有智能寄存器分配算法,使得该存储类说明符不再需要。
编译器在编译期间进行了几种类型的优化,并根据这些优化,授予或拒绝请求。
编译的最后第三阶段——中间代码生成保持生成中间三地址(操作码)的基础编码,在最后的第二阶段进一步优化compiler-optimisation。编译器的最后一个阶段——
target code generation
保证寄存器是否存储类变量是否被授予寄存器
授予对变量的寄存器访问权的请求是由程序发出的,但是,最终是由编译器决定变量在寄存器中的内存分配,这取决于:-
-
CPU中寄存器的可用性。
-
更稳定的优化等