C++ Bit Fields

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

See Also

Classes, Structures, and Unions

Classes and structures can contain members that occupy less storage than an integral type. These members are specified as bit fields. The syntax for bit-field member-declarator specification follows:

declarator opt   : constant-expression

The declarator is the name by which the member is accessed in the program. It must be an integral type (including enumerated types). The constant-expression specifies the number of bits the member occupies in the structure. Anonymous bit fields — that is, bit-field members with no identifier — can be used for padding.

Note    An unnamed bit field of width 0 forces alignment of the next bit field to the next type boundary, where type is the type of the member.

The following example declares a structure that contains bit fields:

// bit_fields1.cpp

struct Date

{

   unsigned nWeekDay  : 3;    // 0..7   (3 bits)

   unsigned nMonthDay : 6;    // 0..31  (6 bits)

   unsigned nMonth    : 5;    // 0..12  (5 bits)

   unsigned nYear     : 8;    // 0..100 (8 bits)

};

 

int main()

{

}

The conceptual memory layout of an object of type Date is shown in the following figure.

Memory Layout of Date Object

 

Note that nYear is 8 bits long and would overflow the word boundary of the declared type, unsigned int . Therefore, it is begun at the beginning of a new unsigned int . It is not necessary that all bit fields fit in one object of the underlying type; new units of storage are allocated, according to the number of bits requested in the declaration.

Microsoft Specific

The ordering of data declared as bit fields is from low to high bit, as shown in the figure above.

END Microsoft Specific

If the declaration of a structure includes an unnamed field of length 0, as shown in the following example,

// bit_fields2.cpp

struct Date

{

   unsigned nWeekDay  : 3;    // 0..7   (3 bits)

   unsigned nMonthDay : 6;    // 0..31  (6 bits)

   unsigned           : 0;    // Force alignment to next boundary.

   unsigned nMonth    : 5;    // 0..12  (5 bits)

   unsigned nYear     : 8;    // 0..100 (8 bits)

};

 

int main()

{

}

the memory layout is as shown in the following figure.

Layout of Date Object with Zero-Length Bit Field

The underlying type of a bit field must be an integral type, as described in Fundamental Types .

© Microsoft Corporation. All rights reserved.

以上摘自 MSDN Library for Visual Studio .Net 2003

 

 

位域( bit-field ):一种压缩空间的成员

这两天在看公司里关于 MPEG-2 流结构的代码,发现 师傅 写关于那些结构的代码的时候出现了如下类似的代码(这里的载自 C++ Prime )。

typedef unsigned int Bit;

class File {

public:

Bit mode           : 2 ;

Bit modified      : 1 ;

Bit prot_owner : 3 ;

Bit prot_group   : 3 ;

Bit prot_world   : 3 ;

// ...

};

    刚开始觉得有些怪怪的,虽然从结构中大概知道是什么意思,但是具体的却不怎么知道。可能是 C/C++ 的知识有些遗漏,实践比较少吧。于是查找资料,得知:

这是一种被称为位域 bit-field 特 殊的类数据成员。它可以被声明用来存放特定数目的位,位域必须是有序数据类型,它可以有符号也可以无符号例如:

class File {

// ...

unsigned int modified : 1; // 位域 (bit-field)

};

位域标识符后面跟有一个冒号,然后是一个常量表达式指定位数,例如, modified 是一个只有一位构成的位域。

在类体中相邻定义的位域,如果可能的话,它们会被放在同一个整数的连续位中,并以此提供空间压缩。例如,在下列 声明中, 5 个 位域被存储在单个 unsigned int 中,它首先与位域 mode 相关联

typedef unsigned int Bit;

class File {

public:

Bit mode: 2;

Bit modified: 1;

Bit prot_owner: 3;

Bit prot_group: 3;

Bit prot_world: 3;

// ...

};

对于位域的访问方式与其他类数据成员相同。例如,类的私有位域只能在类的成员函数和友元中被访问:

