理解32位C编译器中的sizeof(char)

(sizeof)char总是在32位GCC编译器中返回1

但由于32位编译器的基本块大小为4,当基本大小为4字节时,char如何占用单个字节?

考虑以下因素:

struct st { int a; char c; }; 

sizeof(st)返回为8 ,默认块大小为4字节(因为分配了2个块)

我永远无法理解为什么sizeof(char)在分配大小为4的块时返回为1

有人可以解释这个???

我会非常感谢任何回复解释它!

编辑:’bits’的拼写错误已更改为’bytes’。 我对第一次编辑的人抱歉。 我回滚了编辑,因为我没有注意到你所做的改变。 感谢所有那些明确表示必须改变的人,尤其是@Mike Burton,因为他对这个问题进行了抨击,并且@jalf似乎对我对概念的理解得出了结论!

sizeof(char)总是1. Always。 您正在谈论的“块大小”只是机器的本机字大小 – 通常是导致最有效操作的大小。 您的计算机仍然可以单独处理每个字节 – 这就是sizeof运算符告诉您的内容。 当你执行sizeof(int) ,它返回4以告诉你int在你的机器上是4个字节。 同样,您的结构长度为8个字节。 sizeof没有关于字节中有多少位的信息。

你的结构长8个字节而不是5个(正如你所料)的原因是,编译器正在为结构添加填充 ,以便将所有内容与原生字长保持良好对齐,再次提高效率。 大多数编译器都允许您使用#pragma指令或其他编译器扩展来打包结构,在这种情况下,无论机器的字长如何,您都可以强制使用最小的结构。

char的大小为1,因为这是计算机可以处理的最小访问大小 – 对于大多数计算机而言是8位值。 sizeof运算符为您提供所有其他数量的大小,以您所询问的数量为单位的char对象的大小。 由于性能原因,编译器将填充 (请参阅下面的链接)添加到您的数据结构中,因此它在实践中比您只考虑结构定义时想象的要大。

有一个名为数据结构对齐的维基百科文章,它有一个很好的解释和例子。

它是结构对齐。 c使用1个字节,3个字节未使用。 更多(图片!)

示例结构对齐的示例代码:

 struct st { int a; char c; }; struct stb { int a; char c; char d; char e; char f; }; struct stc { int a; char c; char d; char e; char f; char g; }; std::cout< 

struct的大小大于其各个组件的总和,因为它被32位编译器设置为可被4字节整除。 这些结果可能在不同的编译器上有所不同,特别是如果它们在64位编译器上。

首先, sizeof返回多个字节 ,而不是位。 sizeof(char) == 1告诉您char长度为8位(一个字节)。 C中的所有基本数据类型至少有一个字节长。

您的结构返回大小8.这是三件事的总和: int的大小, char的大小(我们知道为1 ),以及编译器添加到结构中的任何额外填充的大小。 由于许多实现使用4字节的int ,这意味着您的编译器正在为您的结构添加3个字节的填充。 很可能这是在char之后添加的,以使结构的大小为4的倍数(32位块中的32位CPU访问数据最有效,32位是4个字节)。

编辑:只是因为块大小是四个字节并不意味着数据类型不能小于四个字节。 当CPU将一个字节的char加载到32位寄存器中时,该值将自动(由硬件)进行符号扩展,以使其填充寄存器。 CPU足够智能,可以以N字节为增量处理数据(其中N是2的幂),只要它不大于寄存器即可。 将数据存储在磁盘或内存中时,没有理由将每个char存储为四个字节。 你的结构中的char看起来好像是四个字节长,因为它后面添加了填充。 如果您将结构更改为具有两个 char变量而不是一个,则应该看到结构的大小相同(您添加了额外的数据字节,并且编译器添加了少一个填充字节)。

C和C ++中的所有对象大小都是以字节而不是来定义的。 字节是计算机上最小的可寻址内存单位。 一位是单个二进制数字, 01

在大多数计算机上,一个字节是8位(因此一个字节可以存储0到256之间的值),尽管计算机存在其他字节大小。

即使在32位计算机上,内存地址也标识一个字节 。 地址N和N + 1指向两个后续字节。

一个int ,通常是32位,覆盖4个字节,这意味着存在4个不同的内存地址,每个内存都指向int一部分。

在32位机器中,所有32个实际意味着CPU被设计为使用32位值有效工作,并且地址长度为32位。 这并不意味着只能以32位的块来寻址存储器。

CPU仍然可以处理单个字节,例如,在处理char时这很有用。

至于你的例子:

 struct st { int a; char c; }; 

sizeof(st)返回8不是因为所有结构都有一个可被4整除的大小,而是因为对齐 。 为了使CPU有效地读取整数,它必须位于可被整数大小整除的地址(4个字节)。 因此int可以放在地址8,12或16上,但不能放在地址11上。

char只需要其地址可以被char (1)的大小整除,因此它可以放在任何地址上。

所以从理论上讲,编译器可以给你的结构大小为5个字节……除非你创建了一个st对象数组,否则这个不行。

在一个数组中,每个对象都紧跟在前一个对象之后,没有填充。 因此,如果数组中的第一个对象放置在可被4整除的地址,则下一个对象将放置在高5字节的地址处,该地址不能被4整除,因此数组中的第二个结构将不会被正确对齐。

为了解决这个问题,编译器在struct中插入填充,因此它的大小成为其对齐要求的倍数。

不是因为不可能创建大小不是4的倍数的对象,而是因为st结构的一个成员需要4字节对齐,所以每次编译器在内存中放置一个int时,它必须确保它被放置在可被4整除的地址。

如果你创建一个两个char的结构,它的大小不会是4.它通常会得到2的大小,因为当它只包含char ,对象可以放在任何地址,所以对齐是这不是问题。

Sizeof以字节为单位返回值。 你在谈论比特。 32位架构是字对齐和字节引用。 架构如何存储char是无关紧要的,但对于编译器,您必须一次引用1个字节的字符,即使它们使用的字节少于1个字节。

这就是sizeof(char)为1的原因。

整数是32位,因此sizeof(int)= 4,双精度是64位,因此sizeof(double)= 8等。

由于优化填充被添加,因此对象的大小是1,2或n * 4字节 (或类似的东西,谈论x86)。 这就是为什么添加填充到5字节对象和1字节没有。 单个char不需要填充,它可以在1个字节上分配,我们可以将它存储在使用malloc(1)分配的空间上。 st不能存储在使用malloc(5)分配的空间中,因为正在复制st结构时,正在复制整个8个字节。

它的工作方式与使用半张纸相同。 您将一个部分用于char,另一部分用于其他部分。 编译器将隐藏此信息,因为将字符加载和存储到32位处理器寄存器取决于处理器。

有些处理器只有加载和存储32位部分的指令,其他处理器必须使用二进制操作来提取char的值。

寻址char的工作原理是AFAIR定义为最小的可寻址存储器。 在32位系统上,指向两个不同的int的指针将至少相隔4个地址点,char地址将仅相隔1个。