gcc中的全局寄存器变量

gcc中的全局寄存器变量,c,gcc,C,Gcc,最近,我在一次采访中被问及全局寄存器变量。我把所有全局变量都存储在数据段中的说法搞砸了。但后来我被问及GCC。在采访后,我得出结论,GCC支持全局寄存器变量 #include<stdio.h> register int var asm("ebx"); //storing global variable in register explicitly int main(void) { ....... } #包括 寄存器int var asm(“ebx”)//在寄存器中显式存储全局

最近,我在一次采访中被问及全局寄存器变量。我把所有全局变量都存储在数据段中的说法搞砸了。但后来我被问及GCC。在采访后,我得出结论,GCC支持全局寄存器变量

#include<stdio.h>

register int var asm("ebx");  //storing global variable in register explicitly

int main(void)
{
.......
}
#包括
寄存器int var asm(“ebx”)//在寄存器中显式存储全局变量
内部主(空)
{
.......
}
这里是链接


但现在我对它的生存期和作用域感到困惑,以及它是作为普通全局变量还是作为寄存器变量工作?另外,gcc上是否有任何方法或一些命令,以便我们确保编译器不会简单地忽略
register
关键字并将其存储在实际的register中?

正如许多人指出的那样,全局保留寄存器通常是个坏主意。我相信这里的初衷是(来自:

这在诸如编程语言之类的程序中可能很有用 具有可访问的两个全局变量的解释器 经常

这是否真的有用,或者只是让事情变得更糟,可能只能在特定情况下确定。在你的情况下(面试问题),这并不重要

像这样的声明的范围是看到该声明的所有内容,正如您对任何全局声明所期望的那样

然而,实现有点棘手。再次引用文件:

在特定寄存器中定义全局寄存器变量 完全注册用于此用途,至少在当前 编译。登记册不分配用于任何其他目的 当前编译中的函数,并且不会保存和 由这些功能恢复

因此,使用该声明编译的所有代码都将保留用于该用途的寄存器。但是,如果您链接到未使用此保留编译的其他代码,则不会为此目的保留该代码

这些文档提供了一个关于qsort的极好示例。如果您的代码是使用此声明编译的,然后它从c运行时调用qsort(可能不是使用此声明编译的),然后qsort调用回您的代码(对于比较函数),那么回调函数无法确保qsort在调用比较函数之前没有踩到寄存器上

如果调用任何库函数都会在寄存器上跺脚,那么这怎么可能起作用呢?再次从文档中:

选择一个通常按功能保存和恢复的寄存器 在您的计算机上调用,以便库例程不会破坏它

即便如此:

从信号访问全局寄存器变量是不安全的 处理程序,或来自多个控制线程,因为系统 库例程可能会暂时将寄存器用于其他用途 (除非您专门为手头的任务重新编译它们)

关于你问题的最后一部分:

编译器不会简单地忽略register关键字,而是存储在 实际寄存器


我不知道你的意思。如果(不知何故)编译器忽略了
asm(“ebx”)
,那么它将不会存储在寄存器中。使用此功能的全部目的是确保
var
存储在实际的ebx寄存器中。

您不能通过调试器尝试一下吗?@MrSykkox:您能帮我解决这个问题吗?你能回答我的第一个问题吗?我会很感激的。我不确定这一生会是什么样子,但我想测试一下。如果您使用的是gdb(-ggdb),则使用调试标志(-g)进行编译。在主代码集中,var=something。在退出前设置断点。并打印寄存器值(info register ebx)。C并不是盲从C++,而是写在墙上。不要在C中使用
auto
;不要在新的C代码中使用
register
(您可以在旧的C代码中非常安全地删除它)。对全局变量使用
register
会将您绑定到特定的C编译器,并且基本上没有任何好处。记住,
register
是对编译器的提示,而不是命令;编译器可以根据您的提示随心所欲。使用
register
确实会阻止您获取变量的地址,但仅此而已。如果您的面试官试图用有关奇怪的gcc扩展的问题来欺骗您,那么您可能无论如何都不想与这些人合作!