ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

C语言:结构体、联合和枚举

C语言:结构体、联合和枚举 目录一、结构体1.结构体的声明2.结构体变量的创建和初始化3.结构体的自引用4.结构体内存对齐5.结构体传参6.结构体实现位段二、联合体1.联合体类型的声名2.联合体的特点三、枚举类型1.枚举类型的声名2.枚举类型的可能取值总结一、结构体结构是一些值的集合这些值称为成员变量结构的每个成员都可以是不同类型的变量。1.结构体的声明struct tag { member-list; }variable-list;例子struct Stu { char name[20]; int age; char sex[5]; char id[20]; };//分号不能丢2.结构体变量的创建和初始化struct Stu { char name[20]; int age; char sex[5]; char id[20]; }s3,s4;//全局变量 struct Stu s2; int main() { struct Stu s1;//局部变量 return 0; }特殊的结构体声明匿名结构体类型没有名称只能使用一次。struct { int a; char b; float c; }x; int main() { return 0; }下面的代码是一个非法的代码编译器觉得是两个不同的结构体。struct { int a; char b; float c; }x; struct { int a; char b; float c; }*px; int main() { return 0; }3.结构体的自引用在结构中包含一个类型为该结构本身的成员是否可以呢答案是可以但是要写成指针的形式来指向下一个数据如果是结构体里包含结构体然后包含的结构体再包含结构体就不知道要分配多少的内存了所以结构体里可以包含该类型的结构体指针。4.结构体内存对齐我们已经掌握了结构体的基本使用了。现在我们深入讨论一个话题计算结构体的大小也就是结构体的内存对齐。对齐规则1. 结构体的第一个成员需对齐到结构体变量起始位置即偏移量为 0 的地址处。2.从第二个成员变量开始对齐到某个对齐数的整数倍的地址处。对齐数编译器默认的的一个对齐数与该成员变量的大小的较小值—vs中默认为8—Linux中gcc没有默认对齐数对齐数就是该成员变量的大小。3.结构体总大小为最大对齐数的整数倍4.如果嵌套了结构体的情况嵌套的结构体成员对齐到自己成员中最大对齐数的整数倍处结构体整体的大小就是最大对齐数的整数倍。修改默认对齐数#pragma这个预处理指令可以改变编译器的默认对齐数#pragma pack(1)//设置默认对齐数为15.结构体传参传值调用 传址调用传址调用更好传值调用浪费空间和时间地址只是4个或者8个字节。如果说怕改变数据的值指针可以用const约束。6.结构体实现位段位段的声名和结构是类似的有两个不同1.位段的成员必须是int、unsigned int或者signed int在C99中位段的类型也可以选择其他整型家族类型比如char2.位段的成员名后边有一个冒号和一个数字。结构体位段数字代表所占的二进制位的个数位段的内存分配位段的空间是按照需要以4个字节或者一个字节的方式来开辟的。位段涉及很多不确定性位段是不跨平台的注重可移植的程序应该避免使用位段。在VS环境下1.分配到的内存是从右向左使用的低位向高位2.剩余空间不够下一个成员使用的时候直接浪费。注意事项位段的几个成员共有一个字节有的成员的起始位置不是某个字节的起始位置那么这些位置处是没有地址的。内存中每个字节分配一个地址一个字节内部的bit位是没有地址的。所以不能对位段的成员使用操作符这一样就不能用scanf给位段成员输入值只能先输入一个变量中然后赋值给位段的成员。二、联合体1.联合体类型的声名像结构体一样联合体也是由一个或者多个成员构成这些成员可以是不同的类型。联合体的关键字是union但是编译器只为最大的成员分配足够的内存空间。联合体的特点是所有成员共用同一块内存空间。所以联合体也叫做共用体。给联合体其中一个成员赋值其他成员的值也跟着变化。2.联合体的特点联合体的成员是共用同一块内存空间的这样一个联合体变量的大小至少是最大成员的大小。对比一下相同成员的结构体和联合体所占的内存情况。当最大成员的大小不是最大对齐数的整数倍的时候就要对齐到最大对齐数的整数倍。现在我们要统计商品信息共有三种商品分别是图书、杯子、衬衫。这三种商品都需要统计库存量、价格和商品类型图书还需要统计书名、作者、页数杯子还需要统计设计衬衫还需要统计设计、可选颜色、可选尺寸。我们可以用结构体来统计struct gift_list { //公共部分 int rest_num; int price; char type[20]; //非公共部分 char book_name[20]; char author[20]; int page; char design[20]; char colour[20]; int size; };但是会产生一个问题就是会浪费很多空间比如我们在统计一本图书的信息的时候我们不需要统计它的设计等内容。在这个时候我们就可以应用联合体来完成统计这样会节省很多空间。代码如下struct gift_list { //公共部分 int rest_num; int price; char type[20]; //非公共部分 union { struct { char book_name[20]; char author[20]; int page; }book; struct { char design[20]; }mug; struct { char design[20]; char colour[20]; int size; }shirt; }item; };联合的一个小练习判断机器是大端还是小端三、枚举类型1.枚举类型的声名枚举类型顾名思义就是一一列举把可能的取值一一列举。比如现实生活中一周的星期一到星期天可以一一列举。性别有男、女、保密可以一一列举。月份可以一一列举。以上三种数据就可以用枚举类型。例子2.枚举类型的可能取值若未定义值的话默认第一个为0剩下的值递增若定义第一个选项的值的话情况如下定义中间元素的值情况如下我们可以用#define定义常量为什么要使用枚举呢。因为相比于#define枚举有以下几个优点1.增加代码的可读性和可维护性2.和#define定义的标识符比较枚举有类型检查更加严谨。3.便于调试预处理阶段会删除#define定义的符号4.使用方便可以一次定义多个常量。5.枚举常量是遵循作用域规则的枚举声名在函数内只能在函数内使用。在C语言中可以拿整数给枚举变量赋值但是在C中不行C的类型检查比较严格。总结以上就是今天的内容啦希望大家能有所收获。
返回列表