【问题标题】:For small values of integer is the memory space is wasted对于小的整数值是浪费内存空间
【发布时间】:2018-01-26 09:36:38
【问题描述】:

我知道整数数据类型占用 2 或 4 个字节的内存。我想知道,如果int数据类型变量值的值小于,那是不是空间浪费了?

#include <stdio.h>
int main(void)
{
  int a=1;
  printf("%d\n",a);
}

二进制值是 00000001,即 1 个字节, int 数据类型为 a 值分配了 2 个字节的空间。剩余的 1 个字节被浪费了吗?

【问题讨论】:

  • “我知道整数数据类型占用 2 或 4 个字节的内存。” 你不知道有什么问题。在某些系统上,一个 int 需要 8 个字节。不要沉迷于“全世界的盒子都像我的盒子”。
  • 除非您的目标是内存有限的嵌入式系统,否则这真的很重要吗?如果将来程序需要处理更大的值怎么办?您可能想对 the Y2K "crisis" 进行一些研究,因为上个世纪的程序员想要节省几个字节而对未来没有太多考虑。
  • int 占用的空间是sizeof(int)(现在通常为 4 或 8 个字节,有时仍为 2 个字节,甚至可能是其他字节,这取决于平台)。您的 a 变量稍后可能会设置为更大的值,因此不会浪费任何东西。
  • @MichaelWalz 有趣的是,曾经有一个 CHAR_BIT == 16 和 sizeof(int) == sizeof(short) == sizeof(char) == 1 的系统(TI DSP)...跨度>

标签: c memory


【解决方案1】:

理论上,是的,空间被浪费了。尽管在 32 位 CPU 上,分配 32 位数据可能意味着更快的访问,因为它适合对齐。因此,使用 32 位变量来存储值 1 可能是对内存消耗的速度优化。

在微控制器系统上,程序员的内存要少得多,因此对变量声明更加挑剔,而是使用 stdint.h 中的类型来分配所需的内存。他们会使用uint8_t 而不是int

如果您想要两全其美 - 最快的访问速度和尽可能低的内存消耗 - 请使用 uint_fast8_t 类型。然后编译器会选择最快的类型,最多可以存储 255 个值。

【讨论】:

  • Lundin,int 不会默认为机器的原始大小吗? (假设寄存器宽度和总线宽度相同。)那不是总是最快的吗?
  • @PaulOgilvie 遗憾的是,没有。 8 位计算机的原始大小是 8,但它们使用 16 位 int,因为 charshortint 都表示 8 位是没有意义的。 C 标准甚至不允许int 这么小。同样,在 64 位计算机上,intlonglong long 都表示 64 位是没有意义的。 See this.
  • 不过,假设您很有可能通过 [...]_fast_t 类型获得这些 - 只要它们不大于本机寄存器大小。
【解决方案2】:

我知道整数数据类型占用 2 或 4 个字节的内存

你呢?所有 C 标准规定 int 必须能够存储介于 -32767 和 +32767 之间的数字,并且不小于 shortchar

一个奇异的系统甚至可能在int 的末尾有未使用的填充位。在接下来的几年里,我们很可能会看到“正常的”int 是 64 位的。

如果您想尽量减少浪费的空间,请使用signed char 类型。它的范围必须是 -127 到 +127。 sizeof(char) 按标准为 1。使用的位数由CHAR_BIT 给出,通常为 8。

最后请注意,最小化空间可能对执行速度几乎没有影响,尤其是在 C 中,其中int 通常是 CPU 的本机类型,而比int 更窄的类型在大多数情况下都会扩大到int C 中的表达式。

【讨论】:

  • long long 类型是在 C 和 C++ 中引入的,只是为了不“污染”int,它已经是一个可怕的类型。因此,int 似乎不太可能变成 64 位,除非编译器实现当然是由白痴编写的(标准不禁止)。如果我们曾经飞跃到 128 位计算机,我想会有一个 long long long 类型。
  • @lundin “编译器实现是由白痴编写的(标准不禁止)。” - 我喜欢那个。
  • 我们似乎已经有一些编译器使long 64 位。这些都是白痴写的——符合 ISO 标准的白痴。
  • @Lundin 我真的不同意长期拥有 64 位。 现在是一个问题,涉及可移植性(通过系统和旧代码),以及某些功能(例如htonl)。从长远来看,我宁愿认为这是一个很好的步骤:为什么我们应该有两种不同的类型(int 和 long),它们的宽度完全相同? [...]
  • @Lundin 帮不上忙,根据您的最后评论,我什至觉得自己被逼到了 my 点……我完全同意这一点,我唯一不同意的是那些长 64 位宽是白痴 - 因为在应用了这个的具体系统上,这一步可能是合适的......
【解决方案3】:

要确定浪费了多少空间,如果有的话,您需要考虑要存储在 int 变量中的值的范围,而不仅仅是当前值。

如果您的int 大小为 32 位,并且您希望在其中存储介于 -2,000,000,000 和 2,000,000,000 之间的正负值,那么您需要全部 32 位,因此您的 @ 中没有任何位987654323@ 被浪费了。另一方面,如果范围是 -30,000 到 30,000,那么您可以使用 16 位数据类型,因此浪费了两个字节。

请注意,有时“浪费”几个字节会提高速度,因为较大的大小恰好是 CPU 寄存器的“本机”大小。在这种情况下,“浪费”变成了“权衡”,因为您可以通过使用额外的内存空间获得额外的速度。

【讨论】:

    【解决方案4】:

    实际上是的,因为您要存储的值可以用更少的内存来表示。

    我的意思是,如果您只想表示二进制值 0 和 1,那么一位就足够了。使用超过一位的内存来表示这些值的所有内容都会消耗额外的内存。

    这就是为什么有些人将小值存储到chars。

    【讨论】:

      【解决方案5】:

      “wasted”是错误的词 - 一个类型的所有二进制数字的值都是有意义的。但是,对于可能值的有限范围,您可以选择使用较小的类型。例如char 也是一个整数类型,通常(尽管不是普遍的)8 位。

      如果您想明确存储大小要求,请使用 stdint.h 类型,例如 uint8_tint8_tuint16_tint16_t 等。

      也就是说,在可能的平台上,使用尽可能小的类型通常是有限的,因为处理器数据对齐和低效率的寄存器存储要求在任何情况下都可能由于架构限制或性能效率而“浪费”空间。

      另一方面,如果您正在编写文件记录或实现通信数据包,例如,对齐可能不是架构问题,那么使用较小的数据类型可能会显着提高空间和 I/O 性能。

      您还可以使用位域来指定表示一个值所需的最小数。但是您在存储中保存的内容可能会抵消为访问位域而生成的其他代码,并且对齐和打包仍然依赖于编译器/架构,因此不会有任何保存。

      【讨论】:

        【解决方案6】:

        通常char,short,int`` long,long long,floatdouble(具有相对无符号类型)具有特定数量的字节,如下所述 [link] [ 1 ].

        例如,对于计算,一个字符需要 2 个字节(通常是 1 个字节)。例如,ARM 架构有一个特定的汇编指令来操作 16 位内存位置;编译器可以选择采用 2 个字节作为速度和空间。但是,程序员不必担心进行转换,因为编译器会进行转换。 在这种情况下,您的代码中不会使用额外的字节。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-06-23
          • 2011-08-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-19
          • 2012-04-07
          相关资源
          最近更新 更多