C语言之位域

C语言之位域

文章链接:http://blog.csdn.net/qq_16628781/article/details/72423976

知识点

  1. 位域的定义和使用示例;
  2. 位域的存储规则理解;
  3. 新名词记录{位域的存储规则}

C语言中的位域,给了我们对于字节的位进行操作。对于一些只需要1位或者几位就能存储的数据,就不必要去开辟更多的空间去存储,从而避免不必要的浪费。

要学习位域,我们需要掌握字节和位的关系,当然还有基本数据类型存储所需要的字节空间。

位域的定义

位域的定义用到的是strcut关键字,关于strcut关键字,可以看上一篇文章http://blog.csdn.net/qq_16628781/article/details/72419878,定义的格式如下:

struct
{
  type [member_name] : width ;
};

说明:

type = 数据类型;

member_name = 位域的名称;

width = 位域中位的数量。宽度必须小于或等于指定类型的位宽度。

下面是位域的定义和使用示例。

/**
 * 有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。
 * 例如在存放一个开关量时,只有 0 和 1 两种状态,用 1 位二进位即可。为了节省存储空间,并使处理简便,
 * C 语言又提供了一种数据结构,称为"位域"或"位段"。
 * 所谓"位域"是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。
 * 每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。
 * 例如:用1位来存放一个开关变量,只有开和关两个状态,0和1;
 * 或者,读取外部文件格式——可以读取非标准的文件格式。例如:9 位的整数。
 * 
 * struct bs{
    int a:8;
    int b:2;
    int c:6;
}data;
 * 说明:说明 data 为 bs 变量,共占两个字节。其中位域 a 占 8 位,位域 b 占 2 位,位域 c 占 6 位。
 * 空域:用来占位而已
 * 
 */
void weiyuTest()
{
    struct bs
    {
        unsigned a:1;
        unsigned  :1;
        unsigned b:2;
        unsigned c:4;
    } bit, *pbit;
    bit.a = 1;
    bit.b = 4;//给位域赋值(应注意赋值不能超过该位域的允许范围)b占3位,所以最大二进制为111=7
    //因为b只占2位,所以即使复制为7(111),最后只会存储两位
    //但是是低两位还是高两位呢?答案是底两位
    //例如我们传入6(110),结果打印出来的是2(10),而不是3(11)
    bit.c = 15;//二进制:1111=十进制:15
    printf("打印出各个位的数值:%d, %d, %d\n", bit.a, bit.b, bit.c);

    pbit = &bit;
    pbit -> a=0;//直接将a数值修改为0
    pbit -> b &= 3;//等价于pbit->b=pbit->b&3,b和3按位与运算
    pbit -> c |= 1;//等价于pbit->c=pbit->c|1,c和1按位或运算
    printf("转换之后各个位的数值;%d, %d, %d\n", pbit->a, pbit->b, pbit->c);
}

位域存储规则

存储规则如下:
1) 当相邻成员的类型相同时,如果它们的位宽之和小于类型的 sizeof 大小,那么后面的成员紧邻前一个成员存储,直到不能容纳为止;如果它们的位宽之和大于类型的 sizeof 大小,那么后面的成员将从新的存储单元开始,其偏移量为类型大小的整数倍。

即是说,如果一个位域的属性,在前面一个位域不够存储时,就会跳过前面属性的大小字节宽度,重新开始存储。此时这个位域属性是和前面的位域属性位置之间是有缝隙的。

eg:

struct bs{
        unsigned m: 6;
        unsigned n: 12;
        unsigned p: 4;
    };
    printf("%d\n", sizeof(struct bs));

m、n、p 的类型都是 unsigned int,sizeof 的结果为 4 个字节(Byte),也即 32 个位(Bit)。m、n、p 的位宽之和为 6+12+4 = 22,小于 32,所以它们会挨着存储,中间没有缝隙。

如果将成员 m 的位宽改为 22,那么输出结果将会是 8,因为 22+12 = 34,大于 32,n 会从新的位置开始存储,相对 m 的偏移量是 sizeof(unsigned int),也即 4 个字节。

如果再将成员 p 的位宽也改为 22,那么输出结果将会是 12,三个成员都不会挨着存储。

当一个位域没有名称,只有占用位域大小时,那么此位域不能够访问,如果没有存储,那么也不分配空间。


总结

位域可以很好的节省空间,也是比较难理解的一个知识点,主要是要对基本的数据类型所需存储大小熟悉,然后还要理解其存储的规则,才能够更好的理解位域。

以上知识点可能理解有误,以及有疏漏,望请不奢赐教。谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值