C语言14之什么是共用体和枚举?

1.共用体union

1.1共用体类型的定义、变量定义和使用

1)共用体union和结构体struct在类型定义、变量定义、使用方法上很相似。

2)共用体和结构体的不同:结构体类似于一个包裹,结构体中的成员彼此是独立存在的,分布在内存的不同单元中,他们只是被打包成一个整体叫做结构体而已;共用体中的各个成员其实是一体的,彼此不独立,他们使用同一个内存单元。可以理解为:有时候是这个元素,有时候是那个元素。更准确的说法是同一个内存空间有多种解释方式。

3)共用体union就是对同一块内存中存储的二进制的不同的理解方式。

4)在有些书中把union翻译成联合(联合体),这个名字不好。现在翻译成共用体比较合适。

5)union的sizeof测到的大小实际是union中各个元素里面占用内存最大的那个元素的大小。因为可以存的下这个就一定能够存的下其他的元素。

6)union中的元素不存在内存对齐的问题,因为union中实际只有1个内存空间,都是从同一个地址开始的(开始地址就是整个union占有的内存空间的首地址),所以不涉及内存对齐。

1.2共用体和结构体的相同和不同

1)相同点就是操作语法几乎相同。

2)不同点是本质上的不同。struct是多个独立元素(内存空间)打包在一起;union是一个元素(内存空间)的多种不同解析方式。

1.3共用体的主要用途

1)共用体就用在那种对同一个内存单元进行多种不同规则解析的这种情况下。

2)C语言中其实是可以没有共用体的,用指针和强制类型转换可以替代共用体完成同样的功能,但是共用体的方式更简单、更便捷、更好理解。

2.枚举

2.1枚举是用来干嘛的?

1)枚举在C语言中其实是一些符号常量集。直白点说:枚举定义了一些符号,这些符号的本质就是int类型的常量,每个符号和一个常量绑定。这个符号就表示一个自定义的一个识别码,编译器对枚举的认知就是符号常量所绑定的那个int类型的数字。

2)枚举中的枚举值都是常量,怎么验证?

3)枚举符号常量和其对应的常量数字相对来说,数字不重要,符号才重要。符号对应的数字只要彼此不相同即可,没有别的要求。所以一般情况下我们都不明确指定这个符号所对应的数字,而让编译器自动分配。(编译器自动分配的原则是:从0开始依次增加。如果用户自己定义了一个值,则从那个值开始往后依次增加)

2.2 C语言为何需要枚举

1)C语言没有枚举是可以的。使用枚举其实就是对1、0这些数字进行符号化编码,这样的好处就是编程时可以不用看数字而直接看符号。符号的意义是显然的,一眼可以看出。而数字所代表的含义除非看文档或者注释。

2)宏定义的目的和意义是:不用数字而用符号。从这里可以看出:宏定义和枚举有内在联系。宏定义和枚举经常用来解决类似的问题,他们俩基本相当可以互换,但是有一些细微差别。

2.3宏定义和枚举的区别

1)枚举是将多个有关联的符号封装在一个枚举中,而宏定义是完全散的。也就是说枚举其实是多选一。

2)什么情况下用枚举?当我们要定义的常量是一个有限集合时(譬如一星期有7天,譬如一个月有31天,譬如一年有12个月••••),最适合用枚举。(其实宏定义也行,但是枚举更好)

3)不能用枚举的情况下(定义的常量符号之间无关联,或者无限的)用宏定义。

总结:宏定义先出现,用来解决符号常量的问题;后来人们发现有时候定义的符号常量彼此之间有关联(多选一的关系),用宏定义来做虽然可以但是不贴切,于是乎发明了枚举来解决这种情况。

2.4枚举的定义和使用

#include "stdio.h"

 

/*

****************************************************************

*     enumeration 类型定义

****************************************************************

*/

/*        // 定义方法1,定义类型和定义变量分离开

enum week

{

    SUN,        // SUN = 0

    MON,        // MON = 1;

    TUE,

    WEN,

    THU,

    FRI,

    SAT,

};

*测试结论记录

*******************************************************************

1、编译以下代码

    enum week w1;        

    w1 = TUE;        

    printf("%s\n", w1);        

出现警告,enum.c:28: warning: format '%s' expects type 'char *', but argument 2 has type 'unsigned int'

分析:典型的格式化输出和类型不匹配,从警告信息可以看出enum变量的类型为unsigned int

    既然是unsigned int,那自然使用%d打印是正确的了。

2、不能有重名的枚举类型。即在一个文件中不能有两个或两个以上的enum被typedef成相同的别名。

分析:这很好理解,因为将两种不同类型重命名为相同的别名,这会让gcc在还原别名时遇到困惑。比如你定义了

typedef int INT;    typedef char INT; 那么INT到底被译为int还是char呢?

3、不能有重名的枚举成员。

分析:经过测试,两个struct类型内的成员名称可以重名,而两个enum类型中的成员不可以重名。实际上从两者的成员

在访问方式上的不同就可以看出了。struct类型成员的访问方式是:变量名.成员,而enum成员的访问方式为:成员名。

因此若两个enum类型中有重名的成员,那代码中访问这个成员时到底指的是哪个enum中的成员呢?

两个#define宏定义是可以重名的,该宏名真正的值取决于最后一次定义的值。编译器会给出警告但不会error

 

********************************************************************

*/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值