我读到内存被安排为32位处理器中的4个字节组和来自http://fresh2refresh.com/c-programming/c-structure-padding/的64位处理器中的8个字节,但没有说明这两者之间的区别。
struct structure2
{
int id1;
char name;
int id2;
char c;
float percentage;
};
答案 0 :(得分:2)
通过32位处理器(更具体地说,它是关于数据总线的大小而不是寄存器的大小),这意味着一次将读取和处理32位(4字节)的数据。
现在,考虑一下int:
int a=10; //assuming 4 bytes
00000000 000000000 00000000 00001010
假设小端架构,它将存储为:
------------------------------------------------------------------------
| 00001010 | 00000000 | 00000000 | 00000000 | <something_else>
-------------------------------------------------------------------------
1st byte 2nd byte 3rd byte 4th byte
\--------------------------------------------------/
|
4 bytes processed together
在这种情况下,当处理器读取要处理的数据时,它可以一次性处理整个整数(所有4个字节一起)(更严格地说,在1个机器周期内)
但是考虑存储相同整数的情况,
------------------------------------------------------------------------
|<something_else>| 00001010 | 00000000 | 00000000 | 00000000 |
-------------------------------------------------------------------------
1st byte 2nd byte 3rd byte 4th byte
\------------------------------------------------------/
|
4 bytes processed together
在这种情况下,处理器需要2个机器周期来读取整数。
大多数架构总是尽量减少CPU周期。
因此,许多编译器首选存储器中的第一种布置,因此强制执行对齐要求(填充)。
因此,4个字节int
存储在从4的倍数开始的地址中,chars
存储在1的多个中,8个字节doubles
存储在8个的多个中,8个字节{{1多个8s等等......
现在考虑一下你的结构
long long int
id1 将存储在内存中的某个地址(从4开始),占用4个字节。
名称将占用下一个字节。
现在如果 id2 存储在下一个字节中,它将破坏上面的对齐规则。因此它将保留3个字节的填充并从adress开始存储,这是4的下一个倍数,将占用4个字节。
对于 c ,同样的事情发生在 name 上。接下来需要1个字节并保留3个字节的填充。
最后百分比会存储在接下来的4个字节中。
所以结构的总大小变为 20字节。
更复杂的案例会说
struct structure2
{
int id1; //assuming 4 byte int
char name; // 1byte
int id2; //4 byte
char c; // 1 byte
float percentage; //assuming 4 byte float
};
这里可能乍一看说大小将 20个字节(char为1个字节+ 7个字节填充+ 0个字节用于double + 4个字节用于int)。
但实际大小为 24字节。
说某人声明了这个结构的数组
struct mystructure
{
char a; //1 byte char
double b; // 8 byte double
int c; // 4 byte int
}
这里(假设20字节结构)虽然arr [0]正确对齐,但如果仔细检查,你会发现arr [1] .b未对齐。因此,在结构的末尾添加了4个字节的额外填充,以使结构大小为其对齐的倍数。(每个结构也有自己的对齐要求)。
因此总大小为24字节。
整数的大小,长整数等由编译器决定。编译器通常负责处理器体系结构,但可以选择不使用。
类似地,是否使用填充是由编译器决定的。不填充称为包装。有些编译器有明确的选择允许打包。
在GCC(GNU C编译器)中,您可以使用struct mystructre arr[4];
执行此操作,因此在以下代码中
__attribute__((__packed__))
mystructure2的大小为6个字节,因为显式请求打包结构。此结构处理速度。
你现在可能已经想到了,64位处理器会发生什么,或者int的大小是不同的。
答案 1 :(得分:0)
本网站并不准确确切地使用哪种64位平台,但似乎假设ILP64(int
,long
和指针是64位)平台,长度对齐的整数。这意味着int
在32位处理器上是4个字节,在64位处理器上是8个字节,每个字节必须在其自身长度的倍数上对齐。
结果是name
和id2
之间填充的长度发生了变化(保留id2
对齐所需的填充)。
在32位平台上,将有三个字节的填充;在64位平台上,将有七个。
c
和percentage
之间的填充可能不会改变,因为浮点变量的大小不受处理器位数的影响。