【问题标题】:Where we have to use only register variable?我们必须在哪里只使用寄存器变量?
【发布时间】:2014-02-27 06:16:42
【问题描述】:

我们知道register variablefaster accessible,并且在compiler 上创建register variable 的任何变量。

register int val;

我只想知道“是否有任何情况/应用程序我们必须只使用register variable,而其他变量在这种情况下没有用处?”

如果能放一段代码就好理解了。

【问题讨论】:

  • 即使您使用关键字register,编译器也可以随意忽略您。
  • Ans: 在阅读了一些教程后,我发现不存在只使用register 变量的情况,因为编译器无法保证我的变量是否为寄存器类型。这样做的好处是——这个变量不是<optimized out>,而是一个自动变量,如果不在代码中使用的话。没有人可以获取寄存器变量的地址,所以我们也可以说它是安全的。

标签: c variables compiler-construction storage cpu-registers


【解决方案1】:

“我们知道”——实际上我们知道。

register 是对编译器的建议,而不是要求。当今疯狂优化的编译器很少需要它。从当前的(C11)标准:

具有存储类说明符寄存器的对象的标识符声明 建议尽可能快地访问对象。这种程度 建议是否有效由实现定义。

所以它可以进入一个寄存器。它还可以进入更快的内存、常规内存甚至是磁盘或内蒙古的服务器,以惩罚编码人员使用不必要的关键字:-)

可能发现它在不是非常聪明的编译器中很有用(例如,可能是一些较旧的嵌入式编译器),但即便如此,您也不会' t 必须 使用它 - 通常,您应该忘记它。它和auto 一样有用。

作为示例,让我们假设一个相当“优化不足”的编译器将每条 C 指令视为一个单元。我的意思是这样的:

int x = 1;
x = x + 7;
x = x - 2;
useX (x);

将转换为程序集(经典的加载存储架构):

loadi  r0,  1          ; set r0 to 1
stor   r0,  [x]        ; store to memory

load   r0,  [x]        ; load from memory
addi   r0,  7          ; add 7
stor   r0,  [x]        ; store to memory

load   r0,  [x]        ; load from memory
subi   r0,  2          ; subtract 2
stor   r0,  [x]        ; store to memory

load   r0,  [x]        ; load from memory
call   useX            ; call the function

换句话说,没有优化意识到在添加之后该值仍在r0中,因此无需再次加载它。

在这样一个(脑死的)编译器中,使用register 可能会带来相当方便的效率。代码:

register int x = 1;
x = x + 7;
x = x - 2;
useX (x);

可能会产生更好的代码:

loadi  r0,  1          ; set r0 to 1
addi   r0,  7          ; add 7
subi   r0,  2          ; subtract 2
call   useX            ; call the function

当然,所有这些都取决于编译器以及它如何使用寄存器。我给出的代码只是一个人为的例子。正如我所说,对于现代编译器,它很少需要。


底线,回答您的具体问题“是否存在我们必须仅使用寄存器变量而其他变量在这种情况下无用的情况/应用?”,答案是否定的.如果是真正的 C 编译器,则不需要使用 register 关键字。

【讨论】:

  • 这是一个真实的陈述,但它没有回答问题。我认为这应该是一个评论。事实上,我发表了惊人的相似评论......
  • 如果附有asm声明,则为必填项。
  • 是的,您可以向编译器提出建议,编译器也可以忽略它。但我想知道我们在哪里以及为什么使用,我的意思是情况......
  • @SK-logic,C 核心语言中没有asm 关键字。一些 实现 可能提供内联汇编(根据 ISO-C 附录 J:通用扩展),但这绝不是必需的。而且,由于它没有在asm { character-string-literal } 之外指定(这只是一种通用 语法,不是强制的),asm 不能强制使用register。我可以很容易地注入只修改内存的内联汇编程序,使用 no 寄存器。
  • @paxdiablo,是的,我在这里谈论的是 gcc 特定的扩展:我不知道强制执行 register 的任何其他情况。但是这个特殊的扩展也被许多其他编译器使用。
【解决方案2】:

没有你必须使用register的情况。但除了似乎是都市传说之外,register在C程序中还有一个语义含义:用register而不是默认auto声明的变量,不能服从&,所以他们的地址不能被取走。这意味着它们永远不能与其他变量别名,因此register 只是一个优化提示,就像restrict 一样。

【讨论】:

  • 我想知道这个细节是否值得一提。我认为是。
  • 要点:“你不能有一个指向寄存器变量的指针”。不知道你为什么会关心,但这是我以前从未想过的事情。
  • @floris:也许有人可能想避免在某些时间关键代码中获取局部变量地址的优化杀手错误。这可能是让编译器让您知道您是否这样做的一种方法。也许您担心在宏中使用变量可能会获取地址而不使其明显,或者将来的代码维护可能会让错误溜进来。我认为这不是一个特别好的例子,但我可以想象有人按照这些思路思考。
【解决方案3】:

在某些情况下,不仅要提示编译器为变量分配寄存器,还要为它命名一个特定的寄存器(然后不允许忽略 register 关键字):实现高效的线程虚拟机器。

这种方法的一个很好的例子是OCaml bytecode interpreter

在任何其他必须混合 C 和汇编代码的情况下,手动将 C 变量映射到寄存器是必不可少的。

【讨论】:

  • 这是一个 GCC 扩展,不是普通 C 语言的一部分。
  • @immibis,现在 GCC 扩展非常普遍,许多其他编译器也实现了(Clang,icc)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-25
  • 2012-11-27
  • 1970-01-01
  • 1970-01-01
  • 2020-08-23
  • 1970-01-01
相关资源
最近更新 更多