void File::write()

{

modified = 1;

// ...

}

void File::close()

{

if ( modified )

// ... 内容从略

}

下面的例子说明了怎 样使用大于 1 位 的位域。

enum { READ = 01, WRITE = 02 }; // 文件模式

int main() {

File myFile;

myFile.mode |= READ;

if ( myFile.mode & READ )

cout << "myFile.mode is set to READ/n";

}

通常情况下我们会定义一组 inline 成员函数,来测试每个位域成员的值。例如,类 File 可以定义成员 isRead() isWrite()

inline int File::isRead() { return mode & READ; }

inline int File::isWrite() { return mode & WRITE; }

 

if ( myFile.isRead() ) /* ... */

有了这些成员函数,现在位域可以被声明为类 File 的私有成员。

由于取地址操作符 & 不能被应用在位域上,所以也没有能 指向类的位域的指针位域也不能是类的静态成员

C++ 标准库提供了一个 bitset 类模板,它可以辅助操纵位的集合。在可能的情况下,应尽可能 使用它来取代位域。要是你对标准库还没没有什么概念,那你只好用这个了。

之前所说的位域都在类中体现的,那么结构体中呢?

定义位域结构的格式为:

    struct < 结构体类型名 >

     {

< 类型 1> < 位域名 1>:< 位数 >;

        < 类型 2> < 位域名 2>:< 位数 >;

        …

        < 类型 n> < 位域名 n>:< 位数 >;

     };

其中, < 类型 > 必须是 unsigned signed int 类型; < 位域名 > 是用户命名的标识符;

< 位数 > 表示该位域所占的二进制位数,是一个正整数。

    例如:

    struct bit8253

     {

      unsigned bcd:1;

      unsigned m:3;

      unsigned rl:2;

      unsigned sc:2;

      unsigned black:24;

     };

    说明:

    1 )对于各个位域必须依次从低到高进行定义;

    2 )位数为 1 的位域只能用 unsigned 类型;

    3 )每个位域的位数应小于计算机的字长,但各个位域的总长度则可以大于一 个字长,超过字长的部分放在下一个存储单元中。

对于这些说明只是针对结构体的呢?还是对于类中的位域一样有适用,还是部分适用呢?有待考证,但是这些都是比较 细节的东西了,编程中如果遇到,要是出了错误往这里想就好了。正如福尔摩斯大致所说: 除去那些不可能的,就是这些可能的了。

       了,我个人觉得位域还是比较有用的。比如在 码流结构 某些传输协议结构 中都有一些字段小于计算机的字长,但是他们某几段的总长度 又是比如 4 个 字 节。还有就是有人提出现在的内存都是那么大的了,没有必要 那么 抠 门 了 吧。但是,有人说过: 程 序员是为程序服务的,而机器不是。 这句话的意思显然了 吧。好了,关于位域就说到此了,希望能使你也能有所收获。

 

 

参考: C++Prime

           潭浩强: C++ 程序设计

以上摘自: http://blog.csdn.net/Adrian_Bu/archive/2006/08/03/1015318.aspx

wave 注:

( 此文内容基本翻译自 C++ Primer)

或者另外参见《 C++ Primer

《Imperfect C++中文版》——1.2 编译期契约:约束 本节书摘来自异步社区出版社《Imperfect C++中文版》一书中的第1章,第1.2节,作者: 【美】Matthew Wilson,更多章节内容可以访问云栖社区“异步社区”公众号查看。 1.2 编译期契约:约束 Imperfect C++中文版本章讲述编译期强制,通常它也被称为“约束(constraints)”。遗憾的是,C++并不直接支持约束。 Im... 阅读详情

相关推荐

位域 (网络见的.)

位域有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的

1451

C++生僻知识点——位字段(bit field)

