解析C语言结构体,位段。
1.结构的定义
聚合数据类型能够同时存储超过一个的单独数据。c语言提供了两种类型的聚合数据类型,数组与结构。数组是相同类型元素的集合,它的每个元素是通过下标引用或指针间接访问来选择的。结构也是一些值的集合,这些值成为它的成员,但一个结构的各个成员可能具有不同的类型。每个结构成员都有自己的名字,它们是通过名字访问的。结构并不是一个它自身成员的数组。和数组名不同,当一个结构变量在表达式中使用时,它并不被替换成一个指针。结构变量也无法使用下标来选择特定的成员。
结构的声明:
struct {
int a;
char b;
float c;
}x; 我们可以看出这个声明创建了一个名叫x的变量,它包含三个成员:一个整数,一个字符,一个浮点数。
2.结构的初始化
如下例子:
struct Student
{ int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}student1{10000,“李炯”,“M”,19,80,“北京”}
这就是对结构的初始化。
3.结构体的typedef
关于结构体的typedef,
typedef是类型定义的意思。typedef struct 是为了使用这个结构体方便。
具体区别在于:
若struct node {}这样来定义结构体的话。在申请node 的变量时,需要这样写,struct node n;
若用typedef,可以这样写,typedef struct node{}NODE; 。在申请变量时就可以这样写,NODE n;
区别就在于使用时,是否可以省去struct这个关键字。
1 首先:
在C中定义一个结构体类型要用typedef:
typedef struct Student
{
int a;
}Stu;
于是在声明变量的时候就可:Stu stu1;
如果没有typedef就必须用struct Student stu1;来声明
这里的Stu实际上就是struct Student的别名。
另外这里也可以不写Student(于是也不能struct Student stu1;了)
typedef struct
{
int a;
}Stu;
结构名是结构的标识符不是变量名.
另一种常用格式为:
typedef struct 结构名
{
类型 变量名;
类型 变量名;
...
} 结构别名;
另外注意: 在C中,struct不能包含函数。在C++中,对struct进行了扩展,可以包含函数。
4.结构体的内存存储(内存对齐规则,为什么存在内存对齐?)
typedef struct fun
{
int a;
char b;
double c;
short d;
}fun;
int main()
{
int ret = sizeof(fun);
printf("%d\n", ret);
system("pause");
return 0;
}
其值为24.
对齐过程分析(对齐参数为其他的同理):
1、结构的第一个成员永远放在结构的0偏移处。
2、从第二个成员开始,都要对齐到某个对齐数的整数倍处(对齐数为结构成员自身大小和默认对齐数的较小值 默认对齐数:vs--8,linux---4).
3、结构自身的总大小必须为最大对齐数的整数倍。
union Fun
{
int a;
char b;
double c;
short d;
};
int main()
{
int ret = sizeof(Fun);
cout << "ret= " << ret <<"\n"<< endl;
system("pause");
return 0;
}
union Fun
{
int a[7];
char b[9];
double c;
short d[4];
}fun;
int main()
{
int ret = sizeof(fun);
printf("%d\n", ret);
system("pause");
return 0;
}
其值为32.
当联合体中无数组时,联合体的大小为联合体中变量类型最大的字节长度;
当联合体中有数组时,联合体的大小最小为字节数最大的数组,同时也要是字节数最大的变量类型的最小整数倍。
5.结构实现位段,位段大小的计算。位段的数据存储。
位段的声明和普通的 成员声明相同,但 是位段成员必须声明为int 、signed int、unsigned int类型。其次在成员名的后面是一个冒号和一个整数,这个整数表示该位段所占用的位的数目。
structbits{
unsigneda:2;
unsignedb:3;
unisngedc:4;
int i;};
这个位段定义中除了定义了各成员的位长以外,还有int型
在上例中,其中a、b、c共占9位,占用了1个字节还要多,不到2个字节。而它后面为int型,占用2个字节。则a、b、c之后的7个位的空间闲置不用,i从另一个字节开头存放。如下图所示:
3)存储单元中位段的空间分配方向为由低位到高位分配。
上例中的字段分配图只是一个示意图,在内在的实际表示其实是这样的:
先定义的a(2个位),被分配到高16位的低位上,紧接着是b(3个位),后面的成员分配依此类推。最后的int型,因为是16位,高16位剩余的7个位不能容纳它,则i被分配到低16位。
6.位段的跨平台问题。