我知道每次我们对变量执行一些计算并且基本上不优化代码时,一个 register 关键字将分配一个用于计算值的寄存器,而一个 volatile 关键字将从内存中读取值。那么,如果一个变量同时被分配了这两个关键字,这是否意味着它本身本质上是 volatile 的?我无法通过编写示例代码来理解这种行为。任何人都可以解释一下吗?
2 回答
在 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;
volatile
意味着对象可能会以编译器无法预测的方式更改,并且register
意味着无法获取其地址。
当对象实际上是平台上的硬件寄存器时,两者的结合非常有意义。一些编译器(例如 gcc)甚至具有将此类变量固定到特定硬件寄存器的扩展。
其他一些代码可能会更改这样的硬件寄存器,因此编译器可能不会假设当前值。const
在这种情况下,添加限定符甚至是有意义的。例如使用 gcc 的扩展名
register uint32_t volatile const eax __asm__("eax");
您将拥有随时检查eax
寄存器的工具,但您无法意外更改它。