文档章节

Effective C++: BitField

SHIHUAMarryMe
 SHIHUAMarryMe
发布于 2016/07/16 20:47
字数 1018
阅读 25
收藏 0

位域是指在信息存储时候并不需要一个完整的字节,只需要占用一个或几个二进制位。

例如:存放一个开关量的时候,只有0和1两种状态,用一位二进制位表示就行了。

所谓位域,就是把一个字节(8位)中的二进制位分为几个不同的区域,并说明几个区域的位数.

需要注意的是:

1,位域的类型必须是整型或枚举类型

2,一个位域字段必须小于等于一个字节(8位). 如果当前字节所剩下的空间不足以存储下一个位域字段指定的位域的时候,从下一个字节开始存储接着存储.我们也可以手动指出从下一个直接开始存储.

3,取地址操作符不能用到位域字段上。

4,位域字段不能是类的静态成员.

5,位域字段在内存中的位置是按照从低位到高位的顺序放置的(针对intel CPU也就是little-endian).

6,别的CPU可能是按照big-endian放置数据到位域字段中的。

7,(wiki)https://en.wikipedia.org/wiki/Endianness

 

#include <iostream>
#include <iostream>

//intel:  little-endian
class BitField { //BitField中的a,b,c,d,e表示位域字段.
private:
	unsigned int a : 4; //最低位  //  0<= a <= 15;
	unsigned int b : 3;           //  0<= b <= 7;
	unsigned int c : 1;           //  0<= c <=1;
	unsigned int d : 4;           //  0<= d <= 15;
	unsigned int e : 4; //最高位  //  0<= e <=15;

	unsigned int f : 2;         // 0<= f <=3;
	unsigned int : 0;           //这里指出即使当前字节没有存满,也会从下一个字节开始存储.
	unsigned int g : 8;        // 0<= g <=255


public:

	BitField();

	~BitField()=default;

	void setBit();

	void print()const noexcept;

};

BitField::BitField()
	/*:a(1)
	 b(2)
	 c(1)
	 d(3) //不能这么初始化.
	e(4) */
{
	//
}

void BitField::setBit()
{
	this->a = 1;
	this->b = 1;
	this->c = 1;
	this->d = 1;
	this->e = 1;

	this->f = 1;
	this->g = 1;
}

void BitField::print()const noexcept
{
	std::cout << this->a << " "
		<< this->b << " "
		<< this->c << " "
		<< this->d << " "
		<< this->e << " "
		<< this->f << " "
		<< this->g << std::endl;
}

int main()
{
	BitField f;
	f.setBit();
	f.print();

	return 0;
}

位域的内存对齐:

1,如果相邻位域字段的类型相同,且位宽之和的大小 小于该类型sizeof的大小,则后面的位域将紧邻前面位域名存储,直到该字节已经不能容纳为止.

2,如果相邻位域字段的类型相同,且位宽之和的大小 大于该类型的sizeof的大小,则后面的位域将开辟一个新的字节进行存储.

3,如果相邻的位域字段的类型不相同,是否采取压缩方式要看编译器了。

4,如果位域字段之间穿插着非位域的字段,则不采用压缩。

5,整个位域结构体的sizeof大小,为结构体内最宽类型成员的整数倍.

 

Demo 1:

//测试工具: vs2015, x64模式.
//intel:  little-endian

struct BF {
	unsigned char a1 : 5;
	unsigned char a2 : 5;
	unsigned char a3 : 5;
	unsigned char a4 : 5;
	unsigned char a5 : 5;
};

int main()
{

    //输出: 1(字节)
	std::cout << "unsigned char: " << sizeof(unsigned char) << std::endl;

    //输出: 4(字节)
	std::cout << "BF: " << sizeof(BF) << std::endl;
    //BF中的位域表面上是一共占用了25个二进制位,不够4个字节,但是又多于3个字节
    //这样一来编译器就会自动填充位,足够4个字节.
    

	return 0;
}

Demo 2:

//测试工具: vs2015, x86
//intel:  little-endian


struct BF {
	unsigned char a1 : 5;
	unsigned char a2 : 5;
	long int      a3 : 5; //注意这里的long int类型.
	unsigned int  a4 : 5;
	unsigned char a5 : 5;
};

int main()
{

    //输出: 1(字节)
	std::cout << "unsigned char: " << sizeof(unsigned char) << std::endl;

    //输出: 4(字节)
	std::cout << "long int: " << sizeof(long int) << std::endl;

    //输出: 12(字节)
	std::cout << "BF: " << sizeof(BF) << std::endl;
    //a1 和 a2只占了10位不够2个字节,但是a3是个long int 类型是4个字节
    //a1 和 a2就会补位到4个字节以便于和 a3对齐.到这里就4个字节了.
    //a3占了4个字节,到这里就8个字节了.
    //a4 和 a5占用了10位不够2个字节补位到与long int的位数相同也就是4个字节,到这里就占用了12个字节了.

	return 0;
}

 

© 著作权归作者所有

共有 人打赏支持
上一篇: Socket: 字节顺序.
下一篇: Algorithm: 红黑树
SHIHUAMarryMe
粉丝 13
博文 164
码字总数 138501
作品 0
武汉
程序员
私信 提问
GCC 8.3 发布,C/C++ 编译器

GCC 8.3 发布了,GCC 8.3 是 GCC 8 分支的 bug 修复版本,其中包含对 GCC 8.2 中的回归和严重 bug 的重要修复,自上一版本以来修复了超过 153 个错误。 GCC(GNU Compiler Collection,GNU编...

段段段落
02/27
0
0
C++各阶段学习书目

1. 入门 Lippman的《Essential C++》 顾名思义,这本书是很短小精悍的。通过这本书,可以对C++的最常用和重要的特性有全面的了解,并对C++的全貌有一个概念。虽然这远远不够,但就是这样的书...

晨曦之光
2012/04/24
301
1
001-EMC 深入解读-目录

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/q1007729991/article/details/82717008 除了刚毕业的应届生,从来没人敢说他精通 C++,Bjarne Stroustrup (C...

--Allen--
2018/09/15
0
0
C#转C++的一点分享

从C#转C++有段时间了,一直想分享点什么,但又不太好意思分享,毕竟自己做C++的时间不太长,最近感觉自己已能胜任现有工作,想分享的想法又强了点,前几天看到这样一篇博客《那些年·我们读过的专业...

爱情经纬线
2014/01/17
3.7K
10
学习C++的50条,谨以送给C++的粉丝们

1.把C++当成一门新的语言学习(和C没啥关系!真的);   2.看《Thinking In C++》,不要看《C++变成死相》(C++编程思想,翻译的非常差);   3.看《The C++ Programming Language》(这...

地瓜儿
2013/01/11
1K
7

没有更多内容

加载失败,请刷新页面

加载更多

AWS自动部署工具codedeploy的部署概述

1)在AWS lambda平台上部署: 三大部分:要部署的内容 --> 部署的配置 --> 更新的lambda函数版本 部署的流程:上传修订的应用程序-->创建一个应用程序-->指定部署组-->指定部署的配置-->指定...

守护-创造
31分钟前
2
0
好程序员教程分享Javascript设计模式

好程序员教程分享Javascript设计模式 方法一 对象字面量表示法   在对象字面量表示法中,一个对象被描述为一组包含在大括号中,以逗号分隔的 name/value 对。对象内的名称可以是字符串或标...

好程序员IT
37分钟前
3
0
fail-fast和fail-safe的介绍和区别

fail-fast和fail-safe 前言 前段时间公司招的实习生在使用迭代器遍历的时候,对集合内容进行了修改,从而抛出ConcurrentModificationException. 然后给他讲解之余也整理了这一篇文章. fail-fa...

群星纪元
39分钟前
3
0
控制反转 IOC

控制反转(Inversion of Control,缩写为IoC)面向对象设计原则,降低代码耦合度 依赖注入(Dependency Injection,简称DI) 依赖查找(Dependency Lookup):容器提供回调接口和上下文条件给...

SibylY
50分钟前
2
0
网络介绍:Kubernetes设计文档

模型和动机 Kubernetes从Docker默认的网络模型中独立出来形成一套自己的网络模型。该网络模型的目标是:每一个pod都拥有一个扁平化共享网络命名空间的IP,通过该IP,pod就能够跨网络与其它物...

xiangyunyan
51分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部