Ara*_*uhi 4 c optimization microcontroller volatile
在C中使用-O0编译器标志时,告诉编译器避免任何类型的优化.将变量定义为时volatile,告诉编译器避免优化该变量.我们可以互换使用这两种方法吗?如果是这样,有什么优点和缺点?以下是我能想到的一些优点和缺点.还有吗?
优点:
volatile.如果代码显示错误行为,而不是进入代码并找到哪些变量需要声明为volatile,我们可以使用-O0标志来消除优化导致问题的可能性.缺点:
volatile关键字只影响特定的变量.例如,如果我们正在研究一个小型微控制器,这可能是一个问题,因为使用-O0可能会产生一个大的可执行文件.das*_*ght 13
编译器标志-O0绝不能替代正确使用volatile,因为编译器正确优化后不起作用的代码本身就会被破坏.你不希望破坏的代码让你看起来"工作",直到有人忘记抛出-O0开关.
根据代码中变量的总百分比,即使大型代码库需要许多volatile变量也是不寻常的.修复丢失的大型代码库volatile可能需要找到一些需要多个变量的战略位置volatile,并修复这几个,而不是采用"猎枪方法"并禁用所有优化.
P__*_*J__ 11
简短的回答是:volatile关键字并不会意味着"不优化".这是完全不同的东西.它通知编译器变量可能被正常程序流中的编译器不可见的东西改变.例如:
每次使用volatile变量时都必须从其存储位置读取,并在每次更改时保存.
这里有一个例子:
int foo(volatile int z)
{
return z + z + z + z;
}
int foo1(int z)
{
return z + z + z + z;
}
Run Code Online (Sandbox Code Playgroud)
和结果代码(-O0优化选项)
foo(int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov edx, DWORD PTR [rbp-4]
mov eax, DWORD PTR [rbp-4]
add edx, eax
mov eax, DWORD PTR [rbp-4]
add edx, eax
mov eax, DWORD PTR [rbp-4]
add eax, edx
pop rbp
ret
foo1(int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov eax, DWORD PTR [rbp-4]
sal eax, 2
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
我认为差别很明显.读取volatile变量4次,读取非易失性一次,然后乘以4.
你可以在这里玩:https://godbolt.org/g/RiTU4g
在大多数情况下,如果在打开编译器优化时程序没有运行,则代码中会有一些隐藏的UB.您应该根据需要进行调试以发现所有这些.正确编写的程序必须在任何优化级别运行.
请记住,"易变" 并不意味着或保证一致性和原子性.