【问题标题】:Can RAM handle different data type sizes?RAM 可以处理不同的数据类型大小吗?
【发布时间】:2011-02-16 10:21:09
【问题描述】:

int、char 和 bool 通常具有不同的大小。我想在哪里 int>char>bool。

  • 但是 RAM 甚至支持这个吗?
  • 它是如何构建的?
  • 它能否利用 bool 只有 1 个字节并将其存储在一个小的“寄存器”中?

【问题讨论】:

  • 对于回答我的人不必介意,有足够的空间:谢谢,我知道 - 但我很好奇:)
  • 它不由 RAM 处理,处理器通常一次将 16 个字节的块读取到缓存中。一个大的多路复用器将正确的字节从那里洗牌到 CPU 寄存器中。洗牌一个字节的时间和一个 int 一样长。
  • 你有没有成功解决过这个问题?您还需要这方面的帮助吗?

标签: c++ ram


【解决方案1】:

大概你的意思是缓存?只是好奇你为什么担心数据结构的大小,你是为嵌入式编程吗?这通常是唯一值得担心的内存占用情况。

如果您有多个要同时维护的位域,您可以使用一个字节作为位域并记住像

这样的值
0x0001 
0x0010 
0x0100 
0x1000 

彼此独立,可以独立于其他人进行检查。人们一直这样做是为了节省一点空间。这就是你想要弄清楚的吗?

例如,如果每个 bool 占用一个字节的空间,那么显然每个字节只使用一个位。所以如果你将 8 位链接在一起,它只会消耗一个字节的空间。

但不要忘记内存中的每个变量也有某种编组(在 .NET 中比在“较低”级别的语言中更明显,但总会有一些东西跟踪正在使用的变量)。所以就像在 C# 的情况下,一个字节实际上需要 3 个字节的 RAM。

但是 RAM 是由块传输的,据我所知,它比单个字节大得多。通常至少以字为单位来衡量,正常大小是一次 32、64 或 128 位。这些数字取决于平台。

【讨论】:

  • 2 次方的十六进制数能达到同样的效果吗?即:0x00010x00020x00040x00080x0010
  • 因为十六进制数字是二进制的简写,所以是的。这都是关于二进制位置的。此外,0x0003 将是第一个和第二个位置为真/设置的简写。
  • 对。另一个问题是,两个十六进制数字不会组成一个字节吗?您的示例对一个字段使用半字节。这不是那么重要。 =]
  • 哦,那是因为这是一个人为的例子,旨在展示基本概念。事实上,一个字节是取决于大小的平台。我们“假设”它的大小是 8 字节,但我们并没有针对所有平台的严格规定。我只是想展示他们是如何排列的。
  • 嗯?疯了……我想我会留意这种稀有的。
【解决方案2】:

如果您所说的“支持”是指机器中的 RAM 是否具有匹配每个大小的本机存储单元,则答案是“这取决于机器和编译器”。

现代机器的最小可寻址存储大小通常是 8 位(8/16/32/64 位)的倍数。编译器可以使用任何这些大小来存储和操作数据。编译器可以优化存储和寄存器使用,但并非必须如此。

