【问题标题】:Can const variables be modified from elsewhere not known at compile time可以从编译时未知的其他地方修改 const 变量吗
【发布时间】:2018-01-16 14:26:15
【问题描述】:

如果 const 是编译时构造,则意味着只有编译器会确保,例如,如果将变量声明为 const,则该变量是只读的,并且不会尝试被其余代码修改正在编译?

如果 const 变量是我们代码中的全局变量,并且我们的代码在运行时链接到试图写入它的动态库,那该怎么办? ,或者如果 ISR 尝试更新它,这不在我们编译的代码中?

我相信编译器可以将 const 变量标记为加载到只读数据部分,这样可以防止变量发生任何变化,但如果不这样做呢?

谢谢

【问题讨论】:

  • const 可能是编译时常量运行时常量。这取决于上下文。
  • 至于您的问题,如果您出于任何原因抛弃了const,那么您可以从您自己的代码或第三方代码中打开undefined behavior,因为它可能会尝试修改数据。只是不要抛弃const,你应该(相对)安全。当然,没有什么能阻止第三方代码将其丢弃,但这是你无法控制的,并且会导致 UB。
  • 如果外部修改了声明为const(而不是const volatile)的变量,则行为未定义。没有“假设”
  • 第三方库如何在不丢弃const 的情况下写入您的常量数据?除非您提供,否则它怎么会知道您的数据?如果您使用const 限定符提供它,那么您应该期望该库不会做坏事并尝试修改数据。如果它试图修改常量数据,那么你应该把它扔掉,永远不要再使用它(当然是在通知作者这个问题之后)。
  • @Engineer999 可以。但随后行为是未定义的。 “未定义行为”一词的用途之一是对假设问题有一个很好的默认答案。如果有人做了不合理的事情,C 标准不保证程序以任何合理的方式运行。你在一个允许事情做任何事情的环境中运行。未知的动态库可能正在为您的函数重写代码。当不合理的事情发生时,无法保证合理的结果。修改一个 const 限定的对象是不合理的事情之一。

标签: c linker compiler-construction constants


【解决方案1】:

编译器将确保,例如,如果一个变量被声明为 const,这个变量是只读的,并且它不会被正在编译的其余代码修改?

是的,就编译器而言。如果您的代码尝试写入 const-qualified 变量,您将收到编译器错误。如果你通过例如抛弃 const 限定符来躲避类型正确性,那么所有的赌注都会被取消。

如果 const 变量是我们代码中的全局变量,并且我们的代码在运行时链接到试图写入它的动态库,那该怎么办? ,或者如果 ISR 尝试更新它,这不在我们编译的代码中?

那么它不应该是 const 限定的,否则编译器会做出奇怪的假设并生成不正确的代码。

但是,在某些情况下,const 变量可能会从外部更新 - 它可能是只读硬件寄存器或 EEPROM 存储单元等。

为了防止编译器在这种特殊情况下做出奇怪的假设,您可以将constvolatile 组合起来。因此,所有可能从外部源(例如硬件或 ISR)更新的变量都应始终声明为 volatile

【讨论】:

  • 实际的规则是尝试将对象 defined 修改为 const-qualified 是未定义的。可以将一个指向 const 限定类型的指针传递给函数,如果原始对象未使用 const 定义,则该函数可以丢弃 const 并修改该对象。
  • 我的理解是 const 仅适用于编译器,因此它将确保我们不会尝试在代码中的任何位置写入变量?然而,编译器是否也会在访问 const 变量时生成特殊的汇编代码以确保它是只读的?
  • @Engineer999 这取决于系统,有时还取决于变量范围。在纯粹的基于 RAM 的系统(例如 PC)上,const 主要用于程序员。例如,在具有真正闪存 ROM 的微控制器上,const 关键字意味着该变量最终会出现在 ROM 中而不是 RAM 中。除非它具有本地范围,否则它可能会或可能不会在 ROM 中结束。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-04
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多