位字段允许用户修改结构体中某个成员变量的特定位数,这种实现对于一般的程序似乎没有什么价值,但是对于硬件工程师来说,可以创建与特定硬件设备上的寄存器对应的数据结构。 同时,如果空间宝贵,数据类型存储数据有空间冗余,也可以使用位字段优化。 比如,C++中,bool类型仅存储0或1,但是与char类型一样占1个字节,浪费空间。考虑到操作系统自动对齐,如果使用位字段,相同的空间可以存储8个bool变量。 #include <iostream> #include <string> using

HYPan 1617

大雄的位域学习笔记

写在前面, 这是我读其他人的文章写下的笔记,第一版和原文几乎相同。侵联删, 后续我也会加入我在其他地方学到的相关的东西,也就是说,这是我自己的一个学习笔记。 当然了,既然是学习笔记,除了链接原文外肯定还有其他内容 原文链接:https://github.com/Light-City/CPlusPlusThings/tree/master/basic_content/bit 1、位域是什么? 1)定义 “ 位域 “ 或 “ 位段 “(Bit field)为一种数据结构,可以把数据以位的形式紧凑的储存,并允许程

Nobita_Nobi的博客 573

关于Bit Fields的两篇资料

C++ Language Reference   C++ Bit Fields

Wave的专栏 2381

C/C++位域(Bit-fields)

前言很早想说说这个问题了,经常也会有很多公司拿位域出来考人,呵呵要真的想弄清楚还要一点点的分析。这里先看看网宿的一道笔试题目://假设硬件平台是intel x86(little endian) typedef unsigned int uint32_t; void inet_ntoa(uint32_t in) { char b[18];

You are what you output 2274

c++ 位域(bit-fields)和 volatile 关键字

/ 结构体中的位域// 占用 1 位// 占用 3 位// 未命名位域,填充 4 位// 占用 8 位// 二进制值:1// 二进制值:101// 二进制值:01111111// 输出:4 bytes(假设 unsigned int 为 4 字节)// 错误:无法取位域成员的地址return 0;

曾经也曾立志 1214

C++ Bit fields

【代码】C++ Bit fields

每一个不曾起舞的日子,都是对人生的辜负。 352

C/C++位域(Bit-fields)之我见

原文 : http://blog.csdn.net/ztz0223/archive/2008/12/24/3599016.aspx # //假设硬件平台是intel x86(little endian) # # typedef unsigned int uint32_t; # void inet_ntoa(uint32_t in) # { ...

ishuang的专栏 141

C/C++ 字节序/位域(Bit-fields)之我见

前言很早想说说这个问题了,经常也会有很多公司拿位域出来考人,呵呵要真的想弄清楚还要一点点的分析。这里先看看网宿的一道笔试题目,这道题目我之前是复制网上的,结果不对,修改了一下,可以正确运行了,谢谢(imafish_i )提醒://假设硬件平台是intel x86(little endian) typedef unsigned int uint32_t; void inet_ntoa(uin

大周辞寒的专栏 2万+

【转】 C/C++位域(Bit-fields)之我见

 前言很早想说说这个问题了,经常也会有很多公司拿位域出来考人,呵呵要真的想弄清楚还要一点点的分析。这里先看看网宿的一道笔试题目,这道题目我之前是复制网上的,结果不对,修改了一下,可以正确运行了,谢谢(imafish_i )提醒://假设硬件平台是intel x86(little endian) typedef unsigned int uint32_t; void inet

lupin8888的专栏 926

c++ 位域(Bit Fields)

C++ Bit Fields Visual Studio 2012 其他版本 此主题尚未评级 - 评价此主题 Classes and structures can contain members that occupy less storage than an integral type. These me

swazer_z 620

C++ 位域(Bit Fields)

位域 有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的...

yaowang107的博客 3090

c++ 位域(Bit Fields)

有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位

LiuLong917的专栏 481
上一篇: linux 2.4 和2.6 内核区别
下一篇: 在Linux磁盘管理中限制用户空间
flymarco
博客等级 码龄20年 4粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值