6

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

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

8 回答 8

6

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

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

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

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

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

于 2010-05-06T14:38:06.043 回答
5

计算机内存被组织成“字”,即给定大小(通常是 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 位而不是单个指令或内存访问。

于 2010-05-06T14:35:49.090 回答
1

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

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

0x0001 
0x0010 
0x0100 
0x1000 

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

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

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

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

于 2010-05-06T14:31:02.203 回答
1

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

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

于 2010-05-06T14:32:00.717 回答
1

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

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

于 2010-05-06T14:35:24.400 回答
0

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

于 2010-05-06T14:39:31.610 回答
0

这和内存有什么关系?

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

于 2010-05-06T14:32:30.033 回答
0

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

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

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

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

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

move.l
move.w
move.b

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

于 2010-05-06T14:33:24.900 回答