1、结构体的定义及初始化
通过数据类型来定义一个一个的变量,当需要很多相同类型的变量时有数组。 基本数据类型在使用时很方便,但是利用它们来描述现实世界就显得捉襟见肘。 例如需要保存一个班学生的信息”姓名,年龄,分数”,按照前面的学习需要单独 定义三个数组,一个保存姓名,一个保存年龄,一个保存分数。这样定义对于后面 的维护,修改,删除会带来麻烦。好比你用三个记事本一个记录学生姓名,一个记 录年龄,一个记录分数,如果删除姓名记事本中的第十个学生,而在年龄,分数记 事本中却删除了第十一个,这是很容易发生的。实际中并不会这么做,我们会利用 一个 Excel 表来记录学生的信息,一行就是一个学生的所有信息,修改,添加,删 除都非常清晰。而这就是今天学习的内容-自定义数据类型。
自定义数据类型:根据自己的需要定义新的数据类型。
自定义数据类型包括结构体,位段,共用体和枚举。当然最重要的就是一号选 手-结构体。
例如:定义一个学生结构体,包含姓名和年龄
struct Student //定义学生结构体{char name[20];//姓名int age; //年龄}; //类型定义完成
这个类型定义好了之后就和基本类型一样使用,可以用来定义单个变量,数 组,指针或者作为另一个结构体的成员。
结构体变量定义好之后该如何访问它的成员呢?如何输出 stu3 中的信息呢? 结构体变量通过”.”号访问其成员。
输出 stu3 信息的代码如下:
printf("%s,%d\n",stu3.name,stu3.age);//通过.号访问成员
struct Student //定义学生结构体{char name[20];//姓名int age; //年龄}; //类型定义完成int main(){struct Student stu1;struct Student stu2 = {"caocao"};struct Student stu3 = {"刘备",25};printf("%s,%d\n",stu3.name,stu3.age);//通过.号访问成员//修改成员的数据strcpy(stu1.name,"孙权"); //字符串复制需要用 strcpystu1.age = 18; //通过.号访问成员printf("%s,%d\n",stu1.name,stu1.age);//通过.号访问成员strcpy(stu2.name,"曹操"); //通过.号访问成员stu2.age = 24; //通过.号访问成员printf("%s,%d\n",stu2.name,stu2.age);return 0;}
2、结构体指针定义及使用
结构体指针定义
结构体不仅能定义普通的变量,也可以定义指针,例如:
struct Student //定义学生结构体{char name[20];//姓名int age; //年龄};int main(){int a = 10;int *p = &a;struct Student stu = {"曹操",23};struct Student *ps = &stu;//类似 pstruct Student *ps2; //没有初始化,野指针return 0;}
结构体指针变量和整型指针变量类似,用于保存同类型变量的地址
结构体指针访问其成员 结构体指针 ps 如何访问结构体的成员呢?一个笨办法就是(*ps).age 这种形 式。注意一定要加”()”,因为”*”的优先级低于”.”,这个办法不仅容易出错, 写起来也繁琐,C 语言有一种更简洁的表达形式。
结构体指针通过”->”访问其成员。
例如下面代码。
int main(){int a = 10;int *p = &a;struct Student stu = {"曹操",23};struct Student *ps = &stu; //类似 pstruct Student *ps2; printf("%s,%d\n",(*ps).name,(*ps).age);//这个方法繁琐,易错printf("%s,%d\n",ps->name,ps->age); //结构体指针访问其成员ps2 = &stu;ps2->age = 30; //通过 ps2 修改 stu 的年龄printf("%s,%d\n",ps2->name,ps2->age);return 0;}
总结:结构体变量通过”.”访问其成员,结构体指针通过”->”访问其成员。
3、结构体数组定义及使用 结构体数组定义 结构体定义完成后和内置类型一样使用,能定义变量,指针当然也可以定义数组。
struct Student{char name[20];int age;};int main(){//内置类型,定义变量,指针和数组int a = 10;int *p = &a;int arr[10] = {1,2,3};//结构体类型,定义变量,指针和数组struct Student stu = {"曹操",23};struct Student *pstu = &stu;struct Student brr[3];struct Student crr[3] = {{"曹操",23},{"刘备",25},{"孙权",18}};struct Student drr[3] = {"曹操",23,"刘备",25,"孙权",18};struct Student err[] = {"曹操",23,"刘备",25,"孙权",18};return 0;}
5、typedef 的使用
在 C 语言中使用结构体时必须加上 struct 这个关键字,那有没有办法省略这 个呢?要想达到这个目的就需要用到关键字 typedef,顾名思义”类型定义”。
typedef 数据类型 新的别名;
它是用来操作数据类型。其主要作用有两个:
1.给一个较长较复杂的类型取一个简单的别名。
2.给类型取一个和问题相关的别名。
如何在使用结构体时省略 struct 这个关键字呢?可以 按照如下方法定义结构体。例如:
//第一个方式struct A{int a;char b;};typedef struct A A;//给 struct A 起个别名叫 A//第二种方式typedef struct B{char a;int b;}B; //给 struct B 起个别名叫 Bint main(){A aa = {10,'x'}; //直接使用 AB bb = {'y',20}; //直接使用 Breturn 0;}
6、共用体,位段和枚举
共用体
共用体也称为联合体,使用关键字 union,它的所有成员共用同一段内存。例如:
typedef struct A{int a;int b;}A;typedef union B{int a;int b;}B;int main(){A aa = {10,20};//B bb = {10,20};//错误,B 中所有成员共用同一段内存,不能同时赋值B bb;bb.a = 10;bb.b = 20;printf("%d,%d\n",aa.a,aa.b);printf("%d,%d\n",bb.a,bb.b);return 0;}
注意在上图中 bb.a = 10,但是在输出结果时却是 20,为什么会这样呢?见下 面的内存图:
原因还是因为共用体所有成员共用同一段内存,如上图在联合体 union B 中 a 和 b 的内存相同。第 19 行代码 bb.b = 20 时会将前面 bb.a 的值也修改成 20。
总而言之使用联合体的准则是:联合体定义的一个变量一定只使用其中的一 个成员。
位段
位段和结构体非常的类似,它成员表示一个或者多个位。由于不同平台,它的 定义有差异(C 标准没有详细定义),所以它不可移植,使用起来不如位运算方便, 在这不做过多介绍,大家只需要认识并知道它的大小即可。
struct A{int a;int b;};struct B //定义位段{int a:10;//表示 a 占用 10 个位int b:20;//表示 b 占用 20 个位};int main(){printf("sizeof(struct A)=%d\n",sizeof(struct A));printf("sizeof(struct B)=%d\n",sizeof(struct B));return 0;}
位段的大小一定是 sizeof(int)的倍数,上例中位段 B 为 10+20 共 30 位,最 小为 4 字节(32 位)。
枚举
枚举:使用关键字 enum,把可能的值全部列举出来,变量的取值只能在列举 的值范围内。 例如枚举星期类型:
enum Weekday{sun,mon,tue,wed,thu,fri,sat};int main(){enum Weekday day1; //定义变量,未初始化enum Weekday day2 = sun; //初始化为星期天enum Weekday day3 = mon; //初始化为星期一return 0;}
如果觉得《C语言 自定义数据类型(结构体 typedef 共用体 位段 枚举)》对你有帮助,请点赞、收藏,并留下你的观点哦!