C/C ++ provides an embedded feature to access the bitwise domain in bytes. Bit fields are useful because:
1) if the storage space is limited, multiple Boolean variables (true/false) can be stored in one byte ).
2) some devices transmit status information encoded as one byte.
3) Some encryption programs need to access bits in bytes.
C/C ++ uses structure-based methods to access bits. In fact, a bit field is a special type of structure member. It defines the length of a field in units of bit.
The general format of bit domain definition is as follows (C ++ style)
Struct-type-name
{
Type name1: length;
Type name2: length;
....
Type Namen: length;
} Variable_list;
Type is the type of a bit field. It should be an integer type such as _ bool (c99), Char, Int, and enumeration.
Length is the length of a bit field. It must be a non-negative integer constant or expression, and the value cannot be greater than the Bit Width corresponding to type. For example, char bit_field: 9 cannot be compiled.
In addition, the bit field with a length of 1 should be declared as unsigned, because a single bit cannot be signed.
Assigning values to bit fields is the same as assigning values to any type of structure members.
Bit fields do not have to be named, so that useless bit can be skipped to facilitate the use of desired bit.
The usage of bitfield variables has some restrictions:
1). Do not use the address of the bitfield variable.
2). bitfield variables cannot constitute arrays.
3) bitfield variables cannot be declared as static.
In particular, the use of bit domains is related to the machine's bit order.
For the differences and relationships between bit and byte orders, refer to the following:
Http://www.linuxjournal.com/article/6788
I have a translation version of this document on my blog. However, I am an amateur translator and do not make any commitments or guarantees on the translation content and quality.
Http://blog.csdn.net/lovekatherine/archive/2007/04/14/1564731.aspx
Next, we will focus on analyzing the relationship between bit domains and bit orders. The following small program is used as an example.
# Include <stdio. h>
# Include <string. h>
Typedef struct _ bitdomain
...{
Unsigned char A: 3;
Unsigned char B: 5;
} X;
Void display (char DST)
...{
Int I;
Unsigned int M = 128;
While (m)
...{
Printf ("% u", (unsigned char) DST/M );
DST % = m;
M/= 2;
}
Printf (",");
}
Int main ()
...{
X;
Memset (& X, 0x0, sizeof (x ));
* (Unsigned char *) & X = 0xb4;
Printf ("sizf of struct X: % d", sizeof (x ));
Int size = sizeof (X );
Char * Ch = (char *) & X;
Int I;
For (I = 0; I <size; I ++)
...{
Display (CH [I]);
}
Printf ("");
Printf ("X. A = % u", (unsigned char) X. );
Printf ("x. B = % u", (unsigned char) X. B );
/**/
Return 1;
}
Running Environment: i386 + ubuntu7.04 + gcc4.1.2
The output result of the program is:
* = 10110100,
X. A = 100 (0x44 ),
X. B = 10110 (0xb ),
The output of the analysis program is as follows:
First, the size of structure X is 1 byte.
Secondly, in the i386 architecture, the byte order and bit order are small ends, that is, the high address where the high byte (BIT) is stored in the memory.
We can see that the layout of X = 0xb4 in the memory is as follows:
Bit 7 6 5 4 3 2 1 0
Value 1 0 1 1 0 1 0 0
According to Kevin's theorem #2: "In a structure in C that contains a bit domain, if A is defined before B, the memory occupied by bit Domain A is always lower than that occupied by B."
We can see that X. A corresponds to 2 ~ Digits 0, x. B corresponding to digits 7 ~ According to the relationship between high addresses and high addresses
X. A = 100, X. B = 10110
Make local modifications to the above program to see what happens when the length of the in-place domain exceeds 8 (1 byte.
# Include <stdio. h>
# Include <string. h>
Typedef struct _ bitdomain
...{
Unsigned short Y: 12;
Unsigned short Z: 4;
} X;
Void display (char DST)
...{
Int I;
Unsigned int M = 128;
While (m)
...{
Printf ("% u", (unsigned char) DST/M );
DST % = m;
M/= 2;
}
Printf (",");
}
Int main ()
...{
X;
Memset (& X, 0x0, sizeof (x ));
* (Unsigned short *) & X = 0x32b4;
Printf ("sizf of struct X: % d", sizeof (x ));
Int size = sizeof (X );
Char * Ch = (char *) & X;
Int I;
For (I = 0; I <size; I ++)
...{
Display (CH [I]);
}
Printf ("");
Printf ("x. y = % x", (unsigned short) x. y );
Printf ("x. z = % x", (unsigned short) X. z );
Return 1;
}
The output result of the program is:
X = (0x32b4)
X. y = 0x2b4
X. z = 0x3
(Y and Z are defined as unsigned short Y: 12 and unsigned short Z: 4 respectively)
Like the memory, it still starts with the memory layout of X.
(Not to mention the general nature. Assume that the address of X is 0x1000)
ADDR 0x1000 0x1001
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
Vlaue 1 0 1 0 1 0 0 0 0 1 0 0 0 0 1 0
Similarly, according to Kevin's theorem #2, we can see that x. y corresponds to the 8bit of 0x1000 and 0 ~ 0 of 0x1001 ~ Bits 3 and X. Z correspond to bits 4 ~ at the address 0x1001 ~ Bits 7.
Therefore, according to the relationship between the high address and the high byte, we can conclude that listen x. y = 001010110100 = 0x2b4, X. z = 0011 = 0x3