为什么无法将变量注册为全局变量?

时间:2010-08-15 08:30:31

标签: c

从某个网站读取时,您无法创建类型为register的全局变量。为什么会这样? 资源: http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlcpp8l.doc/language/ref/regdef.htm

9 个答案:

答案 0 :(得分:20)

theory 中,您可以将处理器寄存器分配给全局范围变量 - 该寄存器只需在程序的整个生命周期内保持分配给该变量。

然而,C编译器通常不会在编译阶段看到整个程序 - 编写C标准以便每个翻译单元(大致对应于每个.c文件)可以独立于其他编译(编译后的对象随后链接到程序中)。这就是为什么不允许全局范围寄存器变量 - 当编译器正在编译b.c时,它无法知道在a.c中有一个全局变量分配给寄存器(因此函数在b.c中必须保留该寄存器中的值。)

答案 1 :(得分:10)

实际上,GCC允许这样做。全球范围内的声明,格式为:

register int foo asm ("r12");

为全局“foo”分配寄存器“r12”(在x86_64上)。这有许多限制,相应的手册页可能是所有麻烦的全局寄存器变量的最佳参考:

答案 2 :(得分:5)

因为它会毫无意义。应用程序工作时始终存在全局变量。肯定没有免费的处理器注册这么长时间;)

答案 3 :(得分:2)

最初,寄存器变量应存储在处理器寄存器中,但全局变量必须存储在数据或BSS部分中,以便可从每个函数访问。今天,编译器没有严格解释register存储类,因此主要是出于兼容性原因。

答案 4 :(得分:2)

register关键字的含义与其名称似乎表示的含义不同,现在它与处理环境的寄存器没什么关系。 (尽管可能曾经为此选择了一次。)唯一限制使用register声明的变量的文本是

  

一元&的操作数操作者   应该是一个功能指示符,   []或一元*的结果   运算符,或指定的左值   一个不是位字段的对象   未与登记册一起申报   存储类说明符

因此它对自动变量(在函数中声明的变量)实现了限制,因此获取此类变量的地址是错误的。接下来的想法是,编译器可以以任何方式表示此变量,作为寄存器或立即汇编器值等。作为程序员,您承诺不会获取它的地址。通常这对全局变量没有多大意义(无论如何,它们都有一个地址)。

总结:

  • 不,register关键字不是 忽略。
  • 是的,它只能用于堆栈 变量,如果你想成为标准符合

答案 5 :(得分:1)

寄存器字在C / C ++中用作编译器使用处理器变量寄存器的请求。寄存器是CPU使用的一种变量,访问速度非常快,因为它不在内存(RAM)中。寄存器的使用受到体系结构和寄存器本身大小的限制(这意味着一些可能就像内存指针一样,其他的则是加载特殊的调试值等等)。

C / C ++使用的调用约定不使用通用寄存器(80x86 Arch中的EAX,EBX等)来保存参数(但是返回的值存储在EAX中),所以你可以声明var这样的寄存器使代码更快。

如果您要求将其设为全局,则要求为所有代码和所有来源保留注册表。这是不可能的,因此编译器会给你一个错误,或者只是让它成为存储在内存中的常用var。

答案 6 :(得分:0)

有些编译器提供了一种将寄存器永久地专用于变量的方法。但是,register关键字不足。编译器决定为寄存器中的例程分配局部变量通常不需要与其他源模块中的任何内容进行协调(虽然一些开发系统在例程之间注册优化,但更简单地定义调用约定以便所有例程都是允许自由更改某些寄存器(因此调用者负责在函数调用后需要时保存内容)但不得更改其他寄存器(因此,如果需要寄存器,则调用的例程负责保存和恢复内容)因此,链接器不需要关注寄存器的使用。

这种方法适用于本地寄存器变量,但对于全局寄存变量则无用。要使全局寄存器变量有用,程序员通常必须告诉编译器哪个寄存器用于哪个变量,并确保在编译所有模块时编译器知道这些保留 - 即使那些不使用否则注册。这在嵌入式系统中很有用,特别是对于中断使用的变量,但系统中允许的变量数量通常非常有限(例如2个左右)。

答案 7 :(得分:0)

那么我们现在都同意吗?我们都看到将全局变量作为寄存器变量会是一个非常非常糟糕的想法吗?如果最初的C定义没有禁止它,那可能是因为没有人认为任何人会以这种方式实际实现它 - 因为他们不应该特别回到CISC时代。

此外:现代优化编译器可以更好地决定何时将变量保存在寄存器中,而不是人类可以做到的。如果你不能这样做,那么你真的,真的需要一个更好的编译器。

答案 8 :(得分:-3)

因为他们在寄存器中。这是一个矛盾。