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

来源:互联网 发布:陈小鲁道歉 知乎 编辑:程序博客网 时间:2024/05/17 05:57
 
位域(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++程序设计
原创粉丝点击