一、结构体的声明
结构体的概念:结构体是一些变量的集合,这些变量称为成员变量。结构体中的变量可以是不同类型的,结构体的成员可以是标量、数组、指针甚至是结构体。
结构体关键字: struct
结构体的声明:
struct tag //tag为结构体标签名,可以自定义
{
member-list; //成员变量列表
}variable-list; //定义出的结构体变量列表(可有可无)
示例:
struct Stu //声明了一个描述学生信息的结构体
{
char name[20]; // {}内的就是成员变量列表
int age;
char sex[5];
char id[20];
}; //分号不能丢
特殊的声明 —— 匿名结构体
struct //省略标签名即为匿名结构体
{
int a;
char b;
float c;
}x, arr[5], *p; //匿名结构体只能在声明的同时定义结构体变量,不能独立使用struct来定义变量
注:只要是两个独立的结构体,不管内部成员变量列表是否相同,都属于不同的类型。
所以不同的两个结构体之间不存在指针接收地址。
结构体的自引用:
在结构体内声明结构体本身类型的指针变量,叫结构体的自引用。
struct Node
{
int data; //为了避免死循环,结构体内直接使用结构体类型声明变量是不可行的
struct Node* next; //正确的方法是:使用结构体类型的指针
};
即:结构体自引用使用结构体类型的指针。
二、结构体的定义和初始化
定义:
struct Point
{
int x;
int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
初始化:
//初始化:定义变量的同时赋初值。
struct Stu
{
char name[15];
int age;
};
struct Stu s1 = {"zhangsan", 20};//初始化,必须按顺序一一对应
struct Stu s2 = {.age = 20, .name = "zhangsan"}; //指定访问可按自定义顺序初始化
struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化
三、结构体的内存对齐
结构体内存对齐的规则:
1、结构体的第一个成员对齐到结构体在内存中存放位置的0偏移处。(第一个字节是0偏移处)
2、从第二个成员开始,每个成员都要对齐到自己对齐数的整数倍处。(自己对齐数:默认对齐数与该成员类型大小中较小的那个)
3、结构体的总大小必须是所有成员自己对齐数中最大的那个的整数倍(包含嵌套的结构体中的对齐数)。
4、如果结构体中嵌套了结构体成员,要将嵌套的结构体成员对齐到这个嵌套的结构体中最大的那个对齐数的整数倍处。
(VS默认对齐数为8,Linux中的gcc没有默认对齐数。)
修改默认对齐数:
#pragma pack() //使用这句预处理指令可修改默认对齐数
//示例:
#pragma pack(4) //修改默认对齐数为4
四、结构体传参
传递结构体类型的实参就要用结构体类型的形参接收。
注:由于结构体的内存大小可能比较大,因此结构体传参更建议使用传址的方式,用指针接收。无需建立临时拷贝,节约空间,提高效率。