基本对齐原则
1)结构体内成员按自身按自身长度自对齐(该成员的起始位置的内存地址必须是它自身长度的整数倍)。
2)结构体的总大小为结构体的有效对齐值的整数倍
结合以上原则,可以知道
char - 位于1的整数倍地址,也就是从0-9(几任何起始地址)
short - 位于2的整数倍地址,也就是0、2、4...这类地址
int - 位于4的整数倍地址,也就是0、4、8...这类地址
结构体的有效对齐值
1)当未明确指定时,以结构体中最长的成员的长度为其有效值
2)当用#pragma pack(n)指定时,以n和结构体中最长的成员的长度中较小者为其值。
3)当用__attribute__ ((__packed__))指定长度时,强制按照此值为结构体的有效对齐值
4)如果pragma pack和__attribute__同时指定则以__attribute__ 的为准
-----------------------------------------------------分割线---------------------------------------------------------------------------
具体例子如下
1. 简单结构体
#include <stdio.h>
typedef struct _X_ {
char a; // 0
short b; // 2
short c; // 4
int d; // 8
char e; // 12
} X;
typedef struct _Y_ {
short a; // 0
char b; // 2
int c; // 4
char d; // 8
short e; // 10
} Y;
int main(void){
X x;
Y y;
// x
printf("#####x#####%ld\n", sizeof(x));
printf("%p-%ld, %p-%ld, %p-%ld, %p-%ld, %p-%ld\n", &x.a, sizeof(x.a), \
&x.b, sizeof(x.b), &x.c, sizeof(x.c), &x.d, sizeof(x.d), &x.e, sizeof(x.e));
// y
printf("#####y#####%ld\n", sizeof(y));
printf("%p-%ld, %p-%ld, %p-%ld, %p-%ld, %p-%ld\n", &y.a, sizeof(y.a), \
&y.b, sizeof(y.b), &y.c, sizeof(y.c), &y.d, sizeof(y.d), &y.e, sizeof(y.e));
return 0;
}
运行结果
详细分析
按照类型自对齐和结构体对齐原则,可以知道X会按4直接对齐
2. #pragma pack(n)强制对齐
#include <stdio.h>
#pragma pack(2)
typedef struct _X_ {
char a;
short b;
short c;
int d;
char e;
} X;
typedef struct _Y_ {
short a;
char b;
int c;
char d;
short e;
} Y;
int main(void){
X x;
Y y;
// x
printf("#####x#####%ld\n", sizeof(x));
printf("%p-%ld, %p-%ld, %p-%ld, %p-%ld, %p-%ld\n", &x.a, sizeof(x.a), \
&x.b, sizeof(x.b), &x.c, sizeof(x.c), &x.d, sizeof(x.d), &x.e, sizeof(x.e));
// y
printf("#####y#####%ld\n", sizeof(y));
printf("%p-%ld, %p-%ld, %p-%ld, %p-%ld, %p-%ld\n", &y.a, sizeof(y.a), \
&y.b, sizeof(y.b), &y.c, sizeof(y.c), &y.d, sizeof(y.d), &y.e, sizeof(y.e));
return 0;
}
运行结果
详细分析
#pragma pack(2)强制2直接对齐,结构体默认最大对齐为4,因此综合可知:结构体按照2对齐
2.__attribute__ ((__packed__))强制对齐
#include <stdio.h>
struct X {
char a;
int b;
short c;
} __attribute__((__8__))x;
struct Y {
char a;
int b;
short c;
} __attribute__((__2__))y;
int main(void){
// x
printf("#####x#####%ld\n", sizeof(x));
printf("%p-%ld, %p-%ld, %p-%ld\n", &x.a, sizeof(x.a), \
&x.b, sizeof(x.b), &x.c, sizeof(x.c));
// y
printf("#####y#####%ld\n", sizeof(y));
printf("%p-%ld, %p-%ld, %p-%ld\n", &y.a, sizeof(y.a), \
&y.b, sizeof(y.b), &y.c, sizeof(y.c));
return 0;
}
运行结果
此段程序仅支持特定平台,比如ARM,X86版本GCC会忽略此强制对齐,造成两个两个相同,运行结果暂无
详细分析
暂无
参考:https://blog.youkuaiyun.com/xiong452980729/article/details/70140050