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

mrn*_*mrn 24 c

const我的嵌入式C程序中有一个变量.它0在程序代码中定义和初始化.它通过链接描述文件放在一个特殊的ROM区域.可以通过特殊编程程序更改特殊区域的内容,但在主程序执行期间不能更改.

问题是我是否必须将常数声明为volatile.如果它没有标记为volatile,编译器是否允许用它替换所有引用0?或者是否有义务在程序执行期间至少加载一次?

n. *_* m. 28

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

extern const int variable;
Run Code Online (Sandbox Code Playgroud)

(即,没有volatile和没有初始化程序)并让链接器脚本或其他工具设置正确的值.

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

  • "我受到解决方案的束缚"我不确定为什么这被称为"解决方案"而不是恰当的"问题".但无论如何,如果没有其他问题,你必须使用`volatile` (5认同)
  • 如果你真的需要在C中定义变量,那么创建一个单独的源文件,只包含`const int variable = 0;`,将其与所有其他代码分开编译,并将其链接. (2认同)

usr*_*301 11

如果标记为volatile编译器必须在每次需要它时从内存加载它.

如果没有标记为volatile,编译器可能会从内存加载一次,将其存储在寄存器中,并使用此寄存器而不是再次加载它.

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

优化编译器可能会注意到const并确定它可以使用其真实的字面值进行编译; 最多到原来的固定点根本不会出现.data你的程序的部分.(或许它确实如此,但永远不会"读".)

由于您更改了链接描述文件中的值,因此编译器无法"知道"编译后更改的值.在这种情况下,使用volatile:告诉编译器在编译时不要相信该值是已知的唯一方法.

  • @Rhymoid:`const`*确实*意味着更多.例如,C11最终草案[第6.7.3.6节](http://port70.net/~nsz/c/c11/n1570.html#6.7.3p6),"如果试图修改用a定义的对象通过使用具有非const限定类型的左值的const限定类型,行为是未定义的." (5认同)
  • 如果没有答案所提供的上下文,你的措辞就会产生误导,使人们相信"const"意味着"如果你通过这个左值修改底层对象,编译器就会抱怨".请注意,这是关于C的最棘手的神话之一,就在那里"C是可移植的汇编","`inline"意味着编译器肯定会在任何地方内联函数",并且`sizeof(int)*CHAR_BIT = = 32` (2认同)