3

我读到 gcc 提供了将全局变量定义为寄存器存储变量的支持。我想知道的是标准是否有任何关于这种支持的规范。

4

5 回答 5

5

有一个普遍的误解,认为 C 的关键字register谈论的是硬件寄存器。这可能是该概念的起源,但在现代 C 中,这不是目的。唯一真正的影响register是,&在这样的野兽上是不允许的。

它们可以以编译器想要的任何方式实现,硬件寄存器,指令立即数,或者在堆栈上,你不会知道。您所知道的是,一个register变量不能与其他变量别名。

为了更直接地回答您的问题,register文件范围内的 no 不是 C 语言的一部分。如果是这样,那将允许我们声明register const几乎任何基数的变量,这可以用作某种全局常量

将硬件寄存器映射到特定变量是编译器提供的扩展,例如 gcc。Gcc 的功能,作为一个扩展,也适用于文件范围。但这是非常令人望而却步的,因为通常 CPU 没有很多硬件寄存器可供备用。

于 2015-07-24T10:19:15.550 回答
4

register不能用于全局变量。C11 6.9/2 涵盖了这一点:

约束

存储类说明符autoregister不应出现在外部声明的声明说明符中。

在这里,外部声明是指不在函数内的任何声明。(不要与extern或外部链接混淆)。

于 2015-07-24T10:02:22.880 回答
2

C99 或 C11 标准不支持或不允许全局寄存器变量(请参阅Sourav GhoshMatt McNabb 的答案)。

作为扩展GCC接受

  register int *foo asm ("a5");

声明一个位于寄存器中的全局 int变量a5...这很少有用,您需要了解 GCC 如何生成代码和分配寄存器,您的 ABI 的调用约定是什么,...以便能够毫无顾忌地使用它...顺便说一句,它可能会削弱 GCC 优化能力。

但它是GCC 特定的,Clang/LLVM 不支持该扩展,即使它支持几个其他 GCC 扩展(例如,计算goto的 -s,...)。

于 2015-07-24T10:16:18.997 回答
2

首先也是最重要的。“寄存器存储变量”的分配(如果有)是编译器的工作。C标准没有指定任何关于相同的强制性内容。

也就是说,

  • 不能使用存储类定义全局变量,根据第§6.9registerC11

    存储类说明符autoregister不应出现在外部声明的声明说明符中。

  • 使用register不保证寄存器中的分配,第 §6.7.1 章(强调我的

    使用存储类说明符为对象声明标识符register 建议尽可能快地访问该对象。此类建议的有效程度由实施定义。

于 2015-07-24T10:00:08.173 回答
1

不,标准没有指定任何这样的功能。存储类的register行为类似于auto全局变量,不能用于全局变量。

根据经验,某台机器固有的所有内容都不是标准 C 的一部分。

于 2015-07-24T10:00:00.810 回答