4

最近我在一次采访中被问到 Q:谁真正决定寄存器变量将存储在哪里(在 RAM 或寄存器中)。

我在谷歌上搜索过,我得到了那个编译器的答案。但是编译器如何决定呢?根据我的理解,它应该在运行时决定。

如果我们在不同的机器上编译和运行程序,那么编译器如何决定将寄存器存储类值存储在哪里。

4

2 回答 2

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

后者更有效,因为它更喜欢寄存器访​​问而不是内存访问。在实践中,当代编译器具有智能寄存器分配算法,使得这个存储类说明符变得不必要。

于 2015-05-18T06:23:29.577 回答
1

编译器在编译期间进行了几种类型的优化,根据这些优化,请求被批准或拒绝。

编译的倒数第三阶段——中间代码生成保持生成基于中间三地址(操作码)编码的基础,在编译器优化的倒数第二阶段进一步优化。编译器的最后阶段---target code generation保证寄存器存储类变量是否被授予寄存器。

授予对变量的寄存器访问权限的请求是由程序发出的,但最终,编译器根据以下条件决定寄存器中变量的内存分配:-

  1. CPU 中寄存器的可用性。

  2. 更稳定的优化等

于 2015-05-18T06:21:30.527 回答