一。C语言结构体中的内存对齐如何计算
规则一:第一个成员在结构体变量偏移量为0的地址处
规则二: 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处
对齐数 =编译器默认对齐数 与 该成员大小 比较后 取较小值
默认对齐数:Linux中4字节,VS中8字节;
规则三 :结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍
规则四:如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
typedef struct Student {
char sex; 占用1个字节 第1字节
char sex1; 按照规则2,该成员占用1个字节 < vs中的8个字节,因此对齐数为1,,对齐到1的整倍数的字节处,即第二个字节。 第 2字节
char sex2; // 按照规则2,该成员占用1个字节 < vs中的8个字节,因此对齐数为1,,对齐到1的整倍数的字节处,即第三个字节。 第 3字节
//第4个字节没有用,空闲
int age ; // 按照规则2,该成员占用4个字节 < vs中的8个字节,因此对齐数为4,,对齐到4的整倍数 第五个字节。 第5-8字节
char name[6] ;//该成员是字符数组,要一个一个的看,数组中的每一个成员都是char,占用1个字节,小于 vs中的8个字节,对齐数为1,占用 9 - 14个字节
//第15,16 字节没有用,空闲
int age2; // // 按照规则2,该成员占用4个字节 < vs中的8个字节,因此对齐数为4,,对齐到4的整倍数 ,1-14已经用了,就只能对齐到17了。占用17-20字节
char name2[3];//3 //该成员是字符数组,要一个一个的看,数组中的每一个成员都是char,占用1个字节,小于 vs中的8个字节,对齐数为1,占用 21 - 23个字节
//第24 字节没有用,空闲
char * address;//8 占用8,= vs中的8个字节,因此对齐数为8,25-32个字节。
//总和为:4+4+8+4+4+8 = 32字节
}_Student;
typedef struct Student {
char sex;//占用1个字节 第1字节
char sex1;//按照规则2,该成员占用1个字节 < vs中的8个字节,因此对齐数为1,,对齐到1的整倍数的字节处,即第二个字节。 第 2字节
char sex2;// 按照规则2,该成员占用1个字节 < vs中的8个字节,因此对齐数为1,,对齐到1的整倍数的字节处,即第三个字节。 第 3字节
//第4个字节没有用,空闲
int age;//按照规则2,该成员占用4个字节 < vs中的8个字节,因此对齐数为4,,对齐到4的整倍数 第五个字节。 第5-8字节
char name[6];//该成员是字符数组,要一个一个的看,数组中的每一个成员都是char,占用1个字节,小于 vs中的8个字节,对齐数为1,占用 9 - 14个字节
//第15,16 字节没有用,空闲
int age2; // 按照规则2,该成员占用4个字节 < vs中的8个字节,因此对齐数为4,,对齐到4的整倍数 ,1-14已经用了,就只能对齐到17了。占用17-20字节
char name2[3];//该成员是字符数组,要一个一个的看,数组中的每一个成员都是char,占用1个字节,小于 vs中的8个字节,对齐数为1,占用 21 - 23个字节
//第24 字节没有用,空闲
char * address;//8 占用8,= vs中的8个字节,因此对齐数为8,25-32个字节。
//总和为:4+4+8+4+4+8 = 32字节
}_Student;
void main() {
_Student s;
int result = sizeof(_Student);
printf("result = %d\n", result);// 32
//offsetof 宏可以使用 offsetof 宏计算一个结构体成员的偏移量。
printf("%zd\n", offsetof(_Student, sex)); // 0
printf("%zd\n", offsetof(_Student, sex1)); // 1
printf("%zd\n", offsetof(_Student, sex2)); //2
printf("%zd\n", offsetof(_Student, age)); // 4
printf("%zd\n", offsetof(_Student, name)); // 8
printf("%zd\n", offsetof(_Student, age2)); // 16
printf("%zd\n", offsetof(_Student, name2)); // 20
printf("%zd\n", offsetof(_Student, address)); // 24
printf("断点在这里");
}
二,带来的问题以及如何fix
从上面看到:在windows vs上,内存对齐的标准是8.
在linux 上,内存对齐的标准是4.
这会有一个问题,当我们在windows使用文件写的方式,写入了一个二进制文件(假设叫做config.bin)。需要在linux 上读取,这就有问题了。写入的时候struct占用了80个字节,但是读取的时候就不一定这个struct就占用80个字节了。
解决方案:如有这样的需求(在windows上生成的文件,需要在linux 上读取)
建议我们在给这个struct前面加上
#param pack(1) //这表示当前使用1字节对齐的方式,既然使用了1字节对齐,就不存在8字节,4字节的问题了
typedef struct student{
char sex;
int age;
char name[64];
}
#param pack() //结束标记,表示只是如上的代码 使用1 字节对齐
本文详细解释了C语言中结构体内存对齐的规则,包括默认对齐数、嵌套结构体对齐等,并指出Windows和Linux之间的对齐差异可能导致文件读取问题。提供了解决方案,使用`#parampack`来统一对齐方式。
1642

被折叠的 条评论
为什么被折叠?



