1.结构体的基本知识
结构是一些值的集合,这些值被称为成员变量,结构体的每个成员可以是不同类型的
2.结构体的声明
struct tag(标签,也叫结构体名)--->此出没tag叫匿名结构体类型,要注意的是,匿名结构体要及时在结构体类型后定义变量
{
//member list(成员列)
exp:char a;
char str[];
};//variable list(变量列)exp:s1,s2;// 首先要提到的是这个锋号,如果没有要定义的变量,要在}后面添加锋号;而定义在结构体后面的变量一般是全局变量,如果是
int main()
{
struct tag s3;
return 0;
}//这样的变量称它为局部结构体变量(s3)
匿名结构体类型要注意的是当创建一个匿名结构体之后,再以相同的成员作为结构体类型定义一个结构体类型指针,是不可行的,在编译器中会认为他们是不同的的结构体类型,即使他们的结构体成员一样
exp:
struct
{
char a;
char str[];
}s1;
struct
{
char a;
char str[];
}* ps1;
int main()
{
struct tag *ps1=&s1;//wraning
return 0;
}//值得注意的是这个没命名的结构体类型,只对他开始定义过的变量有效,也仅限在这,别的地方无法定义新的变量
3.结构体自引用
在结构体类型成员中有个结构体
这时我们要注意,直接将结构体类型对应变量,写入是不对的,我们要指向这个结构体的指针放入,
结构体中经常会使用typedef将结构体类型名,改成其他的简单的名字exp:
typedef stuct (tag){
tags* next//error
struct tag* next;//right
}tags;如果没有tag,是个匿名结构体类型这里的成员列里不能出现结构体的自引用,
在为改名之前就自应用,程序不会识别这个新的类型名
4.结构体变量初始化
struct body{
double weight;
int height;
}t;
struct stu{
char name[];
struct body t;
short age;
}p;
int main()
{
struct stu p={“wangming”,{60.0,175},23};
struct stu* pp=&p;
printf("%s",p.name);//点这个字符是用来访问结构体成员的,
printf("%s",pp->name)//这个是指针访问结构体成员的
return0;
}
5.结构体内存对齐(求结构体的大小)
规则;第一个成员在于结构体变量偏移量为零的地址处//偏移量是指在结构体在内存中放置的第一个位置空间(偏移量为0)算起,每向下一个字节,偏移量加1,
其他成员要对齐某个数字(对齐数)的整数倍的地址处(对齐数:编译器中默认的对齐数和成员大小的较小值)注意字符型数组或者数字型数组的对齐数为元素所占空间大小
结构体的大小为最大对齐数的整数倍
如果结构体内嵌套结构体,还是先算出这该嵌套结构体的大小,在与默认对齐数比较
exp:
struct stu
{
char a;//sizeof=1对齐数为1
char a1;//sizeof=1对齐数为1
int b;//sizeof=4对齐数为4 ,前面的两个char相继占据了偏移量为1和0的两块空间(任何数都是一的倍数)而第三个成员要放在对齐数的倍数处,也就是偏移量为对齐数的倍数处,偏移量为四的位置刚好是第三个成员对齐数4的倍数,就在这里开始存放第三个成员(在第二个成员地基础上向后偏移了两字节,而这跳过的两字节空间将会被浪费掉)4+4=8,8也正好是最大对齐数4的倍数,所以该结构体的大小为8
}s1;//vs里的默认对齐数为8
int main()
{
printf("%d",sizeof(s1));//8
return 0;
}
我们在放置成员的时候,讲究是将小的数据集中放置,可以减少空间的浪费
注意:在gcc环境下,没有默认对齐数
结构体内存对齐的原因:1.不是所有硬件平台都能访问任意地址上的任意数据的,只能在某些地址的取特定数据,2.内存对齐可以减少访问一个数据的次数即减少运算时间,exp:char a;int b;如果不按照内存对齐来存储,这个结构体会在内存中站5个字节,而在32位机器上每次读取4个字节,而b就会分两次读取,而内存对齐后这里的结构体大为8,a存完后会浪费三个字节的空间,再存储b,先一次读a,再一次都b,总共才需要两次,很好的节省了时间,说白了,内存对齐是用空间来换取时间
6.修改默认对齐数
我们可以用#pragma这个预处理命令,改变默认对齐数
#pragma pack(size_t为要设置的默认对齐数数字,而什么都不给,就是取消默认对齐数)
这里涉及到的size_toffsetof(structName,memberName);这样一个函数可以实现算出,结构体成员再内存中的偏移量,他的头文件是<stddef.h>,这是一个宏的概念