我读到 gcc 提供了将全局变量定义为寄存器存储变量的支持。我想知道的是标准是否有任何关于这种支持的规范。
5 回答
有一个普遍的误解,认为 C 的关键字register
谈论的是硬件寄存器。这可能是该概念的起源,但在现代 C 中,这不是目的。唯一真正的影响register
是,&
在这样的野兽上是不允许的。
它们可以以编译器想要的任何方式实现,硬件寄存器,指令立即数,或者在堆栈上,你不会知道。您所知道的是,一个register
变量不能与其他变量别名。
为了更直接地回答您的问题,register
文件范围内的 no 不是 C 语言的一部分。如果是这样,那将允许我们声明register const
几乎任何基数的变量,这可以用作某种全局常量。
将硬件寄存器映射到特定变量是编译器提供的扩展,例如 gcc。Gcc 的功能,作为一个扩展,也适用于文件范围。但这是非常令人望而却步的,因为通常 CPU 没有很多硬件寄存器可供备用。
register
不能用于全局变量。C11 6.9/2 涵盖了这一点:
约束
存储类说明符
auto
和register
不应出现在外部声明的声明说明符中。
在这里,外部声明是指不在函数内的任何声明。(不要与extern
或外部链接混淆)。
C99 或 C11 标准不支持或不允许全局寄存器变量(请参阅Sourav Ghosh或Matt McNabb 的答案)。
作为扩展,GCC接受
register int *foo asm ("a5");
声明一个位于寄存器中的全局 int
变量a5
...这很少有用,您需要了解 GCC 如何生成代码和分配寄存器,您的 ABI 的调用约定是什么,...以便能够毫无顾忌地使用它...顺便说一句,它可能会削弱 GCC 优化能力。
但它是GCC 特定的,Clang/LLVM 不支持该扩展,即使它支持几个其他 GCC 扩展(例如,计算goto
的 -s,...)。
首先也是最重要的。“寄存器存储变量”的分配(如果有)是编译器的工作。C
标准没有指定任何关于相同的强制性内容。
也就是说,
不能使用存储类定义全局变量,根据第§6.9章
register
C11
存储类说明符
auto
和register
不应出现在外部声明的声明说明符中。使用
register
不保证寄存器中的分配,第 §6.7.1 章(强调我的)使用存储类说明符为对象声明标识符
register
建议尽可能快地访问该对象。此类建议的有效程度由实施定义。
不,标准没有指定任何这样的功能。存储类的register
行为类似于auto
全局变量,不能用于全局变量。
根据经验,某台机器固有的所有内容都不是标准 C 的一部分。