以下是一个简单的C
程序:
#include <stdio.h>
typedef struct
{
char a;
double b;
} A;
int main(void) {
printf("sizeof(A) is %d bytes\n", sizeof(A));
return 0;
}
当我将其编译成32-bit
程序时,输出为:
sizeof(A) is 12 bytes
我知道结构内存模块应该是:
____________________________
|a|3 padding| b |
————————————————————————————
但是当我把它编译成64-bit
程序时,输出是:
sizeof(A) is 16 bytes
所以结构内存模块应该是:
____________________________________
|a|7 padding | b |
____________________________________
就个人而言,我认为无论该计划是32-bit
还是64-bit
,结构的大小应始终为16
字节(因为char
为1
字节长,double
的对齐是8
字节)。为什么12
程序中的大小为32-bit
个字节?
答案 0 :(得分:2)
在32位和64位计算机上的Intel CPU上,“ SIMD”变体的浮点指令在单个计算机上读/写16个字节(2个双精度)或8个字节(一个双精度)。指令。这些是处理浮点的最常见说明。一切都取决于速度:
可以通过“对齐的读取指令”或“未对齐的读取指令”来读取单个数据项。确保对齐的版本更快。未对齐的指令必须处理复杂的情况,其中数据在两条高速缓存行甚至两个不同的内存页之间分配。 此外,CPU针对某些指令(即对齐的指令)进行了优化。 如此优化,以至于读取1字节的数据比读取16个对齐的字节要花费更多的时间。 8088(MOV AL / MOV AH等)的原始1字节指令未经过硬件优化。
编译器编写者必须选择密集代码或快速代码。在过去,当我的PC拥有16 KB的内存时,内存很少。后来,人们可以指示编译器准确地对齐结构成员。当64位CPU出现时,内存足够便宜,以至于结构的大小变成16字节的倍数,并且每个结构成员都按照其自然边界对齐-根据其类型:短裤的偶数地址,mod(4,0)对于int和float,对于_int64为mod(8,0),对于_mm128为double(mod)(16,0),对于_mm256为mod(32,0)
答案 1 :(得分:1)
这是实施定义。
最后,它取决于访问内存时CPU指令的限制。编译器通常会尝试选择速度最快的布局,然后选择内存使用率第二。
答案 2 :(得分:1)
在深入研究这个问题之后,我想自己回答问题。
我的操作系统是Solaris,这个问题出现在X86
上(Jonathan Leffler的评论是正确的)。当我在SPARC
上测试它时,32位和64位程序输出&#34; sizeof(A) is 16 bytes
&#34;。
我认为原因是:
(1)在X86
上,访问非对齐数据不会导致程序失效,只会影响性能。对于32-bit
程序,CPU指令一次可以访问4-byte
内存,因此访问8-byte double
将使用2
指令,无需对齐数据。但是对于64-bit
程序,CPU指令一次可以访问8-byte
内存,因此对齐8-byte double
将仅使用1
指令来获取数据,这将改善性能。
(2)Ox SPARC
,数据需要严格对齐,否则将导致&#34; Bus error
&#34;。因此,在7
数据之前始终有double
个填充字节,以使其在8-byte
地址上对齐。
简单来说,此问题取决于CPU
,因为user694733已经回答。