结构体的自引用:
例如有这样的代码
struct student{
char name[1024];
int age;
struct student a;
};
此时我们编译执行后,程序会报错(a使用未定义的struct student),原因很好分析,例如我们想求这个结构体的所占字节大小,student 占的字节就是 char[1024]+int+student ,此时student又是不知道的,就会返回一个死循环。
但如果需要自引用本身结构体,只需要在第四行做一下改动
struct student{
char name[1024];
int age;
struct student* a;
};
因为我们直到指针变量都是四个字节,这样就可以确定所占内存空间大小。
结构体内存对齐:
我们先看代码
typedef struct Test{
char a;
int b;
int c;
}Test;
int main(){
Test t;
printf("%p\n", &t);
printf("%p\n", &t.a);
printf("%p\n", &t.b);
printf("%p\n", &t.c);
printf("%d\n", sizeof(t));
system("pause");
return 0;
}
我们发现每个元素的地址间相差4个字节,并且整个结构体变量所占字节大小位12
我用一张图来表示一下
这里我们发现第一个char元素之后,有三个字节是没有用上的,我用蓝色来表示
将代码改一下
typedef struct Test{
short a;
short b;
int c;
}Test;
int main(){
Test t;
printf("%p\n", &t);
printf("%p\n", &t.a);
printf("%p\n", &t.b);
printf("%p\n", &t.c);
printf("%d\n", sizeof(t));
system("pause");
return 0;
}
用图表示
看到这里就有点懵逼了,有的时候浪费了内存空间,有的时候则没有浪费
这里就要介绍一下结构体的内存规则了
- 第一个成员在与结构体变量偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。(对齐数: 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的值为8
- 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
我们再举个结构体来解释一下:
typedef struct Test{
short a; //a放在偏移量为0的位置
int b; //8 4=> 4 b就要放在偏移量4的整数倍上
char c; //8 1=> 1 c就要放在偏移量1的整数倍上
short d; //8 2=> 2 d就要放在偏移量2的整数倍上
}Test;
用图来表示如下
也可以手动修改对齐数
#pragma pack(1)
//把默认对齐数设成1
#pragma pack()
//还原