C 编译器有义务始终从内存中重新加载 const 值吗?

问题描述 投票:0回答:2

我的嵌入式 C 程序中有一个

const
变量。它在程序代码中用
0
定义和初始化。它通过链接描述文件放置在特殊的 ROM 区域中。通过特殊的编程程序可以改变特殊区域的内容,但在主程序执行过程中不能改变。

问题是我是否必须将常量声明为

volatile
。如果它没有标记为
volatile
,是否允许编译器将所有对它的引用替换为
0
?或者是否有义务在程序执行期间至少加载一次?

c constants compiler-optimization constantfolding
2个回答
28
投票

看起来你的变量实际上是一个常量(即在程序执行期间不会改变),其值是编译器未知的。如果是这种情况,你可以这样声明:

extern const int variable;

(即没有

volatile
并且没有初始化程序)并让链接器脚本或其他工具设置正确的值。

然后,编译器将被允许加载它,并可能将其永远保留在寄存器中,但不会在编译时将其替换为 0 或任何其他值。


11
投票

如果标记为

volatile
,编译器必须在每次需要它的值时从内存中加载它。

如果没有标记为

volatile
,编译器可能从内存中加载它一次,将其存储在寄存器中,并使用该寄存器而不是再次加载它。

未优化的编译器可能会这样做 - 但它也可能愚蠢地每次都加载它。 (因为不重新加载实际上本身就是一种优化。)

优化编译器可能会注意到

const
并决定可以使用其真实的文字值进行编译;直到原始常数 根本不会出现在程序的 .data
 部分中。 (或者也许它确实如此,但它永远不会被“读取”。)

由于您更改了链接描述文件中的值,编译器无法“知道”编译后值已更改。在这种情况下,请使用

volatile

:告诉编译器不要相信编译时该值是已知的唯一方法。

© www.soinside.com 2019 - 2024. All rights reserved.