1.结构体
(1)结构体声明
结构体可以用来给C语言增加新的数据类型,新的数据类型有多个基本类型组成的
结构体本身是一种数据类型,声明一个结构体不占用内存
使用结构体之前必须先声明,声明结构体使用struct关键字
声明语法:
struct 结构体类型名{
结构体成员类型 成员变量名;
.......
};
结构体声明语法中的成员变量不可以初始化,因为结构体声明不分配内存
可以在声明结构体是同时声明结构体变量,但是一般不建议这么做,语法如下:
struct 结构体类型名{
结构体成员类型 成员变量名;
.......
} 结构体变量;
C语言中不能再结构体中加入函数,但是可以使用函数指针
注:使用结构体类型声明变量时需要加上struct关键字
(2)typedef的用法
typedef关键字可以给一个已知的类型起别名
注:不能使用宏给类型起别名
语法:
typedef 已知类型名 类型别名;
在之后的语法中,使用类型的别名就相当于原类型
typedef也可以给结构体类型起别名
语法:
typedef struct 结构体类型名{
结构体成员类型 成员变量名;
.......
} 结构体类型别名;
(3)匿名结构体
在声明结构体是可以省略结构体的类型名,同时声明一个结构体变量,这种结构体就叫匿名结构体
匿名结构体只能使用一次
语法:
struct {
结构体成员类型 成员变量名;
.......
} 结构体变量;
注:使用typedef给结构体类型起别名时可以省略结构体类型名
typedef struct {
结构体成员类型 成员变量名;
.......
} 结构体类型别名;
注:结构体的成员也可以是结构体
(4)结构体变量的初始化
结构体变量初始化的方法和数组初始化的语法是一样的
同类型的结构体变量之间可以互相赋值
通过成员运算符(.)可以访问结构体的成员变量
语法:
结构体变量名.结构体成员变量名
结构体指针可以用来记录结构体变量的地址,类型为 结构体类型 *
也可以通过结构体指针来访问结构体成员变量,使用箭头运算符(->)
语法:
结构体指针变量名->结构体成员变量名
(5)结构体作为函数形参和返回值
结构体变量可以直接作为形参使用
结构体变量也可以直接作为返回值使用
不应该使用结构体变量作为形参而应该使用结构体指针
不应该使用结构变量作为返回值而应该使用结构体指针
(6)结构体对齐
计算机存储数据要求数据对齐,提高访问效率
计算机内存中的数据的地址要求必须是自身大小的整数倍(double只需要是4的整数倍),这个规则就叫数据对齐
由于结构体是由多个成员变量组成的,成员变量本身要求对齐,这样就会造成结构体各个成员变量之间有空隙
意味着结构体整体的大小不一定是所有成员大小之和
结构体对齐规则:
(1)第一个成员自动对齐,可以认为结构体地址从0开始,之后所有成员的地址必须是自身大小的整数倍(double只需要是4的整数倍),如果不是就往后移动直到对齐为止
(2)整个结构体的大小是其中最大成员变量大小(double只需要是4的整数倍)的整数倍,如果不是就在结构体最后补齐
补充:
我们可以使用#pragma pack(n)预处理指令来手动指定计算机中数据对齐的方式
#pragma pack(1) //按1字节对齐