最近我在接受采访时被问及全局寄存器变量。我搞砸了说任何全局变量都将存储在数据段中。但后来我被问及GCC。在采访后我得出结论gcc支持全局寄存器变量
#include<stdio.h>
register int var asm("ebx"); //storing global variable in register explicitly
int main(void)
{
.......
}
这是链接 https://gcc.gnu.org/onlinedocs/gcc/Global-Reg-Vars.html#Global-Reg-Vars
但现在我对它的生命周期和范围感到困惑,以及它是作为普通的全局变量还是作为寄存器变量工作?还有任何方法或gcc上的命令,以便我们确保编译器不会简单地忽略register
关键字并将存储在实际的寄存器中吗?
答案 0 :(得分:5)
正如许多人所指出的那样,在全球范围内保留注册通常是一个坏主意。我相信这里的原始意图是(来自docs):
这在编程语言等程序中可能很有用 具有几个被访问的全局变量的解释器 经常。
这是否真的有用,或者只是让事情变得更糟可能只能针对特定情况来确定。在您的情况下(面试问题),这并不重要。
像这样的声明的范围就是看到声明的所有内容,正如您对任何全局声明所期望的那样。
然而,实施有点棘手。再次引用文档:
在某个寄存器储备中定义全局寄存器变量 完全注册用于此用途,至少在当前 汇编即可。该登记册不会被分配用于任何其他目的 当前编译中的函数,并没有保存和 通过这些功能恢复。
因此,使用该声明进行COMPILED的所有代码都将保留该用途的寄存器。但是,如果您链接到未使用此预留编译的其他代码,则不会将其保留用于此目的。
文档为qsort提供了一个很好的例子。如果您的代码是使用此声明编译的,然后它从c运行时调用qsort(可能是没有使用此声明编译),然后qsort调用回代码(对于compare函数),回调可以& #39;在调用比较函数之前,请确保qsort没有踩踏寄存器。
如果调用任何库函数可以踩踏寄存器,它怎么能工作?再次来自文档:
选择通常按功能保存和恢复的寄存器 在您的机器上调用,以便库例程不会破坏它。
即便如此:
从信号中访问全局寄存器变量是不安全的 处理程序,或来自多个控制线程,因为系统 库例程可以暂时使用寄存器来执行其他操作 (除非你专门针对手头的任务重新编译它们。)
至于问题的最后部分:
编译器不会简单地忽略register关键字并将存储在 实际登记册
我不确定你的意思。如果(某种程度上)编译器忽略了asm("ebx")
,那么它将不会存储在寄存器中。使用它的关键是确保var
存储在实际的ebx寄存器中。