C语言入门简明教程
0x08 结构体、共用体、枚举和用户自定义类型
写在开头
有时候一些我们要存很多数据,比如一家人的户口信息,如果只开数组,无法满足各种不同数据类型的兼容存储,于是我们引进了结构体和共用体来更加灵活地存储复合的数据。
结构体:struct
结构体相当于将多个变量组合在一起成为一个新的,有点像一个箱子,你可以在里面放各种东西。结构体的定义很简单:
这边假设存储狼狼国幼儿园新生信息,给出结构体定义方法:
struct Student{
char* name;
char* birthday;
char* phone;
int male;
};
结构体定义完,我们就可以使用了,声明结构体变量方法:
struct Student student1;
struct Student students[10000];
要访问结构体变量里面的内容,以name为例,则为student.name。通过"."来对结构体成员进行访问。
当通过结构体指针访问内容时,我们当然可以(*ptr).name,但我们同样可以使用ptr->name来直接通过指针访问内容,方便高效。
结构体赋值,我们可以逐个赋值,也可以以如下方式初始化和重新赋值:
struct Student stu2={"st2","10000101","+WF18888888888",1};//初始化
stu2=(struct Student){"st2","10000102","+WF18888888888",1};//重新赋值
//狼狼国手机号码国家代码是+WF:P
如果要定义全局变量而又不想多打一遍struct,可以这么做:
struct XXX{
......//成员
}xxx1,xxx2={......},xxx3[1000];//要更多的往后加就行
特别地,结构体中的成员变量也可以是结构体,方便嵌套定义。
另外,结构体中如果有另一个相同的结构体,则以指针方式存储,常见如以后会讲的链表、树等数据结构。
共用体:union
共用体和结构体很像,但是不同的是,共用体在同一个内存空间中存储不同类型的数据,而且只存储共用体中的一种。
为什么我们要用共用体呢?假设姓名有英文字符串和单纯的一个短的数字,有些人习惯填英文、有些人习惯数字(好怪哦),那么可以在输入英文时使用字符串存储、输入数字时用整数存储。
union Name{
char* name;
int id;
};
共用体初始化:
Name name1={.id=123};
Name name2={.name="xxx"};
除了一个共用体一次赋值只会保留它其中赋值的那个成员的数据且一次只可赋一个值之外,使用方法和结构体相同。
位域
在结构体或共用体中,如果一个变量不会用到其所占内存的绝大多数,可以使用位域来减少内存占用:
struct per{
char* name;
int s:1;//一个人的性别生物学意义上一般只有两种,所以我们可以用int s:1,使分配给s的大小为1个Bit
};
结构体和共用体占用空间的说明
由于要和4的倍数对齐来提高内存查找的效率,结构体占用的内存将为4的倍数,多出来的空间将不存储任何数据;
共用体所占空间为其所有成员中占用空间最大的那个类型所占的空间。
枚举类型
假设一个系统有很多用户类别:访客、一般用户、管理员、超管…,我们可以用数字来代表他们。但是数字的含义很难记住,特别是多人完成一个项目时,由于理解问题和某些人不爱写注释,可能会发生若干错误和冲突。于是,我们通过给一些名称来方便设置,此时我们常用枚举类型:
enum Users{
guest,
user,
admin,
superadmin,
...
};
使用也很简单:
enum Users user1;
user1=user;
//比较方法:
if(user1==user){//do something}
if(user1<superadmin){//do something else}
声明的枚举类型可以强制转换为int值,枚举中的元素从0开始标号,转换后获得这个标号,我们在创建枚举类型时也可以使用自己设置的标号:
enum Users{
guest=-1,
user=1,
admin,//=2
superadmin,//=3
...
}
用户自定义类型
有时候我们创建一个类型名字特别长的变量打字很麻烦,于是我们可以使用typedef来创建自定义类型名称。
typedef long long ll;//将long long 自定义为ll,之后创建该种类型只需要 ll var1就行
注意,与#define不同,typedef交由编译器处理,且只能为类型的自定义名称而不可是某个值的名称。
总结
这块可能比较难理解,自己试试看,然后再试试看自己认为对的一些特殊写法,验证一下自己的感觉~
EOF