我试图根据它的成员了解结构的大小,如数据对齐的简短教程所述(请参阅here。文章指出“所有数据在结构内自然对齐。如果
type
位于地址 0 下面的 double x
位于地址 8 的偏移量为 8,依此类推。因此,这个结构的大小是 48,即使它只包含 37 个字节的有意义的数据。是的,如果 float m
跟随在 type
之后,m 的偏移量将为 4,结构的大小将减少到 40。”句子
是的,如果 float m 直接跟在 type 之后,m 的偏移量将为 4,结构的大小将减少到 40。
对我来说没有意义。为什么仅仅因为成员的顺序改变了结构大小就减少到 40?是因为
double vy
偏移了 40 个字节,然后填充了额外的 8 个字节,导致结构大小为 48 吗?而如果 float m
直接跟在 type
之后,double vy
的偏移量只有 32 个字节,然后再添加 8 个字节导致结构大小为 40?
我写了一个小的 C 程序来仔细检查结构成员的对齐方式:
/*Outputs:
particle one alignment:
type 0
x 8
y 16
m 24
vx 32
vy 40
struct size --> 48
particle two alignment:
type 0
m 4
x 8
y 16
vx 24
vy 32
struct size --> 40
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct ParticleOne {
char type;
double x,y;
float m; // after `y` member
double vx, vy;
} ParticleOne;
typedef struct ParticleTwo {
char type;
float m; // after `type` member
double x,y;
double vx, vy;
} ParticleTwo;
int main() {
ParticleOne *particle_one = malloc(sizeof(ParticleOne));
ParticleTwo *particle_two = malloc(sizeof(ParticleTwo));
// Particle one alignment/offset information
void *p1_type = &particle_one->type;
void *p1_x = (void*)&particle_one->x - p1_type;
void *p1_y = (void*)&particle_one->y - p1_type;
void *p1_m = (void*)&particle_one->m - p1_type;
void *p1_vx = (void*)&particle_one->vx - p1_type;
void *p1_vy = (void*)&particle_one->vy - p1_type;
printf("particle one alignment:\n");
printf("type %d\n", p1_type - p1_type);
printf("x %d\n", p1_x);
printf("y %d\n", p1_y);
printf("m %d\n", p1_m);
printf("vx %d\n", p1_vx);
printf("vy %d\n", p1_vy);
printf("struct size --> %d\n", sizeof(ParticleOne));
// Particle two alignment/offset information
void *p2_type = &particle_two->type;
void *p2_x = (void*)&particle_two->x - p2_type;
void *p2_y = (void*)&particle_two->y - p2_type;
void *p2_m = (void*)&particle_two->m - p2_type;
void *p2_vx = (void*)&particle_two->vx - p2_type;
void *p2_vy = (void*)&particle_two->vy - p2_type;
printf("particle two alignment:\n");
printf("type %d\n", p2_type - p2_type);
printf("m %d\n", p2_m);
printf("x %d\n", p2_x);
printf("y %d\n", p2_y);
printf("vx %d\n", p2_vx);
printf("vy %d\n", p2_vy);
printf("struct size --> %d\n", sizeof(ParticleTwo));
return 0;
}
有了原始的字节序,我们需要:
char type
.double
对齐到八个字节的倍数。x
和y
各8个字节,double x,y
.float m
.float
对齐到八个字节的倍数。vx
和vy
各8个字节,double vx,vy
.即1+7+16+4+4+16 = 48字节。
随着
float
的移动,我们需要:
char type
.float
对齐到四个字节的倍数。float m
.x
和y
各8个字节,double x,y
.vx
和vy
各8个字节,double vx,vy
.即 1 + 3 + 4 + 16 + 16 = 40 字节。
观察到
float
和 double
之间不需要字节,因为 float
以八字节的倍数结束。
你要找的答案实际上在你链接的文章中提到了:
例如,如果用于标识它的地址与八 (8) 对齐,则自然对齐一个 8 字节的浮点数据
如果
type
是第二个成员,该结构已经占用了1个字节,所以下一个可用于自然对齐的位置是下一个八的倍数。为了自然对齐,您实际上跳过了 7 个字节,这可以适合整个浮点数。由于float m
只需要4个字节,所以可以在type
和x
之间自然对齐。