C 为什么注册变量不能成为全局变量?

C 为什么注册变量不能成为全局变量?,c,global,cpu-registers,micro-optimization,C,Global,Cpu Registers,Micro Optimization,当从一个站点读取数据时,你不能生成寄存器类型的全局变量。为什么会这样? 资料来源: 因为它们在寄存器中。这在术语上是矛盾的。最初,寄存器变量应该存储在处理器寄存器中,但全局变量必须存储在数据或BSS部分中,才能从每个函数访问。如今,编译器并没有严格解释寄存器存储类,因此它主要是出于兼容性原因而保留的。,因为它毫无意义。全局变量在应用程序运行时始终存在。很长一段时间内肯定没有空闲的处理器寄存器;) 理论上,您可以将处理器寄存器分配给全局范围变量-该寄存器只需在程序的整个生命周期内保持分配给该变量即

当从一个站点读取数据时,你不能生成寄存器类型的全局变量。为什么会这样? 资料来源:
因为它们在寄存器中。这在术语上是矛盾的。

最初,寄存器变量应该存储在处理器寄存器中,但全局变量必须存储在数据或BSS部分中,才能从每个函数访问。如今,编译器并没有严格解释
寄存器
存储类,因此它主要是出于兼容性原因而保留的。

,因为它毫无意义。全局变量在应用程序运行时始终存在。很长一段时间内肯定没有空闲的处理器寄存器;)

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


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

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

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


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

C/C++使用的调用约定不使用通用寄存器(80x86 Arch中的EAX、EBX等)来保存参数(但返回值存储在EAX中),因此可以声明类似var的寄存器,从而加快代码的编写速度


如果您要求使其成为全局的,那么您需要为所有代码和所有源代码保留注册。这是不可能的,所以编译器会给您一个错误,或者只是将其作为存储在内存中的常规变量。

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

一元运算符&的操作数 应为功能指示器, []或一元数的结果* 运算符,或指定 不是位域的对象,并且 未随登记册一起声明 存储类说明符

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

总结如下:

  • 否,
    寄存器
    关键字不可用 忽略
  • 是的,它只能用于堆栈 变量,如果您想成为标准一致的

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


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

那么我们现在都同意了吗?我们都看到,将一个全局变量作为一个寄存器变量将是一个非常非常糟糕的主意吗?如果原始的C定义没有禁止它,那可能是因为没有人认为任何人会以这种方式实现它——因为他们不应该特别在CI中这样做SC天


此外:现代优化编译器在决定何时在寄存器中保留变量方面比人类做得更好。如果你的编译器做不到,那么你真的需要一个更好的编译器。

既然全局变量在堆中?-1表示忽略了
register
关键字,这是错误的。