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;
}结构变量名表;
struct student s1 = {101,"zhang",78,87,85};
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;
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、当一个声明指定了两个位段,第二个位段比较大,无法容纳第一个位段剩余的位时,编译器有可能把第二个位段放到内存的下一个字,也可能放到第一个位段的后面,从而在两个内存位置的边界上形成重叠。所以位段不能跨平台。