大多数编译器会自动将数据值与平台的字长或数据类型的大小对齐,以较小者为准。绝大多数消费者和企业处理器使用 32 位字长。(即使是 64 位系统通常也使用 32 位作为本机字长)
因此,结构中成员的排序可能会浪费一些内存。在你的具体情况下,你很好。我将在评论中添加已用内存的实际占用空间:
typedef struct structc_tag{
char c; // 1 byte
// 3 bytes (padding)
double d; // 8 bytes
int s; // 4 bytes
} structc_t; // total: 16 bytes
此规则也适用于结构,因此即使您重新排列它们以使最小的字段位于最后,您仍将拥有相同大小(16 字节)的结构。
typedef struct structc_tag{
double d; // 8 bytes
int s; // 4 bytes
char c; // 1 byte
// 3 bytes (padding)
} structc_t; // total: 16 bytes
如果您要声明更多小于 4 字节的字段,如果按大小将它们分组在一起,您可能会看到一些内存减少。例如:
typedef struct structc_tag{
double d1; // 8 bytes
double d2; // 8 bytes
double d3; // 8 bytes
int s1; // 4 bytes
int s2; // 4 bytes
int s3; // 4 bytes
short s4; // 2 bytes
short s5; // 2 bytes
short s6; // 2 bytes
char c1; // 1 byte
char c2; // 1 byte
char c3; // 1 byte
// 3 bytes (padding)
} structc_t; // total: 48 bytes
声明一个愚蠢的结构可能会浪费大量内存,除非编译器重新排序您的元素(通常不会,除非被明确告知)
typedef struct structc_tag{
int s1; // 4 bytes
char c1; // 1 byte
// 3 bytes (padding)
int s2; // 4 bytes
char c2; // 1 byte
// 3 bytes (padding)
int s3; // 4 bytes
char c3; // 1 byte
// 3 bytes (padding)
} structc_t; // total: 24 bytes
// (9 bytes wasted, or 38%)
// (optimal size: 16 bytes (1 byte wasted))
双精度大于 32 位,因此根据第一节中的规则,是 32 位对齐的。有人提到了一个改变对齐方式的编译器选项,并且默认编译器选项在 32 位和 64 位系统之间是不同的,这也是有效的。所以关于双打的真正答案是它取决于平台和编译器。
内存性能由单词控制:从内存加载取决于数据的位置。如果数据包含一个字(即字对齐),则只需加载该字。如果它没有正确对齐(即 0x2 处的 int),处理器必须加载 2 个字才能正确读取其值。这同样适用于双精度,通常占用 2 个字,但如果未对齐,则占用 3。在 64 位系统上,可以本地加载 64 位数量,它们的行为类似于 32 位系统上的 32 位整数,如果正确对齐,它们可以一次加载,但否则,它们将需要 2 个。