1.结构的定义
结构类型定义的一般形式为:
struct 结构名{ 类型名 结构成员名1; 类型名 结构成员名2; ... 类型名 结构成员名n; };struct是定义结构类型的关键字,在struct之后,自行命名一个结构名,它必须是一个合法C标识符,struct与结构名两者合起来共同构成结构类型名,如struct student,大括号里面的内容是结构所包括的结构成员,也叫结构分量,结构成员可以有多个。这样,大括号内定义的成员信息被聚合成一个新的数据类型。
一个结构也分好几种结构变量:结构变量的定义分为以下三种:
1、单独定义
是指先定义一个结构类型,再定义这种结构类型的变量。例如struct student s1;
2、混合定义
混合定义指在定义结构类型的同时定义结构变量。
这种定义的一般形式为:
struct student { 类型名 结构成员名1; 类型名 结构成员名2; ... 类型名 结构成员名n; }s1,s2;3、无类型名定义
无类型名定义是指在定义结构变量时省略结构名。
这种定义方法的形式一般如下:
struct { 类型名 结构成员名1; 类型名 结构成员名2; ... 类型名 结构成员名n; }结构变量名表;
2.结构的初始化 结构变量也可以初始化,即在定义的时候对其赋初值。例如 struct student s1 = {101,"zhang",78,87,85}; 对 结构变量的初始化采用初始化表的方法,大括号内各数据间用逗号隔开,将大括号内的数据项按顺序对应的赋给结构变量内各个成员,且要求数据 类型一致 3.结构体的typedef 在结构中可以利用typedef定义一种心得类型名: 例如: typedef struct SELF_REF3_TAG { int a; struct SELF_REF3_TAG *b; int c; }SELF_REF3; 要小心一个陷阱 typedef struct { int a; struct SELF_REF3_TAG *b; int c; }SELF_REF3; 这个声明的目的是为这个结构创建类型名SELF_REF3,但是它失败了,类型名直到声明的结尾才定义,所以在结构声明的内部它并未定义。这个类型 就是匿名类型。
4.结构体的内存存储(内存对齐规则,为什么存在内存对齐?)
结构内部包含了大量的未用空间,编译器按照成员列表的顺序一个接一个的给每一个成员分配内存。只有当存储成员需要满足正确的边界对其要求的时候,成员之间才会出现用于填充的额外内存空间。
为了说明这一点,考虑下面这个结构:
struct ALIGN { char a; int b; char c; } ;如果某个机器的整型值长度为四个字节,并且它的其实存储位置必须能够被四整除,那么这一个结构在内存中的存储将如图所示:
内存对齐规则:
1、结构的第一个成员永远放在零偏移处
2、从第二个成员开始,都要对齐到某个对齐数的整数倍处。对齐数结构成员自身大小和默认最小对齐数的最小值(vs环境默认-8 lunux默认-4)
3、结构总大小必须是最大对齐数的整数倍
对齐的原因:
1、平台原因:硬件平台的限制
2、性能原因:不对齐可能访问两次,对齐访问效率高
5.结构实现位段,位段大小的计算。位段的数据存储。
位段的声明和结构类似,但它的成员是一个或多个位的字段。这些不同长度的字段实际上存储于一个或多个整型变量中。
位段的声明和任何普通的结构成员声明相同,但有两个例外,首先,位段必须声明为int,signed int或 unsigned int类型,其次在成员名的后面是一个冒号和一个整数,这个整数指定该位段所占用的位的数目。
举个例子:
struct s { int a:2;//2个bite int b:10; int c:5; int d:20;//小于32 }从右向左的排列方式,20大于第一个位段剩余部分排到第二字位段大小:2
不同的编译系统有不同的结果。因为下面这些情况与实现有关的依赖性
1、int位段被当成有符号数和无符号数。
2、位段中为的最大数目。许多编译器把位段成员的限制在一个整型值的长度之内,所以一个能够运行于32位整数的机器上的位段声明可能可能在16位整数的机器上无法运行。
3、位段中的成员在内存中是从左向右分配还是从右向左分配的。
4、当一个声明指定了两个位段,第二个位段比较大,无法容纳第一个位段剩余的位时,编译器有可能把第二个位段放到内存的下一个字,也可能放到第一个位段的后面,从而在两个内存位置的边界上形成重叠。所以位段不能跨平台。