如果在我的代码中某处,我使用变量的地址(例如,将其传递给其他函数),编译器会自动选择将其存储在内存中吗? (而不是将其存储在寄存器中的可能性)。
否则,如果我要求变量的地址(存储为寄存器)会发生什么?我知道我们不能将变量的地址明确设置为注册(register int c
)。
修改:
例如,如果我做了类似
的事情int c = 1;
print("Address of c: %p", &c);
然后这个变量无法存储在寄存器中,不是吗?编译器会自动将其设置为存储在内存中吗?否则(如果它只是存储在寄存器中),屏幕上显示的地址是什么?
答案 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
这样的关键字的原因(告诉编译器在任何地方都没有其他指针副本)。所以一般情况下你不会有你描述的情况。