目录
一、结构体类型的设计
二、结构体的声明
三、结构体的定义和初始化。
四、结构体成员访问
五、结构体指针
六、结构体与数组
七、结构体类型的大小
C语言提供了基本的数据类型,如char,short,int,float,double...等类型我们称之为内置类型。可以使用结构体来封装一些属性,设计出新的类型,在C语言中称为结构体类型。
一、结构体类型的设计
二、结构体的声明
在C语言中,结构体是一种数据类型。可以用结构体来存放一组不同类型的数据,例如:
注:在C语言中,Room是结构体名,不能定义变量,指针,数组等。而struct Room是结构体类型名,能够定义变量,指针,数组等。在C++语言中Room是类型名。
typedef可以为数据类型定义新的型名
这样,给struct Room起了一个新的名字是room。之后用room定义变量。
三、结构体的定义和初始化。
结构体是一种数据类型,是创建变量的模板,不占用内存空间;结构体变量才包含了实实在在的数据,需要储存空间。
结构体的初始化在定义后,可以直接利用{ }进行逐一赋值(按照顺序),或者利用点(.)访问进行赋值,也可以利用指针(->)进行逐个赋值(后面会说的)。
例如,我们定义一个结构体并进行初始化
四、结构体成员访问
如果我们要给一个结构体赋值或者要改变结构体中的成员变量,我们要进行成员访问。
如果不是指针类型的结构体变量:
我们要用点(.)访问的形式来,就是在结构体变量名后,加一个点(.)再接着写访问成员的名称。例如:我们想要改变结构体中成员,用(结构体变量.成员名称)的格式就可以进行赋值或改变。
如果是指针类型的话,我们可以进行访问用到(->)运算符,详细我们在下面具体讲。
五、结构体指针
在C语言中,基本类型能够定义指针变量,结构体类型也可以定义结构体类型指针。
结构体指针的作用是可以间接地引用结构体变量。
结构体类型指针访问成员变量的获取和赋值形式:
1.(*p).成员名(.的优先级高于*,(*p)两边的括号不能少)所以*p.成员名;访问是不能通过编译的,语法错误。
2.还可以使用指向符->访问结构体变量成员
p->成员名(->是减号加大于号,中间没有空格,称为指向符)
示例:
用第一种方式改变了,room1中的房间号和价格。用第二种方式改变了房子的类型。
六、结构体与数组
所谓结构体数组,是指数组中的每个元素都是一个结构体类型。在实际应用中,C语言中结构体类型数组常被用来表示一个拥有相同数据结构的群体。
示例:
这样,我们就定义一个为Room为结构体类型的数组。
七、结构体类型的大小
这个结构体A的大小是char a(1字节)+int b(4字节)+char c(1字节)吗?答案是错误的。
那到底如何计算结构体的大小呢?
由于存储变量地址对齐的问题,计算结构体大小的3条规则:
1.结构体变量的首地址,必须是结构体变量中的“最大基本数据类型成员所占字节数”的整数倍
2.结构体变量中的每个成员变量相对于结构体首地址的偏移量,都是该成员基本数据类型所占字节数的整数倍
3.结构体变量的总大小,为结构体变量中“最大基本数据类型成员所占字节数”的整数倍
根据上个代码,我们分析(假设从0地址开始):
char a占一个字节因为1不是4的整数倍所以要填充三个字节,因为4+4是1的倍数所以4+4+1=9,但是9不是int(4字节)的倍数所以size(A)=12字节
如果结构体嵌套的话
char arr[10]+char brr[8]不是结构体A a中最大基本类型int(4字节)的整数倍,所以填充2字节,因为10+8+2+12因为是double的整数倍所以10+8+2+12+8=40,40也是double的整数倍,所以sizeof(B)=40字节。
对齐问题
为什么要理解字节对齐问题?
1.内存大小的基本单位是字节,理论上来讲,可以从任意地址访问变量,但是实际上cpu并非逐字节读写内存,而是以2,4或8的倍数的字节块来读写内存,因此就会对基本数据类型的地址作出一些限制,即它的地址必须是2,4,或8的倍数。那么要求各种数据类型按照一定的规则在空间上排列,这就是对齐
2.有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读书的结果的高低字节进行拼凑才能得到该32bite数据。显然在读取效率上下降很多
3.由于不同平台对齐方式可能不同,如此一来,同样的结构在不同的平台其大小可能不同,在无意识的情况下,互相发送的数据可能出现错乱,甚至引发严重的问题
指定对齐
1.结构体变量的首地址,必须是MIN{“结构体最大基本数据类型成员所占字节数”,指定对齐方式}大小的整数倍
2.结构体每个成员相对于结构体首地址的偏移量,都是MIN{基本数据类型成员,指定对齐方式}大小的整数倍数
3.结构体总大小,为MIN{结构体“最大基本数据类型成员所占字节数”(将嵌套结构体里的基本类型也算上,得出最大基本数据类型成员所占字节数),指定对齐方式}大小的整数倍
指定对齐值
预处理指令#pragma pack(n)可以改变默认对齐数。n取值为1,2,4,8,16
#pragma pack(n)需要以#pragma pack做结束,表示该种对齐方式至此为止。vs中默认值=8,gcc中默认值=4
示例:
。char a(1字节)是1的倍数,int b(4字节)也是1的倍数,char c(1字节)也是1的倍数 所以sizeof(A)=1+4+1=6字节。