做国外搞笑网站有哪些,wordpress 本地运行,笑话网站域名,网站产品介绍页面的布局方案文章目录 #x1f4dd;前言#x1f320; 联合体类型的声明#x1f309;联合体的特点 #x1f320;相同成员的结构体和联合体对⽐#x1f309;联合体⼤⼩的计算 #x1f320;联合体应用#x1f309;枚举类型的声明 #x1f320;枚举类型的优点#x1f309; 枚举类型的使… 文章目录 前言 联合体类型的声明联合体的特点 相同成员的结构体和联合体对⽐联合体⼤⼩的计算 联合体应用枚举类型的声明 枚举类型的优点 枚举类型的使⽤ 总结 前言
联合体union是允许一个变量通过不同的接口访问内存的一种数据类型表示一个变量可以存储不同类型的值而枚举是使用enum关键字定义一组相关且互斥的整形常量集合。本章阿森将和你学习联合体类型的声明特点有关大小的计算还有枚举类型的声明优点和使用。文章干货满满学习起来吧 联合体类型的声明
同结构体一样声明结构体类型需要使用struct关键字联合体则用union关键字。
包含对象名的声明方式
union 联合体名
{类型 成员1;类型 成员2;... 类型 成员n;
}对象名;代码理解
#include stdio.hunion S
{char c;int a;
}s1;int main()
{s1.c a;printf(%c\n, s1.c);s1.a 10;printf(%d\n, s1.a);return 0;
}代码运行
不包含对象名的声明格式
union 类型名
{ 类型 成员1;类型 成员2;... 类型 成员n;
};代码实现
#include stdio.hunion S
{char c;int a;
};int main()
{union S s2;s2.c b;printf(%c\n, s2.c);s2.a 20;printf(%d\n, s2.a);return 0;
}运行
联合体的特点
编译器只为最⼤的成员分配⾜够的内存空间。联合体的特点是所有成员共⽤同⼀块内存空间。所以联合体也叫共⽤体。
例如
union u
{char c;int u;
};int main()
{union u uu;printf(联合体uu的大小为%zd\n, sizeof(uu));printf( (uu)地址为%p\n, uu);printf((uu.c)地址为%p\n, (uu.c));printf((uu.u)地址为%p\n, (uu.u));return 0;
}输出 图解
联合的成员是共⽤同⼀块内存空间的这样⼀个联合变量的⼤⼩⾄少是最⼤成员的⼤⼩因为联合⾄少得有能⼒保存最⼤的那个成员。
//联合类型的声明
union u
{char c;int i;
};
int main()
{//联合变量的定义union u uu { 0 };un.i 0x11223344;un.c 0x55;printf(%x\n, uu.i);return 0;
}输出 图解 union定义了int和char两个成员共享同一块内存空间int类型占4个字节低地址在前高地址在后char类型只占1个字节存储在int的低地址字节。当执行uu.i 0x11223344时此时int的4个字节分别存储如图然后执行 uu.c 0x55由于VS是小端存储低字节放在低地址处char只占1个字节它会覆盖int低地址的那个字节。所以int原来低地址字节0x44被覆盖为0x55。
相同成员的结构体和联合体对⽐
结构体和联合体的主要区别在于
结构体中每个成员占用自己独立的内存空间可以同时访问每个成员。联合体中所有成员共享同一块内存空间只能同时访问其中一个成员。 内存布局 结构体中每个成员都有固定的偏移地址占用独立的内存空间。 联合体中所有成员共享同一块内存没有偏移地址只能使用一个成员。 访问成员 结构体可以同时读取各个成员的值。 联合体只能访问当前使用的成员其他成员的值将被覆盖。 大小 结构体的大小是所有成员大小的和。 联合体的大小至少是最大成员的大小。
结构体
struct S
{char c;int i;
};
struct S s {0};联合体
union u
{char c;int i;
};
union u uu { 0 };图解对比 结构体S占用char int有可能开辟浪费的空间大小的内存可以独立访问c和i联合体u只占用int大小的内存访问c或i时值会覆盖结构体各成员独立联合体成员共享同一内存空间。
联合体⼤⼩的计算
点击可以查看结构体的内存对齐规则——【C语言】自定义类型结构体深入解析二结构体内存对齐宏offsetof计算偏移量结构体传参 联合体大小计算规则
联合的⼤⼩⾄少是最⼤成员的⼤⼩。当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候就要对⻬到最⼤对⻬数的整数倍。 来代码理解
union Un1
{char c[5];int i;
};union Un2
{short c[7];int i;
};int main()
{printf(%zd\n, sizeof(union Un1));//8printf(%zd\n, sizeof(union Un2));//16return 0;
}运行 图解分析 首先看union Un1如果联合体的大小是最大成员的最大成员的的大小在联合体union Un1中char[5]的大小理应是5那计算的结果不是5。为什么是8呢这是因为它完成了对齐的操作如果是数组是按元素类型大小来算他的对齐数的。char 元素的类型大小是1VS默认对齐数是8对齐数是8i 的大小是4VS默认对齐数是8对齐数是4接下来41整个联合体的对齐数是4根据当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候就要对⻬到最⼤对⻬数的整数倍。此时最大成员大小是数组char [5]大小为5,5不是4的整数倍84*2是4的整数倍。是不是真的是这样呢会不会是偶然呢 接下来我们看第二组union Un2首先short c[7]是数组总大小为14然后由于数组是按照元素的类型大小来算对齐数类型为short类型大小为2VS默认对齐数为8对齐数为228i的大小是4VS默认对齐数是8那么对齐数是448然后整个联合体的对齐数是442然后看成员最大对齐数的大小short c[7]的大小是2*714是不是整个联合体的对齐数4的整数倍可见14不是4的整数倍 根据第二条规则当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候就要对⻬到最⼤对⻬数的整数倍。因此还要多用2个字节升到164*4个字节才是整数倍。 联合体的对齐规则与结构体相似 点击可以查看结构体的内存对齐规则——【C语言】自定义类型结构体深入解析二结构体内存对齐宏offsetof计算偏移量结构体传参 联合体应用 使⽤联合体是可以节省空间的 ⽐如我们要搞⼀个活动要上线⼀个礼品兑换单礼品兑换单中有三种商品图书、杯⼦、衬衫。 每⼀种商品都有库存量、价格、商品类型和商品类型相关的其他信息。 图书书名、作者、⻚数 杯⼦设计 衬衫设计、可选颜⾊、可选尺⼨ 结构体表示
struct gift_list
{//公共属性int stock_number;//库存量double price; //定价int item_type;//商品类型//特殊属性char title[20];//书名char author[20];//作者int num_pages;//⻚数char design[30];//设计int colors;//颜⾊int sizes;//尺⼨
};上述的结构其实设计的很简单⽤起来也⽅便但是结构的设计中包含了所有礼品的各种属性这样使得结构体的⼤⼩就会偏⼤⽐较浪费内存。因为对于礼品兑换单中的商品来说只有部分属性信息是常⽤的。⽐如商品是图书就不需要design、colors、sizes。 所以我们就可以把公共属性单独写出来剩余属于各种商品本⾝的属性使⽤联合体起来这样就可以介绍所需的内存空间⼀定程度上节省了内存。
联合体应用
struct gift_list
{int stock_number;//库存量double price; //定价int item_type;//商品类型union{struct{char title[20];//书名char author[20];//作者int num_pages;//⻚数}book;struct{char design[30];//设计}mug;struct{char design[30];//设计int colors;//颜⾊int sizes;//尺⼨}shirt;}item;
};练习写⼀个程序判断当前机器是⼤端还是⼩端 第一种方法
int check_sys()
{int n 1;//01 00 00 00 00 00 00 01return *(char*)n;
}int main()
{int ret check_sys();if (ret 1)printf(小端\n);elseprintf(大端\n);return 0;
}VS运行
第二种联合体巧妙方法
int check_sys()
{union{char c;int i;}u;u.i 1;return u.c;//返回1是⼩端返回0是⼤端
}VS运行
小端图解 大端存储是指数据的低位字节内容保存在内存的高地址处而数据的高位位字节内容保存在内存的低地址处。 小端存储是指数据的低位字节内容保存在内存的低地址处而数据的高位字节内容保存在内存的高地址处。 如果01是低位字节存储到低地址c时是小端存储如果01低位字节存储到高地址处没有存储到c的位置那么c的位置存储着00返回为0是大端存储。
枚举类型的声明
枚举类型(enum)是一种特殊的类型它可以为一组相关的常量值赋予用户定义的名称。 —简单来说枚举顾名思义就是⼀⼀列举。 枚举类型的声明语法
enum 标识符
{枚举常量1, 枚举常量2,...
} 变量;enum 关键字声明这是一个枚举类型。 标识符是枚举类型的名称。 在大括号{}内列出枚举类型的多个枚举常量用逗号分隔。 变量是枚举类型的变量可以直接使用枚举类型名或枚举常量初始化。
例如
enum Color //Color是枚举类型名
{RED, // 枚举常量 GREEN,BLUE
} color;///color是Color类型的变量int main()
{printf(%d\n, RED);printf(%d\n, GREEN);printf(%d\n, BLUE);return 0;
}
输出
枚举常量默认从0开始依次累加1。也可以手动为枚举常量赋值
例如
enum Color
{RED 1,GREEN 2,BLUE 4
}运行结果
当然第一个元素未被赋值给其它的常量赋值该常量前面的值是默认值012后面递增1。
例如
enum Color
{RED,white,GREEN 8,BLUE ,BLACK,
};int main()
{printf(%d\n, RED);printf(%d\n, white);printf(%d\n, GREEN);printf(%d\n, BLUE);printf(%d\n, BLACK);return 0;
}输出
枚举类型的优点 为什么使⽤枚举 我们可以使⽤ #define 定义常量为什么⾮要使⽤枚举 枚举的优点
增加代码的可读性和可维护性 如之前的扫雷中可以这样定义用PLAY代替1EXIT代替0,更具有个性化
#include stdio.h
#include string.h// 定义游戏选择枚举类型
enum Game_Selection
{EXIT, // 退出游戏PLAY // 开始游戏
};// 打印菜单
void menu()
{printf(********** Menu **********\n);printf(PLAY - Start the game\n);printf(EXIT - Exit the game\n);printf(********** Menu **********\n);
}int main()
{enum Game_Selection input; // 声明游戏选择变量char choice[10]; // 声明选择输入缓冲区do{menu(); // 调用菜单函数printf(Please enter your choice: );scanf(%s, choice); // 读取选择输入getchar(); // 清除输入缓冲区if (strcmp(choice, PLAY) 0){input PLAY; // 设置选择为开始游戏}else if (strcmp(choice, EXIT) 0){input EXIT; // 设置选择为退出游戏}else{printf(输入错误请重新输入\n);continue; // 输入错误继续循环}switch (input){case PLAY:printf(扫雷游戏启动\n);break;case EXIT:printf(不玩了启动不了\n);break;}} while (input ! EXIT);return 0;
}代码运行 和#define定义的标识符⽐较枚举有类型检查更加严谨。 便于调试预处理阶段会删除 #define 定义的符号 使⽤⽅便⼀次可以定义多个常量 枚举常量是遵循作⽤域规则的枚举声明在函数内只能在函数内使⽤ 枚举类型的使⽤
那是否可以拿整数给枚举变量赋值呢在C语⾔中是可以的但是在C是不⾏的C的类型检查⽐较严格。 在C语言中枚举类型实际上就是整数类型编译器会把枚举常量替换成对应的整数值。所以可以用整数直接给枚举变量赋值。 而在C中枚举类型是完全独立的类型。编译器会检查类型是否匹配不允许用整数直接给枚举变量赋值。
例如
# define _CRT_SECURE_NO_WARNINGS 1
#include stdio.h
#include string.h
//C语言
enum Color//颜⾊
{RED 1,GREEN 2,BLUE 4
};
int main()
{enum Color c;c 1; // 可以直接赋值整数return 0;
}输出
// C语言
enum Color//颜⾊
{RED 1,GREEN 2,BLUE 4
};Color c;
c 1; // 错误类型不匹配输出 总结 C语言中枚举类型实际上就是整数允许用整数直接赋值 C中枚举类型是独立类型不允许用整数直接赋值需要强制类型转换 总结
这次阿森和你一起学习联合体类型的声明特点然后进行相同成员的结构体和联合体对⽐⼤⼩的计算联合体应用枚举类型的声明优点和扫雷改造使⽤方法阿森将下一节和你一起学习动态内存管理 。
感谢你的收看如果文章有错误可以指出我不胜感激让我们一起学习交流如果文章可以给你一个小小帮助可以给博主点一个小小的赞