我正试图根据结构的成员来理解结构的大小,正如一个关于数据对齐的简短教程所描述的那样(参见here。该文章指出“所有数据在结构中自然对齐。如果type
位于地址0,则以下double x
位于地址8的偏移量8,依此类推。因此,即使这个结构只包含37字节的有意义数据,它的大小也是48。是的,如果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;
}
2条答案
按热度按时间ibrsph3r1#
使用原始字节顺序,我们需要:
char type
的一个字节。double
与8个字节的倍数对齐。double x,y
中的x
和y
各8个字节。float m
的四个字节。float
与八个字节的倍数对齐。double vx,vy
中的vx
和vy
各8个字节。即1+7+16+4+4+16 = 48字节。
移动
float
后,我们需要:char type
的一个字节。float
与四个字节的倍数对齐。float m
的四个字节。double x,y
中的x
和y
各8个。double vx,vy
中的vx
和vy
各8个字节。即1 + 3 + 4 + 16 + 16 = 40字节。
注意,
float
和double
之间不需要字节,因为float
以8字节的倍数结束。sdnqo3pr2#
你要找的答案实际上在你链接的文章中提到了:
例如,如果用于标识8字节浮点数据的地址与八(8)对齐,则该数据自然对齐
如果
type
是第二个成员,则结构体已经占用了1个字节,因此下一个可用于自然对齐的位置是下一个8的倍数。为了自然对齐,您实际上跳过了7个字节,这可以容纳整个浮点数。由于float m
只需要4个字节,因此它可以在type
和x
之间自然对齐。