【发布时间】:2015-07-24 09:55:49
【问题描述】:
我读到 gcc 支持将全局变量定义为寄存器存储变量。我想知道的是,标准是否对这种支持有任何规范。
【问题讨论】:
-
您可能还想read this
标签: c global-variables storage-class-specifier register-keyword
我读到 gcc 支持将全局变量定义为寄存器存储变量。我想知道的是,标准是否对这种支持有任何规范。
【问题讨论】:
标签: c global-variables storage-class-specifier register-keyword
C 的关键字register 谈论硬件寄存器是一个常见的误解。这可能是该概念的起源,但在现代 C 中,这不是目的。 register 唯一真正的效果是,& 不允许在这样的野兽身上。
它们可以以编译器想要的任何方式实现,硬件寄存器,指令立即数,或者在堆栈上,你不会知道。您所知道的是,register 变量不能与其他变量别名。
为了更直接地回答您的问题,文件范围内的 register 不是 C 语言的一部分。如果是这样,那将允许我们声明几乎任何基数的 register const 变量,这可以用作某种 global constants。
将硬件寄存器映射到特定变量是编译器提供的扩展,例如 gcc。 Gcc 的功能,作为一个扩展,也适用于文件范围。但这是相当令人望而却步的,因为通常 CPU 没有很多硬件寄存器可供备用。
【讨论】:
register 不能用于全局变量。 C11 6.9/2 涵盖了这一点:
约束
存储类说明符
auto和register不得出现在外部声明的声明说明符中。
这里,外部声明是指任何不在函数内的声明。 (不要与extern 或外部链接混淆)。
【讨论】:
首先。 “注册存储变量”的分配,如果有的话,是编译器的工作。 C 标准没有指定任何强制性相同的内容。
也就是说,
全局变量不能用register存储类定义,根据C11,第§6.9章
存储类说明符
auto和register不得出现在外部声明的声明说明符中。
使用register 并不能保证寄存器中的分配,第 §6.7.1 章(强调我的)
使用存储类说明符
register声明对象的标识符建议尽可能快地访问该对象。 此类建议的有效程度由实施定义。
【讨论】:
extern int foo; extern int *bar; 代码foo++; *bar ^= 1; foo++; *bar ^= 2; 必须按顺序执行所有四个步骤。如果foo 可以是寄存器限定的,则操作可以重新排序为foo+=2; *bar^=3;。
C99 或 C11 标准不支持或不允许Global register variables(请参阅Sourav Ghosh's 或Matt McNabb's 答案)。
作为扩展,GCC 接受
register int *foo asm ("a5");
声明一个全局 int 变量坐在寄存器a5... 这很少有用,你需要了解GCC如何生成代码和分配寄存器,调用是什么您的 ABI 的约定,...能够毫无畏惧地使用它...顺便说一句,它可能会削弱 GCC 优化能力。
但它是 GCC 特定的,Clang/LLVM 确实 not 支持该扩展,即使它支持几个其他 GCC 扩展(例如计算 goto-s,...) .
【讨论】:
没有。标准没有指定任何这样的特性。存储类register 的行为类似于auto,不能用于全局变量。
根据经验,某台机器固有的所有内容都不是标准 C 的一部分。
【讨论】: