由C语言位域(冒号)谈C语言的结构体、枚举、共用体

综述

今天看到一行代码

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
说明:完成文章。
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C语言中的共用体(Union)和位域(Bit-Field)是用来优化内存使用和灵活操作数据的工具。 共用体是一种特殊的数据类型,它允许不同的变量共享同一块内存空间。共用体中的成员变量共享同一内存,占用内存大小等于最大成员的大小。通过修改共用体的一个成员变量的值,可以影响到其他成员变量的值。共用体适用于在不同的数据类型之间进行转换或者存储占用内存大小不定的数据。 位域是一种特殊的结构体成员变量,可以指定成员变量占用的位数,从而实现对内存空间的灵活利用。位域的成员变量必须是整型数据类型,并且位域的大小不能超过该整型类型的大小。位域可以用于减小数据结构占用的内存大小,以及进行数据的位操作。 共用体位域结构体可以一起使用。通过在位域结构体中定义共用体成员变量,可以实现对内存的灵活使用和数据的高效操作。共用体可以用于存储不同类型的数据,而位域可以用于压缩数据的存储空间。这种结合使用的方式可以为我们的程序带来更加高效和节省内存的特点。 总结起来,C语言中的共用体位域结构体提供了一种优化内存使用和操作数据的方式。它们可以灵活地对内存空间进行利用,并且能够高效地操作数据。通过合理的使用共用体位域结构体,我们可以达到节省内存和提高程序执行效率的目的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值