我理解register关键字将为计算值分配一个寄存器,而volatile关键字将在每次对变量进行计算时从内存中读取该值,并基本上不会优化代码。因此,如果变量同时被分配这两个关键字,那么它是否意味着它本身本质上是volatile的?通过编写示例代码我无法理解其行为。有人能解释一下吗?
在C语言中,register
存储类的行为与auto
存储类完全相同,唯一的区别是如果程序尝试获取或使用该对象的地址(6.5.3.2、6.7.1),实现必须(根据5.1.1.3)发出诊断警告。将register
用作编译器优化提示通常没有意义,因为足够聪明以利用对象无需存储的编译器肯定能够跟踪哪些对象可以声明为register
;相反,它应被理解为代码质量检查,以确保程序员没有通过获取对象地址无意中破坏了优化机会。
换句话说,从一个有效程序中删除所有register
关键字对程序的语义没有影响;在这方面,它类似于static_assert
。
volatile
类型限定符表示访问(读取和写入)该对象被视为副作用,不能被优化掉。对于不存在于定义位置内存中的对象(即具有register
存储类的对象),这在性能测试中非常有用:
start = time();
for (multiple loops)
register volatile int result = test_function();
stop = time();
elapsed = stop - start;
auto
变量没有的特性:您无法获取寄存器变量的地址。 - Richard J. Ross IIIvolatile
表示对象可能以编译器无法预测的方式发生改变,而register
则表示其地址无法被获取。
当该对象实际上是平台上的硬件寄存器时,这两者的结合就有了完美的意义。一些编译器(如gcc)甚至有扩展来将这样的变量固定到特定的硬件寄存器上。
其他一些代码可能会更改这样的硬件寄存器,因此编译器可能对当前值不做任何假设。在这种情况下,添加一个const
限定符甚至也是有意义的。例如,在gcc的扩展中使用。
register uint32_t volatile const eax __asm__("eax");
你可以随时使用工具检查eax
寄存器,但不会意外更改它。
register
变量是什么意思?这种变量没有“存储”模型,因此也没有“读取”或“写入”的模型。 - Jens Gustedtsetjmp
的函数中,我认为需要一个具有volatile
和register
限定符的对象,以反映在两次从setjmp
返回之间所做的任何更改,而仅仅带有register
限定符的对象则不能做到这点。 - supercat
register
命令。 - Joeregister
声明的变量不能被地址访问。 - Daniel Fischerregister int some_var;
(或者register volatile int some_var;
),在源代码中使用&some_var
将会违反限制,并要求进行诊断(编译器是否中止编译取决于编译器,但你的程序不符合规范)。 - Daniel Fischer