“register”存储类最初是提示编译器,限定的变量使用频率很高,将其值保留在内存中会影响性能。绝大多数CPU架构(也许不包括SPARC?甚至没有反例)不能在两个变量之间执行任何操作,而不先将其中一个或两个从内存加载到其寄存器中。从内存加载变量到寄存器中,并在进行操作后写回到内存中,所需的CPU周期比操作本身多得多。因此,如果一个变量经常被使用,通过为其设置一个寄存器并完全不使用内存,可以获得性能提升。
然而,这样做有各种要求。每个CPU架构的要求都不同:
- 所有处理器都有固定数量的寄存器,但每个处理器型号的数量不同。在80年代,您可能只有4个可以合理用于“register”类型变量。
- 大多数处理器不支持在每个指令中使用每个寄存器。在80年代,通常只有一个寄存器可用于加法和减法,您可能无法将该寄存器用作指针。
- 调用约定规定了可以预期被子程序覆盖的不同寄存器集,即函数调用。
- 寄存器的大小因处理器而异,因此存在一些情况下“register”类型变量将不适合寄存器。
由于C旨在独立于平台,因此无法通过标准来强制执行这些限制。换句话说,尽管可能无法编译具有20个“register”变量的过程,但C程序本身不应该是“错误”的,因为没有逻辑原因可以解释机器不能拥有20个寄存器。因此,“register”存储类始终只是一个提示,如果特定的目标平台不支持它,则编译器可以忽略它。
无法引用寄存器是不同的。寄存器明确地没有在内存中保持更新,并且如果对内存进行更改,则不会保持当前状态;这就是存储类的全部意义。由于它们不打算在内存中具有保证的表示形式,因此它们在内存中没有逻辑上有意义的地址,这些地址可能对于可能获得指针的外部代码是有意义的。寄存器对于其自己的CPU没有地址,它们几乎永远没有任何协处理器可以访问的地址。因此,任何试图获取对“register”类型变量的引用的尝试都是错误的。 C标准可以轻松地强制执行此规则。
然而,随着计算机的发展,一些趋势出现,削弱了“register”存储类本身的目的。
处理器现在拥有更多的寄存器,今天您可能至少有16个寄存器,并且它们可以在大多数情况下互换使用。多核处理器和分布式代码执行已变得非常普遍;只有一个核心可以访问任何一个寄存器,而且它们绝不会共享,除非涉及内存。为变量分配寄存器的算法变得非常有效。
事实上,编译器现在非常擅长将变量分配到寄存器中,它们通常比任何人都能更好地进行优化。它们肯定知道哪些变量是最频繁使用的,而无需告诉它们。如果编译器被要求遵守手动输入的“register”提示,则生成这些优化将更加复杂(即不适用于标准或程序员)。编译器忽略这些提示已成为一种普遍现象。当C++存在时,它已经过时。它包含在标准中以保持C ++尽可能接近C的真正超集。遵守提示的要求,以及强制提示可以被遵守的条件的要求相应减弱。今天,这种存储类本身已经被弃用。
因此,即使今天(直到计算机甚至没有寄存器)您仍然不能逻辑上引用CPU寄存器,但是标准要求编译器遵守“register”存储类已经非常过时,因此要求编译器要求您在使用它时合乎逻辑是不合理的。
register
是 C++ 中的一个提示,编译器可以忽略它。如果您获取它的地址,编译器也会忽略它。 - Jean-Baptiste Yunès