由C语言位域(冒号)谈C语言的结构体、枚举、共用体
2015-08-19 17:02
302 查看
综述
今天看到一行代码unsigned char busy:1;
不太明白 : 的作用,百度了几分钟,发现是结构体中位域操作符,深感平时工作疏于学习,以至于这么简单的问题还不知道,所以写了这篇文章,以作为复习。
1、关于位域
有些信息在储存时,并不需要占用一个完整的字节,而只需占几个或一个二进制位,例如存放一个开关常量,只有0和1两种状态,用一个二进制位即可满足要求,无需浪费空间,并且可以使处理更加简便,所以C语言提供了一种数据结构,成为位域(或位段)。这样就可以把几个不同的对象用一个字节的二进制位域来表示。所谓“位域”就是是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每一个域有一个域名,允许在程序中按域名进行操作。位域主要用于结构体。
struct temp { int a:8; int b:2; int c:6; }data;在上面的代码中,data占2个字节。位域的两个特点如下:
1.1. 一个位域必须存储在同一个字节中,不能跨两个字节。如果一个字节所剩空间不够存放另一个位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:
struct temp { char a:4 char :0 //空域 char b:4 //从下一单元开始存放 char c:4 }其中,a占第一个字节的4位,后4位填零不用,b从第二个字节开始,占4位,c占剩下4位。
1.2. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:
struct temp { char a:4 char :2 //空域 char b:4 //从下一单元开始存放 char c:4 }
2、结构体
2.1、存在理由
描述一组具有相同类型数据的有序集合,用于处理大量相同类型的数据运算 使用构造类型——数组描述一组具有不同类型数据的有序集合,用于处理大量不同类型的数据运算 使用构造类型——结构体
2.2、定义方式
2.2.1、先声明结构体类型再定义变量名
struct stu { 成员列表 }; struct stu Lucy;
2.2.2、在声明类型的同时定义变量
struct stu { 成员列表 }Lucy;
2.2.3、直接定义结构体类型变量,无类型名
struct { 成员列表 }Lucy,Bob;在上面三种定义结构体变量的方式中,stu为结构体类型名(第三种没有类型名),Lucy为结构体变量名。可以同时变量多个结构体变量名(如第三个)。
结构体类型名:指定了一个结构体类型(相当于char),它相当于一个模型,但其中并无具体数据,系统对之也不分配实际内存单元。
结构体变量名:实际分配空间——为了能在程序中使用结构体类型的数据,应当定义结构体类型的变量,并在其中存放具体的数据。
我们推荐使用如下方法(使用typedef重命名)其中STU为结构体类型名,Lucy与Bob为结构体变量名:
typedef struct student { int num; char name[20]; char sex; }STU; STU Lucy,Bob;
2.4、注意事项
2.4.1、结构体变量的成员引用必须单独引用结构体变量名.成员名
如:
Lucy.num = 101; scanf("%c",&Lucy.sex); printf("%s",Lucy.name);2.4.2、允许具有相同类型的结构体变量相互赋值(多用于结构体成员整体操作,例如排序等)
Bob = Lucy;2.4.3、结构体可以在定义的时候进行初始化
STU Lucy = {12, "hello", 'm'};3.4、允许嵌套定义结构体变量,成员引用多级引用
Lucy.birthday.mouth = 12;关于结构体数组和结构体指针等深层次用法,在中介绍,此处不做赘述!
3、共用体
3.1、存在理由和特点
a.同一内存段可以用来存放几种不同类型的成员,但每一瞬间只有一种起作用b.共用体变量中起作用的才成员是最后一次存放的成员,在存入一个新的成员后原有成员的值会被覆盖
c.共用体变量的地址和它的个成员的地址都是同一地址
3.2、定义方式
和结构体非常类似,有三种定义方式,我们推荐下面这种:typrdef union data { short int i; //短整型:2个字节 char ch; //字符型:1个字节 float f; //实型:4个字节 }DATA; DATA a,b;a.i——>引用共用体变量中的整型变量i
a.ch——>引用共用体变量中的整型变量ch
a.f——>引用共用体变量中的整型变量f
3.3、参考代码
#include<stdio.h> //共用体 typrdef union data { long int x; //长整型:4个字节 char y; //字符型:2个字节 int z; //整型:4个字节 }DATA; DATA a = {10}; int mian() { a.x = 5; a.y = 6; a.z = 15; printf("%d\n",a.x + a.y); return 0; }
分析:
初始化为10(后面的修改只改变了一个字节)
10 0000 1010
5 0000 0101
6 0000 0110
15 0000 1111
打印结果是30,因为初始化和修改共用体元素,都是单位覆盖。因而这里无论是4字节的a.x还是1字节的a.y都是15,打印的结果为30(共用体所占的字节是最大的元素,也就是这个结构体占4字节)。
4、枚举
4.1、存在理由
有的时候我们需要几种可能的值(我们也可以用define来获得,或者使用const类型的变量),或者我们需要这几个变量自动的那规律来变化(如何变化见下面),比如,我们的定义中是一周7天,或者我们需要12中颜色,我们就可以使用枚举。枚举是将变量的值一一列举出来,变量的值只限于列举出来的值的范围。4.2、定义方式
同样的枚举我们推荐用下面的定义方式typrdef enum week //枚举类型 { mon,tue,wed,thu,fri.sat,sun }WEEK; WEEK workday、weekday; //枚举变量其中week为枚举类型名,WEEK为枚举变量名,mon,tue,wed,thu,fri.sat,sun为枚举值表,workday、weekday为枚举变量,workday与weekday只能取sun...sat中的一个。
workday = mon; //正确
weekday = tue; //正确
workday = abc; //错误,枚举中没有abc
如果没有初始化(注意下面的写法是不规范的),那么
mon = 0
tue = 1
wed = 2
...
sun = 6
我们也可以初始化
mon = -1
那么
tue = 0
wed = 1
...
sun = 5
或者我们也可以初始化
mon = 0
tue = 0
那么
wed = 1
...
sun = 5
我们可以看到,从没有定义的那个元素开始逐次增加,本质上enum是整数型(如果是java, 则不是整数型,而是一个由编译器生成的特殊的类)。
4.3、注意事项
a.枚举值是常量,不能在程序中用赋值语句对它赋值,例如sun = 5; mon = 2; sun = mon;都是错误的。b.可以改变枚举值的默认值(上面的初始化就是这种方式),如:
enum week { mon = 3; tue,wed,thu,fri.sat,sun };那么mon等于3,tue等于4,以此类推。
4.4、事例代码
#include<stdio.h> //枚举 typrdef enum week //枚举类型 { sun = 2,mon,tue,wed,thu,fri.sat }WEEK; WEEK a,b,c;//枚举变量 enum bool { false,true }bl; int main() { a = sun; b = mon; c = ture; printf("%d, %d, %d",a, b, c); bl = ture; if(1 == bl) { printf("bl为真\n"); } return 0; }打印结果为:2,3,4bl为真。
5、结束语
结构体、共用体、枚举都是构造类型数据,我们从定义方式就可以看到他们的相似性。在结构体类型中的位段使用是值得我们注意的,如果用好了,会使我们在项目中节省很多必要的空间!【END150613】<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
版本:V1.1
时间:2015.09.19
作者:Alan
说明:修改部分错误和修改排版
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
版本:V1.0
时间:2015.06.13
作者:Alan
说明:完成文章。
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
相关文章推荐
- C++堆栈问题
- c++primer之函数(函数基础和参数传递)
- 值得推荐的C/C++框架和库
- VC++ MFC中如何将应用程序的配置信息保存到注册表中(二)
- C++指针探秘
- C语言
- 使用c++代替使用的c包!
- C语言格式化输出(整理1)
- Implement strStr() (C,C++,Java,Python)
- 黑马程序员———C语言———【strlen()和sizeof()的区别、排序、算法】
- VC++ MFC中如何将应用程序的配置信息保存到注册表中(一)
- Java与C++实现相同的MD5加密算法
- c++编译器对多态的实现原理总结
- C++之常量与指针
- (C++ 11) 关联容器
- c++中static总结
- c++ primer plus 第九章《编程题9.6.2》
- c++ primer plus 第八章《编程题8.8.7》
- 腾讯电面——C/C++基础之关键字
- c++ primer plus 第八章《编程题8.8.5》