在C中使用volatile关键字来防止编译器对变量执行某些优化,以及其他细微更改。
例如;
volatile int my_int = 0;
创建一个整数。在某些情况下,它可能会阻止以下优化:
while(my_int == 0); // Loop until my_int != 0
优化至:
while(1); // Loop infinity.
这对于包括嵌入式系统中经常遇到的情况很有用,例如可以通过中断函数调用对变量进行修改的情况。还有许多其他这种技术有用的例子。 my_int
可以是由这样的函数修改的标志。 (这只是一个玩具模型。)
但是,请考虑函数修改的数据是数组的情况。数据可以由指针指向。
unsigned char* my_data = new unsigned char[256];
在这种情况下,考虑到my_data是这个问题[1]的特定情况下的全局变量,是volatile
关键字冗余,还是仍然需要?
[1]可能没关系。
如果答案是需要volatile关键字,那么使用正确的语法是什么?
例如,volatile unsigned char* my_data
,我假设声明指针本身是易失性的,而不是它指向的数据。
最后,在C和C ++中的使用有区别吗?
答案 0 :(得分:28)
是的,volatile
是必需的,正确的声明是:
volatile unsigned char *my_data;
这声明my_data
是指向volatile unsigned char的指针。
要使指针本身易变,你需要改为:
unsigned char *volatile my_data;
当然,指针和指向数据都可能是不稳定的:
volatile unsigned char *volatile my_data;
C和C ++之间没有区别。
答案 1 :(得分:0)
菲利普·贡萨尔维斯(FilipeGonçalves)已经提供了答案,但我想详细说明。
基本上,只要您希望程序真正考虑变量值而又不聪明,就需要volatile关键字。不管您拥有哪种类型的变量都没有关系,只是如果编译器看不到在赋值和调用之间对该变量进行任何更改,它可能会对其进行优化(当然取决于您的设置)。
从编译器的POV看,事件的顺序为"assign 0 to Var"->"do unrelated stuff, but surely not touching Var"->"check Var value"
,变量Var的声明位置和声明方式无关紧要,除非使用volatile
关键字,否则代码将得到优化。
答案 2 :(得分:0)
C声明应从右到左读取,并在左侧添加限定符。
所以volatile char * x
的意思是'x'是一个指向易变性字符的指针。
而char volatile * x
表示'x'是指向char的易失性指针
做法的差异在于,在访问x [0]时,在第一种情况下,需要在源代码的每个外观上读取x [n]处的值(例如,a = x[n]*x[n]
中两次) / p>
在第二种情况下,每次都要读取x个本身,然后再次计算x [n]的地址,然后再读取x [n]。
因此,volatile char volatile *x
是多余的。
但是,将数组或其元素声明为volatile将阻止编译器在多个读取之间缓冲它们。它不能确保读取易失性数组的函数在包含旧值的情况下不会读取数组的前半部分,而在包含更新值的情况下(在外部更改后)不会读取数组的后半部分,从而导致结果不一致。 仅在单个元素彼此独立时才建议在数组或结构(或单个变量集)上使用volatile。如果更改其中一个会影响其他(或它们的使用/含义),那么volatile根本没有帮助,应该对整个访问使用互斥锁(防止在处理过程中更改数组内容)。