未使用的易失性变量

3

如果我将一个变量声明为volatile并且在程序中没有使用它,编译器会优化该变量吗?

如果是局部的或全局的volatile变量声明呢?

谢谢。


3
强调Jim Balter在下面评论中的话:“volatile关键字与编译器是否为未使用的变量分配存储空间无关。”你认为什么会让你觉得volatile会影响编译器输出呢? (注:已翻译为简洁易懂的中文,不包含额外解释或内容。) - pascal
3个回答

7
编译器可以消除(忽略)未使用的volatile变量声明(但编译器无法消除未使用的全局变量定义-它必须假定某些其他翻译单元(TU)将引用它)。
如果变量是函数本地的且未使用,则无论其易失性如何,编译器都可以消除它。不清楚您是否可以拥有有意义的本地易失性变量,尽管我想您可以调用一个将其地址传递给某些代码的函数,然后安排中断处理程序写入该变量-实现易失性(但是,这显然是已使用的变量)。 volatile限定符控制(影响)编译器生成访问变量的代码方式-如果代码不访问变量,则没有必要更改它生成的代码,除非避免生成对变量的引用。它可能不存在。
进一步思考:
如果变量是static volatile并且在源代码中未被引用,它可以被消除吗?
答案(几乎肯定)是肯定的。源代码中没有对变量的引用,以可移植的方式访问它的唯一方法需要引用它。可能的不可移植黑客包括定义多个这样的静态变量,并将其中一个的引用传递给某个函数,然后该函数期望能够通过地址操作访问其他变量。但是,这样的代码最多也是丑陋和不可移植的。编写此类代码的作者可能应该被带到某个地方并安静地劝阻他再次编写此类代码。
因此,无法消除全局变量定义;它可能来自另一个TU。可以消除未使用的静态变量定义。可以消除未使用的本地变量定义。无论所涉及的变量是否具有volatile限定符,都适用。

3
我想知道编译器是如何做到的。它一次只会编译一个模块,如果变量没有声明为静态的,那么它无法知道该变量是否在其他地方被使用。这看起来更像链接器的工作。 - Sergei Tachenov
1
“不清楚你是否可以拥有有意义的本地易失性变量”:在使用for循环进行延迟的情况下,循环计数器(通常用于嵌入式系统)必须声明为volatile。例如,在volatile int i; for (i=100; i>=0; --i) {}中。该for循环没有逻辑意义,但不能被优化掉。如果不是由于volatile关键字,优化器将会这样做。(但它是一个被使用的变量)。 - Gauthier
@gauthier:有趣的观察。变量并非易变的,也不会在编译器不知情的情况下发生改变,但通过指定为易变,你强制编译器生成了循环(它必须将其视为可能会改变的)。谢谢! - Jonathan Leffler
1
此外,volatile 用于确保在调用 longjmp 后恢复包含 setjmp 的例程中的局部变量。 - Jim Balter
1
该变量并非在没有编译器知晓的情况下随意更改,这并不是volatile的含义所在。它限制了编译器进行"as if"转换的能力;这些限制在C标准中有详细说明。 - Jim Balter
显示剩余2条评论

3

volatile与存储分配无关——如果编译器在没有volatile关键字的情况下消除了未使用的变量,那么在有volatile关键字的情况下也可以并且很可能会被消除。如果你想确定,请检查生成的代码或符号表。


-1
如果一个变量没有被使用,那就是最理想的情况。优化只在操作和计算的情况下进行。
如果数据没有进行任何操作,就不需要进行优化。

编译器也可以针对程序大小进行优化。消除未使用的变量是一种优化方法。 - Fred Foo
这个回答在很大程度上是正确的,不应该被贬低。事实上,C标准只规定了volatile如何限制编译器的语义模型;它对存储分配没有任何影响。无论编译器是否为未使用的变量分配存储空间,volatile关键字都是无关紧要的。 - Jim Balter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接