【问题标题】:Does making a variable a const or final save bytes or memory?是否将变量设为 const 或 final 保存字节或内存?
【发布时间】:2017-11-03 08:57:43
【问题描述】:

我一直在使用一个程序,并且一直在尝试节省字节和存储空间。

我的 C 程序中有很多变量,但我想知道是否可以通过在整个程序中使用 don't changeconstfinal 的一些变量来减小程序的大小。

所以我的问题是:

  • 将静态变量标识为constant时是否有任何字节保存?
  • 如果这样做可以保存字节,为什么要保存它们?如果是constant,程序如何以不同的方式存储变量,为什么这种方式需要更少的存储空间?
  • 如果通过将变量定义为constant 没有保存字节,那么为什么开发人员首先要以这种方式定义变量?难道我们不能省略const,以防我们以后需要更改变量(尤其是在这样做没有失败的情况下)?
  • 是否只有一些 IDE/语言可以使用 constant 变量保存字节?

感谢您的帮助,非常感谢。

【问题讨论】:

  • 如果编译器将其优化为编译时常量,那么是的,它可以节省几个字节的内存,因为它可能不需要变量空间。这要求您在定义时初始化变量,并且您永远不会在任何地方获取变量的地址。但总的来说,不要指望它。
  • 至于为什么人们使用const?好吧,如果您有一个不允许修改的变量,那么当然我们将其设为const。这是一个语义问题,它有助于人们阅读代码,它有助于防止你(或其他人)犯下愚蠢的错误,它甚至可以帮助编译器做出优化决策。
  • C 没有指定constant。它确实指定了const
  • 根据处理器的不同,常量变量可能最终会成为指令的立即值操作数,这样可以节省少量空间。

标签: c variables constants final


【解决方案1】:

我认为您正在研究深度嵌入式系统(例如 cortex-M 处理器)。 对于这些,您知道 SRAM 是一种稀缺资源,而您拥有大量的 FLASH 存储器。 然后尽可能对任何不改变的变量使用 const 关键字。 这样做会告诉编译器将变量存储在 FLASH 内存中而不是 SRAM 中。

例如,要在系统上存储文本,您可以这样做:

const char* const txtMenuRoot[] = { "Hello, this is the root menu", "Another text" };

那么在FLASH中不仅存储了文本,还存储了它的指针。

【讨论】:

  • 这个答案说的是实话,但它是错误的:没有“内存节省”,它只是使用不同类型的内存。
  • 我的答案在哪里写着我节省内存?
  • 问题是关于节省内存的。您的答案应该回答问题,但事实并非如此。
【解决方案2】:

您的所有问题在很大程度上取决于编译器和环境。用于嵌入式环境的 C 编译器可以很好地节省内存,而其他编译器可能不行。

将静态变量标识为常量时是否有任何字节保存?

是的,有可能。但是请注意,“const”通常并不是为了指定如何存储变量——而是它的含义是帮助程序员和编译器更好地理解源代码(当编译器“更好地理解”时,它可以产生更好的目标代码)。一些编译器可以使用该信息也将变量存储在只读内存中,或者将其删除并将其转换为目标代码中的文字。但就您的问题而言,#define 可能更合适。

如果这样做可以保存字节,为什么要保存它们?如果变量是常量,程序如何以不同的方式存储变量,为什么这种方式需要更少的存储空间?

在源代码中声明的变量可以到目标代码中的不同位置,以及当目标文件加载到内存中并执行时的不同位置。请注意,各种架构也存在差异——例如在小型 8/16 位 MCU(用于电子设备的 CPU)中,通常没有“加载”目标文件。因此,变量的值存储在某处 - 无论如何。但是在低级别,编译器可以使用文字而不是地址,这主要节省了一些内存。假设您在源代码中声明了一个常量变量 GAIN=5。当在某个公式中使用该变量时,编译器会发出类似“LD R12,GAIN”的信息(使用地址 GAIN 的内容加载寄存器 R12,其中存储了变量 GAIN)。但编译器也可以发出“LD R12,#5”(在 R12 中加载值“5”)。在这两种情况下都需要一条指令,但在第二种情况下,所涉及的变量没有内存。这是一种节省,也可以更快。

如果不通过将变量定义为常量来保存字节,那么为什么开发人员首先要以这种方式定义变量?难道我们不能只省略 const 以防我们以后需要更改变量(尤其是在这样做没有失败的情况下)?

如前所述,“const”关键字旨在更好地定义将对变量执行的操作。为了清楚起见,这对程序员很有用。明确说明变量不打算被修改是有用的,特别是当变量是形式参数时。在某些环境中,实际上有一些只读内存只能读取而不能写入,如果一个变量(可能是“系统变量”)被标记为“const”,程序员就清楚了 - 并且 -编译器,如果遇到试图修改该变量的代码,它会发出警告。

是否只有一些 IDE/语言可以使用常量变量保存字节?

绝对是的。但是不要谈论 IDE:它们只是编辑器。关于语言,事情很复杂:它完全取决于实现和优化。可能这种保存仅在编译器(而非解释器)中使用,并且很大程度上取决于编译器的优化选项/功能。

【讨论】:

    【解决方案3】:

    这样想const(C 中没有finalconstant 这样的东西,所以我将忽略它)。如果编译器可以节省内存,它会(特别是当您编译优化大小时)。 const 为编译器提供了有关对象属性的更多信息。当编译器拥有更多信息时,它可以做出更明智的决定,并且不会阻止编译器做出与获得该信息之前完全相同的决定。

    它不会伤害并且可能会有所帮助,它还可以帮助使用代码的程序员更轻松地对其进行推理。编译器和程序员都得到了帮助,没有人受到伤害。这是双赢的。

    【讨论】:

      【解决方案4】:

      编译器可以根据对代码的了解来减少使用的内存,const 帮助编译器了解真实的代码行为(如果您激活警告,您可以对 const 的放置位置提出建议)。

      但是由于使用的硬件的对齐限制,结构可以包含未使用的字节,并且编译器无法更改结构的内部顺序。这只能通过更改代码来完成。

      struct wide               struct compact
      {                         {
          int_least32_t i1;             int_least32_t i1,
          int_least8_t b;                             i2;
          int_least32_t i2;             int_least8_t b;
      }                         }
      

      由于对齐限制,结构宽度可以在成员“b”和“i2”之间有一个空白空间。 这不是 struct compact 的情况,因为元素是从最宽(可能需要更大的对齐)到更小的元素列出的。

      在同样的情况下,结构紧凑甚至可以带来更快的代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-08
        • 1970-01-01
        • 1970-01-01
        • 2011-03-31
        • 2014-02-17
        • 2012-06-11
        相关资源
        最近更新 更多