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