【发布时间】:2018-05-15 11:20:11
【问题描述】:
当您在 C 中使用 -O0 编译器标志时,您告诉编译器避免任何类型的优化。当您将变量定义为volatile 时,您告诉编译器避免优化该变量。我们可以互换使用这两种方法吗?如果是这样,有什么优点和缺点?以下是我能想到的一些优点和缺点。还有吗?
优点:
- 使用 -O0 标志很有帮助,如果我们有一个很大的代码库,其中应该声明为
volatile的变量不是。如果代码显示错误行为,我们可以使用 -O0 标志来消除优化导致问题的可能性,而不是进入代码并查找需要声明为 volatile 的变量.
缺点:
-
-O0 标志将影响整个代码,而
volatile关键字仅影响特定变量。例如,如果我们正在开发一个小型微控制器,这可能是个问题,因为使用 -O0 可能会产生一个大的可执行文件。
【问题讨论】:
-
" 我们可以使用 -O0 标志来消除优化导致问题的可能性" 是的,您可以使用它作为调试技术来查找错误。但不是作为错误修复。
-
@Lundin 我认为您夸大了
volatile和-O0之间的相似性。将变量一次读入寄存器并将其保留在那里,多次使用该值而不重新读取它,或者相反地不断更新寄存器中的该值并仅在循环的多次迭代后将其存储一次,这不是一种优化.这种行为不是-O0可以防止的,但这种行为直接与volatile的真正含义相矛盾。使用-O0在识别代码问题方面可能有用,但它远非确定或详尽。 -
@AndrewHenle 在大多数系统上将变量放在寄存器中本身就是一种优化。无论如何,OP 所指的错误类型很可能是文件范围变量由 ISR 或回调更新,但主程序没有意识到变量已更改,因此相应地优化了代码。这是一个经典且非常讨厌的错误,您可以实际上通过禁用优化来追踪它。一个比较常见的现实世界场景是:“为什么代码在发布版本中中断,而不是在调试版本中中断”。
-
AFAIK 编译器完全可以忽略任何
-Ox标志。只要遵循“好像”规则,在每个级别上进行哪些优化或不进行哪些优化都留给编译器来决定。除非编译器文档有说明,否则无法保证每个变量都会隐含volatile。
标签: c optimization microcontroller volatile