存储在寄存器中的变量的地址

时间:2013-05-20 03:48:17

标签: c

如果在我的代码中某处,我使用变量的地址(例如,将其传递给其他函数),编译器会自动选择将其存储在内存中吗? (而不是将其存储在寄存器中的可能性)。

否则,如果我要求变量的地址(存储为寄存器)会发生什么?我知道我们不能将变量的地址明确设置为注册(register int c)。

修改

例如,如果我做了类似

的事情
int c = 1;
print("Address of c: %p", &c);

然后这个变量无法存储在寄存器中,不是吗?编译器会自动将其设置为存储在内存中吗?否则(如果它只是存储在寄存器中),屏幕上显示的地址是什么?

3 个答案:

答案 0 :(得分:19)

首先,C标准禁止获取声明为register的变量的地址,就像struct中的位字段一样。

对于非寄存器(“自动”)变量,简短回答是肯定的。优化器最简单的策略是立即溢出其地址被采用的变量。

“溢出”只是寄存器分配文献中的一个术语,意思是“决定放在记忆而不是寄存器中。”

复杂的优化器可以执行别名分析,并且仍然在寄存器中保存一个值,即使它的地址已被占用。只要能够证明结果指针不可能用于更改值,就可以实现这一点。

另一个相关的优化是有效范围分割。这允许变量存储在寄存器中,用于指令范围的一部分,其中它包含有用值(其“有效范围”)并且溢出到其他部分。在这种情况下,溢出的部分将对应于指针可能用于更改变量值的位置。例如:

x = 3;
... lots of computations involving x
if T {
  // SPILL HERE, so store register holding x to memory
  int *p = &x;
  ... lots of computations, perhaps using p to change x
  *p = 2;
  // DONE SPILL HERE, so reload register
  ... more code here not using p to change x.
}
else {
  ... lots of computations involving x.
}

此代码的积极优化器可能会为x分配堆栈位置,但会将其加载到代码顶部的寄存器中,并将其保留在那里,但标记为SPILL的区域除外。该区域将被寄存器存储器存储器和匹配的寄存器负载包围。

答案 1 :(得分:3)

通过获取其地址,您强制编译器将变量放入内存而不是将其优化为寄存器。

这个答案有一些很好的信息:Address of register variable

答案 2 :(得分:0)

编译器必须非常小心优化指针,因为任何人都可以在幕后更改它们。这就是优化像restrict这样的关键字的原因(告诉编译器在任何地方都没有其他指针副本)。所以一般情况下你不会有你描述的情况。