【讨论】:

    【解决方案3】:

    这与 RAM 有什么关系?

    bool 可以为真或假,通常表示为 0 或 1(1 位)。 一个 char 可以有不同的大小,这取决于所使用的字符集。 ASCII 使用 7 位。 Unicode 最多使用 32 位。 整数是整数,通常支持 -2^31....2^31-1(32 位)的范围,但它们也有其他大小。

    【讨论】:

    • 在内存中,一个布尔值通常占用一个完整的字节。因为处理器和内存管理器处理一个字节比处理一个比特要容易得多。
    • 现在布尔值甚至经常“使用”32 位甚至 64 位,但这只是为了提高效率而进行的填充。同时,您不应该忘记“标志”,它们也不过是一堆布尔值。布尔值本身仍然只使用一位。内存布局取决于平台和编译器。
    【解决方案4】:

    如果您愿意,您可以使用 C++ 位域,但您将是这个星球上少数几个这样做的人之一(从技术上讲,位域在 C 中定义良好,但从未真正使用过)

    C++ 编译器对您隐藏 RAM 的访问方式是有充分理由的。在某些情况下,您希望对此进行优化,但这种情况极为罕见。在当今客户端 PC 中大量 RAM 的世界中,微优化是不值得的。

    通常,您应该相信您的(优化)编译器会做正确的事情。您提供给编译器的源代码只是模糊地类似于编译器生成的机器代码。如果您的编译器很好,那么微优化会很有帮助,这是一个神话。您必须确切地知道编译器在优化过程中需要帮助的地方,才能比编译器优化得更好。如果编译器认为您的代码太复杂而无法优化,您甚至可以使事情变得更糟。

    如果你想要一些技术背景:

    在机器语言级别上,它取决于处理器。例如,摩托罗拉 680x0 系列处理器允许您做

    move.l
    move.w
    move.b
    

    读取和写入 RAM 的不同“单元”(长/字/字节)。处理器在其 RAM 上的外观会有所不同,具体取决于它处理的指令。一些嵌入式处理器甚至可能使用 4 位作为它们的最小单位。

    【讨论】:

      【解决方案5】:

      RAM 并不真正关心数据类型的大小。它只是以字节为单位存储数据。 CPU 控制基本数据类型,知道它们有多少字节。例如,在创建 int 时,CPU 决定使用 4 或 8 字节(分别为 32 或 64 位架构)

      无法寻址一位,但您可以创建一个自定义结构,将 8 个布尔值存储在一个字节中。在 C++ 中,您可以使用位域来使用它。

      【讨论】:

      • 另外,STL 的bitset 对于处理节省空间的布尔值数组很有用。
      【解决方案6】:

      计算机内存被组织成“字”,即给定大小的字节序列(通常是 2 次方)。内存通常以这些单元读取和写入,这些单元通常与寄存器的大小和 CPU 对算术运算符的本机支持兼容。这通常是机器“比特等级”的来源(例如,32 位 CPU、64 位 CPU、旧的 8 位视频游戏机)。

      当然,您通常需要与原生字号不同的字号。机器指令和智能编码允许您通过应用各种位级逻辑运算符将这些单词分解成更小的单元,或者通过“组合”多个单词将它们组合成更大的单元。

      例如,如果您有一个 32 位字,您可以将一个字与 0xff0000ff 之类的模式相结合以获取该字中的第一个和最后一个字节,或者 0x0000ffff 仅获取第二个 16 位 int 的内容。

      在布尔的情况下,通常将内存用作位图。您基本上可以将 X 个“布尔值”放在 X 位字中,并通过与引用该布尔值的“掩码”进行与或或运算来访问特定位。例如,第一位为 1,第二位为 2,第四位为 4,等等。

      在大多数机器中,不建议将较小的数据类型拆分为两个单词(这称为对齐)。

      当您使用 C 或 C++ 等高级语言时,您通常不必担心所有这些内存组织问题。如果分配一个 int、一个 short 和一个 double,编译器将生成适当的机器代码。仅当您希望在动态分配的内存中巧妙地组织事物时,才直接执行此操作,例如手动实现位图时。

      当使用比原生字长更大的单位时,编译器会再次为您处理大部分事情。例如,在 32 位机器上,您可以轻松处理 32 位 int 操作,但要在 8 位机器或 16 位机器上运行相同的代码,编译器会生成代码来执行较小的操作并将它们组合起来得到结果。这就是为什么通常认为建议在 64 位机器上运行 64 位操作系统的部分原因,因为否则您可能会在 32 位操作系统上执行多个指令和读/写来模拟 64 位而不是单个指令或内存访问。

      【讨论】:

        【解决方案7】:

        在普通的现代计算机上,所有内存都是字节可寻址的。也就是说,RAM 中的每个字节大小的存储位置都分配有一个唯一编号。如果您想存储一个单字节的值,例如 bool(尽管在 C++ 中 bool 不是要求是一个字节,但它们通常是),它需要一个存储位置,比如位置 42。

        如果你想存储大于一个字节的东西,比如int,那么它将占用多个连续的存储位置。例如,如果您的 int 类型为 16 位(2 字节)长,则其中一半将存储在位置 42 中,另一半存储在位置 43 中。这可以推广到更大的类型。假设您有一个 64 位(8 字节)long long int 类型。这种类型的值可能存储在位置 42、43、44、45、46、47、48 和 49 之间。

        有一些更高级的注意事项称为“对齐”,某些类型的处理器需要遵守这些注意事项。例如,处理器可能有一个规则,即两字节值必须从偶数地址开始,或者四字节值必须从可被 4 整除的地址开始。您的编译器将处理此细节给你。

        编译器也知道每种类型的长度,所以当它为你的程序生成机器码时,它会知道每个变量的存储从哪个地址开始,它会知道变量存储在多少个连续字节中.

        另一方面,“寄存器”是存在于处理器中而不是 RAM 中的东西,并且通常是固定大小的。处理器寄存器的一种用途是存储从 RAM 中检索到的值。例如,如果您的处理器有 32 位(4 字节)寄存器,则从 RAM 加载的bool 值仍将消耗整个 4 字节寄存器,即使它在 RAM 中时仅消耗一个字节。

        【讨论】:

        • 这实际上不是真的,但是 CPU 让它看起来像那样。在普通的现代计算机上,RAM 被组织在 DIMM 模块中。您无法寻址 DIMM 的单个字节,只有 8 字节/64 位。
        • 嗯,这取决于你说的水平。如果您正在谈论处理器接受哪些类型的地址(这是程序员通常会关心的最低级别),那么内存确实是字节可寻址的,即使在较低的硬件级别,这可能并非如此。
        • 这是对具有字节可寻址内存的“普通”现代 ISA 的一个很好的总结。它没有必须那样,您可以设计一台机器,其中最小的可寻址单元是一个字(16 位或 32 位)。一些现代 DSP 仍然这样做。是的,很好地简化了缓存的现实;具有高速缓存和/或智能内存控制器present a byte-oriented view of memory 的 CPU,即使底层 DRAM 仅支持至少 8 字节的突发传输。没有缓存的 CPU 通常在总线上有启用/禁用信号以支持字节存储。
        【解决方案8】:

        大多数商品硬件都有字节可寻址内存。再深入一点,我们会看到 CPU 寄存器具有位宽(日常内容为 32 或 64 位)。然后缓存和总线在这些块(64 或 128 个字节)上运行。您可以尝试利用这一点,但您需要非常详细地了解硬件,并且您会将自己绑定到特定平台。另一方面,您不必利用这一点,因为您的编译器已经这样做了。

        【讨论】:

          猜你喜欢
          • 2021-08-19
          • 2017-02-10
          • 1970-01-01
          • 1970-01-01
          • 2011-03-08
          • 2018-07-07
          • 2019-05-04
          • 1970-01-01
          • 2021-12-22
          相关资源
          最近更新 更多