gpt4 book ai didi

c - -O0 编译器标志是否与 C 中的 volatile 关键字具有相同的效果?

转载 作者:太空狗 更新时间:2023-10-29 15:09:43 25 4
gpt4 key购买 nike

当您在 C 中使用 -O0 编译器标志时,您告诉编译器避免任何类型的优化。当您将变量定义为 volatile 时,您告诉编译器避免优化该变量。我们可以交替使用这两种方法吗?如果是这样,利弊是什么?以下是我能想到的一些优缺点。还有吗?

优点:

  • 如果我们有一个大型代码库,其中应该声明为 volatile 的变量却没有声明,则使用 -O0 标志会很有帮助。如果代码显示错误行为,而不是进入代码并查找哪些变量需要声明为 volatile,我们可以只使用 -O0 标志来消除优化导致问题的可能性.

缺点:

  • -O0 标志将影响整个代码,而 volatile 关键字仅影响特定变量。例如,如果我们在小型微 Controller 上工作,这可能是一个问题,因为使用 -O0 可能会产生一个大的可执行文件。

最佳答案

简短的回答是:volatile 关键字not 表示“不优化”。这是完全不同的东西。它通知编译器变量可能会被一些在正常程序流程中对编译器不可见的东西改变。例如:

  1. 它可以被硬件改变——通常是映射到内存地址空间的寄存器
  2. 可以被从未调用的函数改变——例如中断例程
  3. 变量可以被另一个进程或硬件改变——例如多处理器/多核系统中的共享内存

volatile 变量每次使用时都必须从其存储位置读取,并在每次更改时保存。

这里有一个例子:

int foo(volatile int z)
{
return z + z + z + z;
}

int foo1(int z)
{
return z + z + z + z;
}

和生成的代码(-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

我认为区别很明显。 volatile 变量读取 4 次,non volatile 读取一次,然后乘以 4。

你可以在这里玩自己:https://godbolt.org/g/RiTU4g

在大多数情况下,如果您打开编译器优化后程序无法运行,则您的代码中存在一些隐藏的 UB。您应该根据需要进行调试以发现所有这些。正确编写的程序必须在任何优化级别运行。

请记住,“volatile”并不意味着或保证一致性和原子性。

关于c - -O0 编译器标志是否与 C 中的 volatile 关键字具有相同的效果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50348902/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com