【C语言】结构体(struct)最全的讲解(万字干货)以及枚举类型 |
您所在的位置:网站首页 › 结构体创建函数 › 【C语言】结构体(struct)最全的讲解(万字干货)以及枚举类型 |
谢谢观看!希望以下内容帮助到了你,对你起到作用的话,可以一键三连加关注!你们的支持是我更新地动力。 因作者水平有限,有错误还请指出,多多包涵,谢谢! 目录 一、结构体类型的声明1.1结构体回顾1.1.1结构的声明1.1.2结构体变量的创建和初始化 1.2结构的特殊声明1.3结构的自引用 二、结构体内存对齐2.1对齐规则2.2为什么存在内存对齐?2.3修改默认对齐数 三、结构体传参四、结构体实现位段4.1什么是位段?4.2位段的内存分配4.3位段的跨平台问题4.4位段的应用4.5位段使用的注意事项 五、枚举类型5.1枚举类型的声明5.2枚举的优点在自定义的类型中一共有3种: 结构体、联合体、枚举 那么就先让我们了解一下结构体的细节和枚举类型吧。 一、结构体类型的声明 1.1结构体回顾结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是相同类型的变量,也可以是不同类型的变量。成员变量可以是一个或者多个。 数组也是一些值的集合。数组的每个元素只能是相同类型的数据。元素个数可以是一个或者多个。 注意区分数组和结构的不同点和相同点。 1.1.1结构的声明 struct tag { member-list;//成员列表 }variable-list;//变量列表让我们通过代码来描述一个学生:一个学生具有的属性是年龄、名字、性别、学号等。 //结构体类型,类似于int,char,float等类型 //不同的是,这个是我们自己创建的类型,我们创建类型是为了什么?当然是为了创建变量了,类似于int a、 char c等 //类型名是struct Stu,和int 、char一样 struct Stu { char name[20];//名字 int age;//年龄 char sex[5];//性别 char id[20];//学号 }; //分号不能丢,重要的部分1.1.2结构体变量的创建和初始化 结构体变量的创建有2种方式,但是有点小区别: 在声明的时候进行创建结构体变量。此时的变量是全局变量在main()函数中用结构体类型来创建结构体变量。此时的变量是此时的变量是局部变量 struct Stu { char name[20];//名字 int age;//年龄 char sex[5];//性别 char id[20];//学号 }s1,s2;结构体变量的创建第一种方法,创建了变量s1、s2,类型是struct Stu //s1、s2是全局变量 int main() { //结构体变量的创建第二种方法 struct Stu s3;//创建了变量s3,类型是struct Stu struct Stu s4;//创建了变量s4,类型是struct Stu struct Stu s5;//创建了变量s5,类型是struct Stu //s3、s4、s5是局部变量 struct Stu s6 = {"王五",18,"男","2024"};//在创建结构体变量是进行赋值,就是初始化 return 0; }结构体变量的初始化有2种方式,但是也有区别: 在结构体变量的创建时,用{}进行初始化。此时必须严格按声明中成员变量的顺序来初始化用{.成员变量 = , .成员变量 = }(使用到.操作符)来初始化变量。 #include struct Stu { char name[20];//名字 int age;//年龄 char sex[5];//性别 char id[20];//学号 }; int main() { //按照结构体成员的顺序初始化 //在结构体变量的创建时,用`{}`进行初始化 struct Stu s = { "张三", 20, "男", "20230818001" }; printf("name: %s\n", s.name); printf("age : %d\n", s.age); printf("sex : %s\n", s.sex); printf("id : %s\n", s.id); //按照指定的顺序初始化 //用`{.成员变量 = , .成员变量 = }`(使用到`.`操作符)来初始化变量 struct Stu s2 = { .age = 18, .name = "lisi", .id = "20230818002", .sex = "⼥" }; printf("name: %s\n", s2.name); printf("age : %d\n", s2.age); printf("sex : %s\n", s2.sex); printf("id : %s\n", s2.id); return 0; }通过上面学习结构体的知识,让我们写个代码实现一下,创建和初始化,以及打印数据。 struct Book { char book_name[20];//书的名字 char author[20];//作者 float price;//定价 char id[19];//书号 }; int main() { struct Book b1 = { "C语言","王五",38.8f,"PG20240520" }; struct Book b2 = { .id="PG20240510",.book_name="c++",.author="李四",.price=55.5f }; printf("%s %s %f %s\n", b1.book_name, b1.author, b1.price, b1.id); printf("%s %s %f %s\n", b2.book_name, b2.author, b2.price, b2.id); return 0; }
分析一下:对于5.5、9.0我们是可以准确的写成对应的2进制数1001.0、101.1,那么对于这样的浮点数,在内存中是可以准确存放相关的值(E、M、S),但是对于38.8,我们是不能完整地写成对应的2进制数据100110.110...,因为0.8=0.5+0.25+...会始终差一些才可以等于0.8,而由于对于float浮点数中的M相关值的存放限制在23位,那么就可能会舍弃掉一部分的位数,导致浮点数在内存中并不是准确保存的。 所以结论是:浮点数在内存中并不是准确保存的。那根据这一点,在我们对浮点数进行比较大小时,我们就不能简单地对2个数据进行 ==是否相等的判断,而是有一定的误差。 int main() { //这是错误的比较浮点数的大小,因为可能会导致一些误差 flaot f = 3.45; if(f == 3.45) { } //这是正确的比较浮点数的大小 if(fabs(f-3.45) num); } int main() { struct S s = {{1,2,3,4}, 1000}; print1(s); //传结构体 print2(&s); //传地址 return 0; }结构体讲完就得讲讲结构体实现位段的能力。 4.1什么是位段?
结论:从修改了初始值的常量开始后面的枚举常量表示的数字都递增+1,前面的保持不变。 5.2枚举的优点
//写一个计算器-完成整数的加法、减法、乘法、除法 //代码一 enum Option { EXIT,//0 ADD,//1 SUB, MUL, DIV }; void menu() { printf("**********************************\n"); printf("****** 1. add 2. sub ******\n"); printf("****** 3. mul 4. div ******\n"); printf("****** 0. exit ******\n"); printf("**********************************\n"); } int main() { int input = 0; do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case SUB: break; case ADD: break; case MUL: break; case DIV: break; case EXIT: printf("退出\n"); break; default: printf("选择错误,重新选择\n"); break; } } while (input); return 0; } void menu() { printf("**********************************\n"); printf("****** 1. add 2. sub ******\n"); printf("****** 3. mul 4. div ******\n"); printf("****** 0. exit ******\n"); printf("**********************************\n"); } int main() { int input = 0; do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: break; case 2: break; case 3: break; case 4: break; case 0: printf("退出\n"); break; default: printf("选择错误,重新选择\n"); break; } } while (input); return 0; } 对比一下代码一和代码二,在我们看代码主函数main()中的分支语句switch,发现两个代码的可读性不一样,看代码一我们可以明确知道哪一部分要实现加减乘除具体的操作,而代码二中我们是根据打印菜单对应下来才写相应的操作的。 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |