Bit field

From Wikipedia, the free encyclopedia
  (Redirected from Bitfield)
Jump to navigation Jump to search

A bit field is a data structure that consists of one or more adjacent bits which have been allocated to hold a sequence of bits, stored so that any single bit or group of bits within the group can be set or inspected.[1][2] A bit field is most commonly used to represent integral types of known, fixed bit-width.

The meaning of the individual bits within the field is determined by the programmer; for example, the first bit in a bit field (located at the field's base address) is sometimes used to determine the state of a particular attribute associated with the bit field.[3]

Within CPUs and other logic devices, collections of bit fields called "flags" are commonly used to control or to indicate the outcome of particular operations.[4] Processors have a status register that is composed of flags. For example if the result of an addition cannot be represented in the destination an arithmetic overflow is set. The flags can be used to decide subsequent operations, such as conditional jump instructions. For example, a JE ... (Jump if Equal) instruction in the x86 assembly language will result in a jump if the Z (zero) flag was set by some previous operation.

A bit field is distinguished from a bit array in that the latter is used to store a large set of bits indexed by integers and is often wider than any integral type supported by the language.[citation needed] Bit fields, on the other hand, typically fit within a machine word,[3] and the denotation of bits is independent of their numerical index.[2]

Implementation[edit]

Bit fields can be used to reduce memory consumption when a program requires a number of integer variables which always will have low values. For example, in many systems storing an integer value requires two bytes (16-bits) of memory; sometimes the values to be stored actually need only one or two bits. Having a number of these tiny variables share a bit field allows efficient packaging of data in the memory.[5]

In C and C++, native implementation-defined bit fields can be created using unsigned int, signed int, or (in C99:) _Bool. In this case, the programmer can declare a structure for a bit field which labels and determines the width of several subfields.[6] Adjacently declared bit fields of the same type can then be packed by the compiler into a reduced number of words, compared with the memory used if each 'field' were to be declared separately.

For languages lacking native bitfields, or where the programmer wants control over the resulting bit representation, it is possible to manually manipulate bits within a larger word type. In this case, the programmer can set, test, and change the bits in the field using combinations of masking and bitwise operations.[7]

Examples[edit]

C programming language[edit]

Declaring a bit field in C and C++:

// opaque and show
#define YES 1
#define NO  0

// line styles
#define SOLID  1
#define DOTTED 2
#define DASHED 3

// primary colors
#define BLUE  0b100
#define GREEN 0b010
#define RED   0b001

// mixed colors
#define BLACK   0                    /* 000 */
#define YELLOW  (RED | GREEN)        /* 011 */
#define MAGENTA (RED | BLUE)         /* 101 */
#define CYAN    (GREEN | BLUE)       /* 110 */
#define WHITE   (RED | GREEN | BLUE) /* 111 */

const char* colors[8] = {"Black", "Red", "Green", "Yellow", "Blue", "Magenta", "Cyan", "White"};

// bit field box properties
struct BoxProps
{
  unsigned int  opaque       : 1;
  unsigned int  fill_color   : 3;
  unsigned int               : 4; // fill to 8 bits
  unsigned int  show_border  : 1;
  unsigned int  border_color : 3;
  unsigned int  border_style : 2;
  unsigned char              : 0; // fill to nearest byte (16 bits)
  unsigned char width        : 4, // Split a byte into 2 fields of 4 bits
                height       : 4;
};

[6]

The layout of bit fields in a C struct is implementation-defined. For behavior that remains predictable across compilers, it may be preferable to emulate bit fields with a primitive and bit operators:

/* Each of these preprocessor directives defines a single bit,
   corresponding to one button on the controller.  
   Button order matches that of the Nintendo Entertainment System. */
#define KEY_RIGHT  0b00000001
#define KEY_LEFT   0b00000010
#define KEY_DOWN   0b00000100
#define KEY_UP     0b00001000
#define KEY_START  0b00010000
#define KEY_SELECT 0b00100000
#define KEY_B      0b01000000
#define KEY_A      0b10000000

int gameControllerStatus = 0;

/* Sets the gameControllerStatus using OR */
void KeyPressed( int key ) { gameControllerStatus |= key; }

/* Clears the gameControllerStatus  using AND and ~ (binary NOT)*/
void KeyReleased( int key ) { gameControllerStatus &= ~key; }

/* Tests whether a bit is set using AND */
int IsPressed( int key ) { return gameControllerStatus & key; }

Processor status register[edit]

An example of bitfields status register is included in the 6502 processor. Each of the single bitfields describes information about the machine state:[8]

  • N Negative flag
  • V oVerflow flag
  • unused
  • B Break flag
  • D Decimal flag
  • I Interrupt-disable flag
  • Z Zero flag
  • C Carry flag

These bits do not need to manipulated as they are set by the processor as the result of an operation and are evaluated by explicitly defined branching instructions for example BVC (Branch on oVerflow Clear), BEQ (Branch Z = 0). The exception is the I flag for which were is an explicit SEI ( SEt Interrupt Disable) instruction.

Extracting bits from flag words[edit]

A subset of flags in a flag field may be extracted by ANDing with a mask. A large number of languages support the shift operator (<<) where 1 << n aligns a single bit to the nth position most also support the use of the AND operator (&) to isolate the value of one or more bits.

If the status-byte from a device is 0x67 and the 5th flag bit indicates data-ready. The mask-byte is . ANDing the status-byte 0x67 (0110 0111 in binary) with the mask-byte 0x20(0010 0000 in binary) evaluates to 0x20. This means the flag bit is set i.e the device has data-ready. If the flag-bit had not been set, this would have evaluated to 0 i.e. there is no data available from the device.

To check the nth bit from a variable v, perform the operation:

bool nth_is_set = (v & (1 << n)) != 0;
bool nth_is_set = (v >> n) & 1;

Changing bits in flag words[edit]

Writing, reading or toggling bits in flags can be done only using the OR, AND and NOT operations - operations which can be performed quickly in the processor. To set a bit, OR the status byte with a mask byte. Any bits set in the mask byte or the status byte will be set in the result.

To toggle a bit, XOR the status byte and the mask byte. This will set a bit if it is cleared or clear a bit if it is set.

See also[edit]

References[edit]

  1. ^ Penn Brumm; Don Brumm (August 1988). 80386 Assembly Language: A Complete Tutorial and Subroutine Library. McGraw-Hill School Education Group. p. 606. ISBN 978-0-8306-9047-3.
  2. ^ a b Steve Oualline (1997). Practical C Programming. "O'Reilly Media, Inc.". pp. 403–. ISBN 978-1-56592-306-5.
  3. ^ a b Michael A. Miller (January 1992). The 68000 Microprocessor Family: Architecture, Programming, and Applications. Merrill. p. 323. ISBN 978-0-02-381560-7.
  4. ^ Ian Griffiths; Matthew Adams; Jesse Liberty (30 July 2010). Programming C# 4.0: Building Windows, Web, and RIA Applications for the .NET 4.0 Framework. "O'Reilly Media, Inc.". pp. 81–. ISBN 978-1-4493-9972-6.
  5. ^ Tibet Mimar (1991). Programming and Designing with the 68000 Family: Including 68000, 68010/12, 68020, and the 68030. Prentice Hall. p. 275. ISBN 978-0-13-731498-0.
  6. ^ a b Prata, Stephen (2007). C primer plus (5th ed.). Indianapolis, Ind: Sams. ISBN 978-0-672-32696-7.
  7. ^ Mark E. Daggett (13 November 2013). Expert JavaScript. Apress. pp. 68–. ISBN 978-1-4302-6097-4.
  8. ^ InCider. W. Green. January 1986. p. 108.

External links[edit]