目录
5.修改默认对齐数
1.基础知识
结构是一些值的集合,这些值成为成员变量,结构的不同成员可以是不同类型的变量。
结构体的声明
struct tag//tag可以自定义
{
member-list;
}variable-list;
比如:我们可以描述一个学生:
声明一个结构体类型,是通过学生类型来创建学生变量(对象)。
一个学生的特征有姓名,性别,年龄,电话等等。
struct stu
{
char name[20];
char tele[12];
char sex[10];
int age;
};//struct是结构体关键字,stu是结构体标签可以任意取名字。
struct s
{
char name[20];
int age;
};
int main()
{
struct s arr[50];//可以存50个struct s类型的数据
return 0;
}
我们创建结构体变量的方式如下:
struct stu
{
char name[20];
char tele[12];
char sex[10];
int age;
}s4,s5,s6;//也可以,s3,s4,s5,s6都是全局变量
struct stu s3;//全局变量
int main()
{
//结构体变量的创建
struct stu s1;
struct stu s2;
return 0;
}
有时我们可能在结构体类型后面没有标签,那么这就是一个匿名结构体。
匿名结构体类型,struct后面没有结构体标签,只能利用变量列表创建变量x
//struct
//{
// int a;
// char b;
// float c;
//}x;
//struct
//{
// int a;
// char c;
//}x;
//struct
//{
// int a;
// char c;
//}* pas;//匿名结构体指针类型,不可以用来存x的地址,因为这是完全不同的类型
匿名结构体类型只能用一次
//int main()
//{
//
// return 0;
//}
2.结构体自引用
在结构体中不可以包含自己的类型,如1.1
typedef struct Node
{
int date;
// 1.1struct Node n;//error:结构体类型自己里边 不能 包含自己类型的成员变量
struct Node *n;//结构体的正确的自引用方式
}Node;
int main()
{
struct Node n1;
Node n2;//两种写法都没有问题
return 0;
}
3.结构体的初始化
我们先来一段代码
struct t
{
double weight;
short age;
};
struct s
{
char c;
struct T st;
int a;
double d;
char arr[20];
};
int main()
{
struct s s = {'c',{55.6,30},100,3.14,"hello world"};
printf("%c,%d,%lf,%s\n",s.c,s.a,s.d,s.arr);//结构体成员的访问
printf("%lf\n",s.st.weight);
return 0;
}
初始化结构体的时候我们用“{}”,比如上边的代码块:
struct s s = {'c',{50.6,30},100,3,14,"hello world"}
这条语句就是创建了一个结构体变量s给结构体赋值,注意赋的值要用逗号隔开。
在访问结构体变量的时候我们要通过结构体变量(s)+(.)的形式访问,比如我上边的第一个printf语句。
4.结构体内存对齐
学习内存对齐将有利于我们计算结构体的大小,并且有利于我们研究如何将结构体写到最小以节省空间。
struct s1
{
char c1;
int a;
char c2;
};
struct s2
{
char c1;
char c2;
int a;
};
int main()
{
struct s1 s1 = {0};
printf("%d\n",sizeof(s1));
struct s2 s2 = {0};
printf("%d\n",sizeof(s2));
return 0;
}
在这段代码中s1的大小是12个字节,s2大小是8个字节。
要想明白为什么定义相同的变量我们的结构体大小却不一样,就必须搞清楚结构体内存对齐规则。
1.第一个成员在与结构体变量偏移量为0的地址处。
2.其他成员变量,要对齐某个数字(对齐数)的整数倍的地址处。
3.结构体的总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,
结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
对齐数 = 编译器默认的一个对齐数与该成员大小的较小值。VS编译器默认为8.
我来通过画图给大家解释一下这两句话什么意思。
所以s1的空间是12个字节。
接下来我们来研究一下结构体嵌套结构体的时候怎么计算结构体大小。
struct s3
{
double d;//对齐数8
char c;//对齐数1
char i;//对齐数1
};//结构体总大小是16
struct s4
{
char c1;//对齐数1
struct s3;//最大对齐数8
int i;//对齐数4
};
所以s4大小是32 。
所以我们要让占用空间小店变量尽量放在前面。
5.修改默认对齐数
#pragma pack(4)//设置默认对齐数为4。
#pragma pack()//取消默认对齐数。
struct s
{
char c;
int i;
double d;
};
int main()
{
offsetof()//判断成员对于起始位置的偏移量
}