`
61party
  • 浏览: 1106735 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

C/C++ 位域(Bit Fields)

 
阅读更多

今天中午与同事讨论位域的问题,越讨论越迷糊,最终还是求救Google,找到一些文章,把比较好两篇的转载于下。


1. 原文:http://www.cs.cf.ac.uk/Dave/C/node13.html


We have seen how pointers give us control over low level memory operations.

Many programs (e.g.systems type applications) must actually operate at a low level where individual bytes must be operated on.

NOTE:The combination of pointers and bit-level operators makes C useful for many low level applications and can almost replace assembly code. (Only about 10 % of UNIX is assembly code the rest is C!!.)

Thebitwiseoperators of C a summarised in the following table:

Table:Bitwise operators
& AND
$/mid$ OR
$/wedge$ XOR
$/sim$ One's Compliment
$0 /rightarrow 1$
$1 /rightarrow 0$
<< Left shift
>> Right Shift


DO NOTconfuse & with &&: & is bitwise AND, &&logicalAND. Similarly for$/mid$and$/mid/mid$.

$/sim$is a unary operator -- it only operates on one argument to right of the operator.

The shift operators perform appropriate shift by operator on the right to the operator on the left. The right operatormustbe positive. The vacated bits are filled with zero (i.e.There isNOwrap around).

For example:x<< 2 shifts the bits inxby 2 places to the left.

So:

ifx= 00000010 (binary) or 2 (decimal)

then:

$x /gt/gt= 2 /Rightarrow x = 00000000$or 0 (decimal)

Also: ifx= 00000010 (binary) or 2 (decimal)

$x <<= 2 /Rightarrow x = 00001000$or 8 (decimal)

Therefore a shift left is equivalent to a multiplication by 2.

Similarly a shift right is equal to division by 2

NOTE: Shifting is much faster than actual multiplication (*) or division (/) by 2. So if you want fast multiplications or division by 2use shifts.

To illustrate many points of bitwise operators let us write a function,Bitcount, that counts bits set to 1 in an 8 bit number (unsigned char) passed as an argument to the function.

This function illustrates many C program points:

  • for loopnotused for simple counting operation
  • x$/gt/gt=1 /Rightarrow$x = x >> 1
  • for loop will repeatedly shift rightxuntilxbecomes 0
  • use expression evaluation ofx & 01to controlif
  • x & 01masksof 1st bit ofxif this is 1 thencount++

Bit Fieldsallow the packing of data in a structure. This is especially useful when memory or data storage is at a premium. Typical examples:

  • Packing several objects into a machine word.e.g.1 bit flags can be compacted -- Symbol tables in compilers.
  • Reading external file formats -- non-standard file formats could be read in.E.g.9 bit integers.

C lets us do this in a structure definition by putting :bit lengthafter the variable.i.e.


struct packed_struct {
		 unsigned int f1:1;
		 unsigned int f2:1;
		 unsigned int f3:1;
		 unsigned int f4:1;
		 unsigned int type:4;
		 unsigned int funny_int:9;
} pack;


Here thepacked_struct contains 6 members: Four 1 bitflagsf1..f3, a 4 bittypeand a 9 bitfunny_int.

C automatically packs the above bit fields as compactly as possible, provided that the maximum length of the field is less than or equal to the integer word length of the computer. If this is not the case then some compilers may allow memory overlap for the fields whilst other would store the next field in the next word (see comments on bit fiels portability below).

Access members as usual via:

pack.type = 7;

NOTE:

  • Onlynlower bits will be assigned to annbit number. So type cannot take values larger than 15 (4 bits long).
  • Bit fields arealwaysconverted to integer type for computation.
  • You are allowed to mix ``normal'' types with bit fields.
  • Theunsigneddefinition is important - ensures that no bits are used as a$/pm$flag.

Frequently device controllers (e.g.disk drives) and the operating system need to communicate at a low level. Device controllers contain severalregisterswhich may be packed together in one integer (Figure12.1).

Fig.12.1Example Disk Controller RegisterWe could define this register easily with bit fields:

struct DISK_REGISTER  {
     unsigned ready:1;
     unsigned error_occured:1;
     unsigned disk_spinning:1;
     unsigned write_protect:1;
     unsigned head_loaded:1;
     unsigned error_code:8;
     unsigned track:9;
     unsigned sector:5;
     unsigned command:5;
};

To access values stored at a particular memory address,DISK_REGISTER_MEMORYwe can assign a pointer of the above structure to access the memory via:

struct DISK_REGISTER *disk_reg = (struct DISK_REGISTER *) DISK_REGISTER_MEMORY;

The disk driver code to access this is now relatively straightforward:

/* Define sector and track to start read */

disk_reg->sector = new_sector;
disk_reg->track = new_track;
disk_reg->command = READ;

/* wait until operation done, ready will be true */

while ( ! disk_reg->ready ) ;

/* check for errors */

if (disk_reg->error_occured)
  { /* interrogate disk_reg->error_code for error type */
    switch (disk_reg->error_code)
    ......
  }

Bit fields are a convenient way to express many difficult operations. However, bit fields do suffer from a lack of portability between platforms:

  • integers may be signed or unsigned
  • Many compilers limit the maximum number of bits in the bit field to the size of anintegerwhich may be either 16-bit or 32-bit varieties.
  • Some bit field members are stored left to right others are stored right to left in memory.
  • If bit fields too large, next bit field may be stored consecutively in memory (overlapping the boundary between memory locations) or in the next word of memory.

If portability of code is a premium you can use bit shifting and masking to achieve the same results but not as easy to express or read. For example:

unsigned int  *disk_reg = (unsigned int *) DISK_REGISTER_MEMORY;

/* see if disk error occured */

disk_error_occured = (disk_reg & 0x40000000) >> 31;

Exercise 12507

Write a function that prints out an 8-bit (unsigned char) number in binary format.

Exercise 12514

Write a function setbits(x,p,n,y) that returns x with the n bits that begin at position p set to the rightmost n bits of an unsigned char variable y (leaving other bits unchanged).

E.g. ifx= 10101010 (170 decimal) andy= 10100111 (167 decimal) andn= 3 andp= 6 say then you need to strip off 3 bits of y (111) and put them in x at position 10xxx010 to get answer 10111010.

Your answer should print out the result in binary form (see Exercise12.1although input can be in decimal form.

Your output should be like this:

   x = 10101010 (binary)
   y = 10100111 (binary)
   setbits n = 3, p = 6 gives x = 10111010 (binary)

Exercise 12515

Write a function that inverts the bits of an unsigned char x and stores answer in y.

Your answer should print out the result in binary form (see Exercise12.1although input can be in decimal form.

Your output should be like this:

   x = 10101010 (binary)
   x inverted = 01010101 (binary)

Exercise 12516

Write a function that rotates (NOT shifts) to the right by n bit positions the bits of an unsigned char x.ie no bits are lost in this process.

Your answer should print out the result in binary form (see Exercise12.1although input can be in decimal form.

Your output should be like this:

   x = 10100111 (binary)
   x rotated by 3 = 11110100 (binary)

Note: All the functions developed should be as concise as possible


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-fieldmember-declaratorspecification follows:

declaratoropt  : constant-expression

Thedeclaratoris the name by which the member is accessed in the program. It must be an integral type (including enumerated types). Theconstant-expressionspecifies 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.

NoteAn unnamed bit field of width 0 forces alignment of the next bit field to the nexttypeboundary, wheretypeis 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 typeDateis shown in the following figure.

Memory Layout of Date Object

Note thatnYearis 8 bits long and would overflow the word boundary of the declared type,unsigned int. Therefore, it is begun at the beginning of a newunsigned 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 inFundamental Types.

分享到:
评论

相关推荐

    c c++位域研究总结!!!

    位域(Bit-fields)是 C 语言和 C++ 语言中都有的一个概念,但是位域有很多需要注意的问题。其中一个重要的问题是大端和小端字节序的问题。 大端和小端字节序是计算机科学中的一种约定,用于描述多字节数字在计算机...

    C/C++笔试题

    位域(bit fields)允许在结构体中定义具有固定位数的成员。这在某些应用场景下可以节省内存空间,如硬件接口编程。位域的使用需要特别小心,因为它们的行为可能依赖于特定的编译器和处理器架构。 #### 27. 字符串...

    C++ 旅程

    #### 一、C/C++中的位域(Bit Fields) **概念解释:** 位域(Bit Fields),也被称为位段,是C/C++中的一种特殊的数据结构,它允许在一个整数类型(通常是`unsigned int`)中定义一系列具有固定宽度的字段,每个...

    嵌入式CC++语言精华文章集锦

    - **位域(Bit Fields)**: 可以在一个整数类型中定义多个位作为单独的变量使用,节省内存空间。 **1.4 示例** 以下是一个示例,展示了如何使用结构体和联合体来实现一种通用的通信协议: ```c typedef struct { ...

    linux开发常用参考手册合集

    而“关于C、C++位域(Bit-fields)的看法.doc”则讨论了位字段这一C/C++中的特殊数据结构,解释了如何利用位字段节省存储空间和优化数据结构。 最后,“apue2e_src.rar”可能包含《Advanced Programming in the UNIX ...

    嵌入式C C++语言精华文章

    - **位域操作**:通过使用位域(`bit fields`),可以在单个`struct`成员中表示多个布尔值或枚举值,从而节省空间资源。 #### C++中extern "C"含义深层探索 **知识点概述**:`extern "C"`是C++中用于处理C和C++混合...

    c++编程常遇问题总结

    2. 位域型(Bit Fields): 位域是C++中一种节省存储空间的数据结构,允许我们定义结构体中的成员只占用指定的位数。定义位域的基本语法如下: ```cpp struct BitFieldStruct { 数据类型 成员名 : 长度; }; ``` ...

    华为内部教材:C++中级培训教程(PPT)

    类可以包含命名空间(namespace)、类名(class names)、成员变量(class members)、成员函数(member functions)、静态成员函数(static member functions)、联合体(union)、位域(C++ Bit Fields)、嵌套类(nested class ...

    C++查看数据二进制形式

    4. **位域(Bit Fields)**:C++支持在结构体中定义位域,这允许你直接操作单个比特。这对于查看和理解数据的二进制结构非常有帮助,尤其是在处理紧凑的数据格式时。 5. **内存映射文件(Memory-Mapped Files)**:...

    华为C++中级培训胶片ppt

    类名称、成员变量、成员函数(包括普通成员函数和静态成员函数)、联合体(Union)、位域(Bit Fields)、嵌套类声明、类型名在类作用域内的定义、多重继承、虚函数、抽象类以及控制类成员访问权限(private、...

    C++使用培训教材,工程使用

    - **位字段(C++ Bit Fields)**:允许在结构或类中定义位域,节省内存。 - **嵌套类声明(Nested Class Declarations)**:类内定义的类,可以增加封装性。 - **类型名称在类作用域(Type Names in Class Scope)**...

    bitwise_operation.rar_matlab例程_C++_

    此外,C++还提供了一些特殊的位操作,如位域(bit fields)和位掩码(bit masks),它们在处理结构体和定义状态标志时非常有用。 文件“bitwise_operation”很可能是一个Matlab或C++的源代码文件,展示了如何在实际...

    求字节运算符.zip

    5. **编译器优化与位域**:位字段(bit fields)允许在一个字节或多个字节中定义和操作结构体的各个部分,节省内存空间。编译器可能对位字段进行优化,但其行为可能因编译器和平台而异,需要谨慎使用。 6. **二进制...

    OllyICE,od

    OllyDbg 是一种具有可视化界面的 32 位汇编-分析调试器。它的特别之处在于可以在没有源...不仅如此,OllyDbg还能识别大量的常量符号名(如:窗口消息、错误代码、位域[bit fields]…)并能够解码为已知的函数调用。

    C 语言编程常见问题解答.chm

    10.3 位域(bit fields)是可移植的吗? 10.4 移位和乘以2这两种方式中哪一种更好? 10.5 什么是高位字节(high-order byte)和低位字节(low-order byte)? 10.6 16位和32位的数是怎样存储的? 第11章 调试 ...

Global site tag (gtag.js) - Google Analytics