引言
在用C语言解决问题的过程中,我们常会遇到如何用一个变量去表示它的性质、内容等,例如,在表示学生时,我们常会对其的姓名、年龄、成绩等进行规定,于是我们规定,在C语言中,用struct类型去表示“学生”,即结构体。
结构体声明
声明
struct tag
{
member-list;
}variable-list;
举例:一个学生,包含年龄、姓名、学号(成员变量)等内容,可以将其如下所示定义
struct Stu
{
char name[20];
int age;
char id[20];
};
创建与初始化
如图,即是一个结构体的创建和初始化
struct Stu s={"18","张三","20231131051"};
此外,也可以打乱顺序初始化,如
struct Stu s={.age=18,.name="张三",.id="20231131051"};
结构体成员变量的访问
在上述示例中,对结构体s中的成员变量进行访问有两种方式,分别如下所示
1.
s.age
s.name
s.id
//以上是C语言结构体对成员变量的直接访问
2.
定义一个指针,struct Stu *p=&s;
此时访问方式为p->age
注意,此时的p是结构体指针,类型为struct Stu *
结构特殊声明
在实际应用,我们常会遇到结构体对象名称不明确的情况,这种时候,我们可以对结构体进行匿名声明
struct
{
int a;
int b;
int c;
}s;
注意,在对结构体进行匿名声明的时候,编译器会认为此匿名变量与另一个匿名变量不是同一数据类型,要再次使用的话,需要用typedef来重新命名
结构体自引用
类似于数据结构中的链表,我们可以使用结构体来模拟实现,如下
struct Stu
{
int data;
struct Stu* next;
}
结构体内存对齐
对齐规则
1.第一个成员对齐到和结构体变量起始位置偏移量为0的地址处
2.其他成员变量对齐到对齐数的整数倍的地址处(对齐数:编译器默认的一个对齐数与该成员变量大小的较小值)
3.结构体大小为最大对齐数的整数倍
4.若嵌套结构体,则结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体整体大小就是所有最大对齐数的整数倍。
修改默认对齐数
可以使用#pragma这个预处理指令来改变编译器的默认对齐数,如#pragma pack(1)将默认对齐数修改为1
结构体传参
在将结构体作为参数传递给一个函数时,我们会有两种传参模式,即传值和传址
void print1(struct S s);
//
VOID PRINT2(struct S* p);
事实上,在结构体传参的时候,我们首选传址的方式,因为函数传参时,传参数会压栈,会造成额外的系统开销,故不采用。
位段
介绍
位段与结构体类似,主要有两点不同:1.位段的成员必须是int、unsigned int、signed int三种(C99中除外);2.位段的成员名后有一个冒号和一个数字,数字代表其占几个比特位。
struct A
{
int _a:2;
int _b:5;
int _c:10;
int _d:30;
};
上述位段的大小为8个字节,计算过程:首先,由于是int型,分配四个字节,可存32位,a,b,c存完之后再分配四个字节,总共八字节。
注意点:位段不可跨平台使用,因此不适用于可移植代码。
应用
网际协议中IP数据报,多个属性可用几个比特位描述