最近我在接受采访时被问到以下问题: 谁实际上决定寄存器变量将存储在哪里(在RAM或寄存器中)。
我在google上搜索过,我得到了编译器的决定权。 但编译器如何决定?应根据我的理解在运行时决定。
如果我们在不同的机器上编译运行程序,那么编译器如何决定存储寄存器存储类值的位置。
答案 0 :(得分:3)
register
存储类说明符是编译器的提示,访问变量应该“尽可能快”,这意味着(在寄存器体系结构上)应该将其存储分配给寄存器。这禁止了一些事情,比如取变量寄存器的地址没有地址。但是,编译器可以自由地忽略这个提示(§6.7.1¶5):
具有存储类说明符
register
的对象的标识符声明建议尽可能快地访问对象。这些建议有效的程度是实施定义的。
编译代码时,编译器必须选择如何将局部变量和算术运算映射到CPU寄存器和堆栈存储器上的操作。这称为寄存器分配;这些决定是在编译时完成的,并且被编入函数的编译代码中。
假设我们有一个非常天真的编译器,它正是我们所说的,并没有优化任何东西。如果我们给它这个代码:
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
后者更有效,因为它更喜欢通过内存访问进行寄存器访问。在实践中,当代编译器具有智能寄存器分配算法,这使得该存储类说明符不必要。
答案 1 :(得分:1)
编译器在编译期间进行了几种类型的优化,并且根据这些优化,请求被授予或拒绝。
编译的第三个阶段---中间代码生成保持生成基于中间三地址(操作码)的基础 编码,在第二个最后阶段进一步优化 编译器的优化。编译器的最后阶段---
target code generation
使得它保证了寄存器是否存储 类变量将被授予注册表。
授予寄存器访问变量的请求由程序完成,但最后,编译器根据以下内容决定寄存器中变量存储器的分配: -
CPU中寄存器的可用性。
更稳定的优化等。