C语言11--自定义数据类型,结构体,联合体,枚举

自定义数据类型

C语言除了可以使用基本数据类型以外,也可以自定义新的数据类型。新的数据类型由多个基本数据类型组成的,自定义数据类型分为 结构体 联合体(共用体) 枚举
1.结构体
(1)基本语法
在实际问题中,比如表示一个学生,学生本身包含学号(整型),姓名(字符串),身高(浮点型),分数(浮点型)…,这些属性不应该分开,而是构成一个整体来代表一个完整的学生。
C语言中可以使用结构体来将多个不同的数据类型组合起来,形成某种意义上的自定义的数据类型。
使用结构体前必须先声明(类型),声明结构体使用struct关键字
声明语法:
struct 结构体类型名{
结构体成员类型 成员变量名;

};

比如:
struct student{
int id;//学号成员
char name[20];//姓名成员
float height;//身高成员
//float weight;
};

//结构体声明不分配内存空间,所以成员变量在声明不能初始化
//struct 结构体类型名 代表新定义的结构体类型

声明结构体变量(不能省略struct):
struct 结构体类型名 结构体变量名;

也可以在声明结构体类型时同时声明结构体变量,通常不这么做
struct 结构体类型名{
结构体成员类型 成员变量名;

} 结构体变量名;

(2)结构体变量的初始化
结构体变量的初始化有两种语法,第一种是使用数组初始化的方法进行初始化。
struct student stu = {10,“xiaoming”,175.2f};

第二种结构体初始化方法对指定的成员分别进行初始化。这种初始化的语法不要求初始化顺序,而且允许只初始化一部分成员,方便对结构体进行扩展
struct student stu = {
.id = 10,//前面是一个小圆点,表示结构体中的某个成员
.name = “hello”,
.height = 180.4f,
};

//未被初始化的成员将被初始化为0

(3)结构体成员的访问
结构体相当于一个集合,内部有多个成员,每个成员都可以单独访问,访问结构体成员需要使用一个新的运算符 --------- .(成员运算符)
语法如下:
结构体变量.成员变量名;

比如:
stu.id = 100;
//std.name = “zkk”;//错误
strcpy(std.name,“zkk”);
stu.height = 155.5f;

(4)结构体声明语法的扩展
结构体声明通常使用typedef对结构体类型起别名,语法如下:
typedef struct 结构体类型名{
结构体成员类型 成员变量名;

} 结构体类型别名;

比如:
typedef struct student{
int id;//学号成员
char name[20];//姓名成员
float height;//身高成员
} Stu;
//Stu 等价于 struct student

使用typedef时可以省略结构体类型名,语法如下:
typedef struct{
结构体成员类型 成员变量名;

} 结构体类型别名;

比如:
typedef struct{
int id;//学号成员
char name[20];//姓名成员
float height;//身高成员
} Stu;

声明结构体时可以省略结构体类型名,这种结构体叫匿名结构体,匿名结构只能使用一次。
//匿名结构体
struct{
结构体成员类型 成员变量名;

} 结构体变量名;

(5)结构体指针与数组
结构体指针可以记录结构体变量的地址,类型为 结构体类型 *
通过结构体指针也可以访问结构体变量,通过箭头运算符(->)
Stu *pstu = (Stu *)malloc(sizeof(Stu));

pstu->id = 100;
strcpy(pstu->name,“zzy”);
pstu->height = 161.5f;

使用结构体作为数组元素类型构成结构体数组,访问语法和普通数组没有区别,将每个元素当成结构体使用。
struct student s[5];//拥有5个元素的学生结构体数组
s[0].id = 10;
(&s[0])->id = 100;

(s+1)->id = 10;//第2各元素的id成员
(*(s+1)).id = 100;

(6)结构体作为函数形参和返回值
结构体变量可以直接作为形参使用
不应该直接使用结构体变量作为函数的形参而应该使用结构体指针
结构体变量可以直接作为返回值使用
不应该直接使用结构体变量作为函数的返回值而应该使用结构体指针

结构体可以嵌套,结构体的成员也可以是结构体。

2.结构体的数据对齐
计算机存储数据要求数据对齐,目的是提高访问效率
计算机内存中数据的地址要求应该是数据自身大小的整数倍,这个规则就叫数据对齐。

由于结构体有多个成员变量组成,成员变量本身要求对齐,这样救就会造成结构体各个变量之间可能有空隙,意味着整个结构体的大小不一定是所有成员大小之和。
//第一个成员自动对齐,可以认为从0开始
struct A{
char ch;//0-1
//1-4
int num;//4-8
double d_num;//8-16
};

struct B{
short s_num;//0-2
long l_num;//8-16
char ch;//16-17
//17-24
};

结构体对齐的规则有两个:
1.每个成员的首地址必须是自身大小的整数倍(可以认为地址从0开始),如果不是就后移对齐
2.整个结构体的大小必须是最大成员大小的整数倍,不够在最后补齐

注:32位系统double只需要4字节对齐和补齐

C语言提供了语法强制按照指定规则对齐,使用一条预处理指令
#pragma pack(n)//表示数据最多按n字节对齐
比如
#pragma pack(1)//按1字节对齐

单个数据对齐的值叫m值,比如double类型m=8
整个结构体对齐的值叫M值,M是最长元素的m值

3.联合体(共用体)
联合也可以定义新的数据类型,声明联合使用关键字union
声明联合体的语法和结构体完全一样,仅仅是关键字不同
union 联合类型名{
成员变量声明;

};

联合体中所有的成员变量存储在内存中的起点都一样
整个联合体的大小是其中最大成员变量的大小

联合中所有的成员变量互相影响,修改其中一个会影响其他成员变量的值
联合可以用不同方式使用同一段空间,当任何时候只会使用多个数据中的其中一个是,就可以使用联合。

4.枚举
枚举也可以自定义数据类型,声明枚举使用enum关键字。
枚举类型规定了一组固定的名称(应该大写),这些名称实际上是用数字保存的,在程序可以当数字使用。
声明枚举类型语法:
enum 枚举类型名{
名字1,名字2,名字3…
};
//枚举类型默认给第一个名字分配0数字,后面的明书代表的数字依次递增

enum 枚举类型名{
名字1,名字2=9,名字3…
};
//也可以直接指定某个名字对应的数字,改名字后面的名字对应的数字将同时发生变化

声明枚举变量语法:
enum 枚举类型名 枚举变量名;
//枚举变量可以记录类型中某个名字

typedef同样可以用于枚举
使用枚举变量的目的是增加程序的可读性。
如果名字代表的数字有意义,选择使用宏定义,否则选择使用枚举

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值