网站设置搜索关键字,企业网站项目流程,免费做淘客cms网站,网站备案拍照背景图前言#xff1a; 如果你还对结构体不是很了解#xff0c;那么本篇文章将会从 为什么存在结构体#xff0c;结构体的优点#xff0c;结构体的定义#xff0c;结构体的使用与结构体的大小依次介绍#xff0c;同样会附带枚举与联合体 目录 为什么存在结构体#xff1a; 结构…前言 如果你还对结构体不是很了解那么本篇文章将会从 为什么存在结构体结构体的优点结构体的定义结构体的使用与结构体的大小依次介绍同样会附带枚举与联合体 目录 为什么存在结构体 结构体的优点
结构体的定义
结构体的使用
方法一
方法二 函数传值打印
方法三 函数传址打印 两种打印方法
第二种是利用- 这里的 -就相当于(*).
方法四 跟方法三差不多不利用函数打印
结构体的typedef 结构体的大小计算 ⾸先得掌握结构体的对⻬规则
1.结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处 2.其他成员变量要对⻬到某个数字对⻬数的整数倍的地址处。对⻬数编译器默认的⼀个对⻬数与该成员变量⼤⼩的较⼩值。VS 中默认的值为 8
Linux中gcc没有默认对⻬数对⻬数就是成员⾃⾝的⼤⼩
3.结构体总⼤⼩为最⼤对⻬数结构体中每个成员变量都有⼀个对⻬数所有对⻬数中最⼤的的整数倍。
4.如果嵌套了结构体的情况嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处结构 体的整体⼤⼩就是所有最⼤对⻬数含嵌套结构体中成员的对⻬数的整数倍。
先解决对其数问题 枚举 枚举的使用案例
联合体也叫共用体 为什么存在结构体 当一个整体由多个数据构成时于是人们就创造了数组我们用数组来表示这个整体但是数组有个特点内部的每一个元素都必须是相同类型的数据。 ☀ 在实际应用中我们通常需要由不同类型的数据来构成一个整体比如学生这个整体可以由姓名、年龄、身高等数据构成这些数据都具有不同的类型姓名可以是字符串类型年龄可以是整型身高可以是浮点型。 ☀ 为此C语言专门提供了一种构造类型来解决上述问题这就是结构体它允许内部的元素是不同类型的。 结构体的优点 可以在一个结构中声明不同的数据类型。相同结构的结构体变量是可以相互赋值的。结构体的存储方式可以提高CPU对内存的访问速度。结构体可以将同一对象的多个数据类型存储在一起方便数据的存储和处理。可以通过结构体变量名和成员名来访问数据。可以定义结构体数组方便批量处理数据。 那么有有优点就会有缺点
如果项目的复杂性增加管理所有数据成员就变得很困难 。对程序中的一个数据结构进行更改需要在其他几个地方进行更改。 所以很难跟踪所有的变化。结构体需要更多的存储空间因为它为所有数据成员分配内存甚至速度更慢。结构体占用更多存储空间因为它为所有不同的数据成员提供内存而联合仅占用最大数据大小参数所需的内存大小并且与其他数据成员共享相同的内存。 结构体的定义 一般结构体定义便是如下
struct stu
{//变量成员
};
这里的struct是必不可少的部分而stu是我们自拟定的里面便是填充的变量成员
这个结构体就是struct stu类型的
同理下面这个结构体就是struct st类型的
struct st
{//变量成员
}; 这时候我们便可以在里面填充成员
比如这样
struct st
{int a;char b;struct st* ps;//也可以填充这个类型的指针
};
那么结构体定义完后我们开始讲解怎么去使用 结构体的使用 这里的s为变量名
struct st
{int a;char b;
};
int main()
{struct st s { 10,b };//初始化return 0;
} 接下来介绍打印 方法一 struct st
{int a;char b;
};
int main()
{struct st s { 10,b };//初始化printf(%d %c, s.a, s.b);return 0;
} 方法二 函数传值打印 struct st
{int a;char b;
};
void print(struct st ps)
{printf(%d %c, ps.a, ps.b);
}
int main()
{struct st s { 10,b };//初始化print(s);return 0;
} 方法三 函数传址打印 两种打印方法 第一种的打印是利用解引用 第二种是利用- 这里的 -就相当于(*). struct st
{int a;char b;
};
void print(struct st* ps)
{printf(%d %c\n, (*ps).a, (*ps).b);printf(%d %c\n, ps-a, ps-b);
}
int main()
{struct st s { 10,b };//初始化print(s);return 0;
} 方法四 跟方法三差不多不利用函数打印 struct st
{int a;char b;
};
int main()
{struct st s { 10,b };//初始化struct st* ps s;printf(%d %c\n, (*ps).a, (*ps).b);printf(%d %c\n, ps-a, ps-b);return 0;
} 结构体的typedef 当一个结构体类型的类型名过于长的时候我们不免过于不想去写这时候就可以用typedef
重命名使用起来很简单
typedef struct st
{int a;char b;
}st;
int main()
{struct st s { 10,b };//初始化//等价于st s { 10,b };//return 0;
} 结构体的大小计算 先举例一个代码 代码跑出来这个结构体大小是8
那么怎么计算的呢 其原理就是对其原则 ⾸先得掌握结构体的对⻬规则
1.结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处 2.其他成员变量要对⻬到某个数字对⻬数的整数倍的地址处。对⻬数编译器默认的⼀个对⻬数与该成员变量⼤⼩的较⼩值。VS 中默认的值为 8
Linux中gcc没有默认对⻬数对⻬数就是成员⾃⾝的⼤⼩
3.结构体总⼤⼩为最⼤对⻬数结构体中每个成员变量都有⼀个对⻬数所有对⻬数中最⼤的的整数倍。
4.如果嵌套了结构体的情况嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处结构 体的整体⼤⼩就是所有最⼤对⻬数含嵌套结构体中成员的对⻬数的整数倍。 我们计算一下这个结构体大小
struct S1
{char c1;int i;char c2;
};
printf(%d\n, sizeof(struct S1))
先解决对其数问题
char 自身对齐数为1 vs上默认对齐数为8 实际取小的 那么最后为1
int 为4 偏移量
在C语言中偏移量通常指的是结构体中成员变量相对于结构体起始地址的偏移量。假设有一个结构体定义如下
struct Person {int id;char name[20];int age;
};假设struct Person p;是一个Person类型的结构体变量我们可以通过p.id、p.name和p.age来获取各个成员变量的地址。偏移量就是从结构体起始地址到成员变量地址的字节偏移量。
例如假设p表示结构体p的起始地址p.id表示id成员变量的地址那么p.id - p就是id相对于结构体起始地址的偏移量。在C语言中可以使用指针和强制类型转换来计算偏移量例如
int offset (char *)p.name - (char *)p;这样就可以得到name成员变量相对于结构体p的偏移量。偏移量在一些底层编程中经常用来访问结构体中的特定成员变量尤其是在处理二进制数据或者硬件寄存器时非常有用。
画图表示如下 那么我们进行利用图进行计算
typedef struct st
{char c1;int i;char c2;
}st;
int main()
{printf(%zd, sizeof(st));return 0;
}第一个char偏移量为0放于第一个int放于偏移量为4的整数倍数处 最后一个char偏移量为1放于1的整数倍数处
用图表示如下 图上的大小一共占了9个字节
然后我们进行最后一步 最大对齐数为4 而9不是最大对齐数的整数倍 所以要浪费3个字节补充该结构体大小到12 那么最大怎么算了就可以解答上面那个问题为什么是8 //练习3
struct S3
{double d;char c;int i;
};
printf(%d\n, sizeof(struct S3));
//练习4-结构体嵌套问题
struct S4
{char c1;struct S3 s3;double d;
};
printf(%d\n, sizeof(struct S4)); 答案分别是16 32 枚举 在《C语言深度剖析》这本书中留有一个问题枚举变量的大小是多少
大家猜一下大小为多少
enum Color
{GREEN 1,RED,BLUE,GREEN_RED 10,GREEN_BLUE,sss,
}c;
int main()
{printf(%zd, sizeof(c));
}
答案是4为啥呢
因为枚举变量的取值为花括号内的任意一个值有且只能有其中一个值而这个值是int型的在X86系统中int型的数据占内存4个字节。所以sizeof(c) 4也就是枚举变量的值为4。 枚举的使用案例 当我们写菜单的时候会用到switch语句
当我们写case是一般会用到case 1 case 2
但如果功能一旦多我们就会分不清该case 要实现哪一项功能
这时候就可以用到枚举 就比如通讯录
enum option
{EXIT,//等价于0ADD,//1DEL,//2SEARCH,//3MODIFY,//4SHOW, //5SORT,//6SAVE,//7
};void menu()
{printf(**************************************\n);printf(***** 1.add 2.del *****\n);printf(***** 3.search 4.modify *****\n);printf(***** 5.show 6sort *****\n);printf(***** 7.save 0.exit *****\n);printf(**************************************\n);
}
int main()
{do {menu();printf(请输入你的选择:);scanf(%d, input);switch (input){case ADD:Addcontact(con);break;case DEL:Delcontact(con);break;case SEARCH:Searchcontact(con);break;case MODIFY:Modifycontact(con);break;case SHOW:Showcontact(con);break;case SORT:SortContact(con);break;case SAVE:SaveContact(con);break;case EXIT:SaveContact(con);DestroyContact(con);printf(退出通讯录\n);break;default:printf(输入错误请重新输入:\n);break;}} while (input);return 0;
}联合体也叫共用体 联合的成员是共⽤同⼀块内存空间的这样⼀个联合变量的⼤⼩⾄少是最⼤成员的⼤⼩因为联合 ⾄少得有能⼒保存最⼤的那个成员。
那么看以下代码 发现三者的空间是共用一块空间所以这也对应了名字共用体公用一块空间 #include stdio.h
union Un
{char c;int i;
};
int main()
{//联合变量的定义 union Un un {0};un.i 0x11223344;un.c 0x55;printf(%x\n, un.i);return 0;
}
既然公用一块空间那么小端
这个代码运行结果如何呢
我们发现将i的第4个字节的内容修改为55了其实是改的低地址处的数据 同样大端下会打印55223344
利用联合体写一个函数判断机器为大端还是小端
int check_sys()
{union{int i;char c;}un;un.i 1;return un.c;//返回1是⼩端返回0是⼤端
}