The bit domain in C language is a complicated issue and involves many aspects. For the basic content of bit domain, refer to the following article: Understanding the bit domain in C Language
The analysis code is as follows:
#include "stdio.h" #include "memory.h" typedef struct _BitSeg1{ int a:4; int b:3; }BitSeg1; typedef struct _BitSeg2{ char a:4; char b:3; }BitSeg2; int main() { BitSeg1 ba1; ba1.a=1; ba1.b=2; printf("First time: a->%d\tb->%d\n",ba1.a,ba1.b); ba1.a=100; ba1.b=30; printf("Second time:a->%d\tb->%d\n",ba1.a,ba1.b); char str[]="0123"; memcpy(&ba1,str,sizeof(BitSeg1)); printf("Third time: a->%d\tb->%d\n",ba1.a,ba1.b); printf("sizeof BitSeg1: %d\n",sizeof(BitSeg1)); printf("sizeof BitSeg2: %d\n",sizeof(BitSeg2)); return 0; }
Output result:
After the-assignment: the value of A is 1 B and 2.
After the second Value assignment: the value of A is 4B and the value of-2.
After the second Value assignment: the value of A is 0 B and the value of 0 B is 3.
The number of bytes of bitseg1 is 4.
The number of bytes of bitseg2 is 1.
In the code, bigseg1 defines two int fields, which occupy only four and three spaces respectively. when values of A and B in bitseg1 are 1 and 2, the output results are as expected. when the second value is 100 and 30, the output result is 4 and-2. Why?
1. Assignment Problems
The above problem occurs because of the combined effect of the value assignment and bitfield. Although both A and B are of the int type, in the bigseg1 structure, they only have four and three digits as the actual valid digits. that is to say, the first 4 digits in bigseg1 are a, and the next 3 digits are B (there is no byte crossover problem here ). execute the ba1.a = 100 statement, where 100 of the binary code is: 01100100, the program only assigns the first four digits of the 100 binary number (represented in red) to, so a in BA1 is only 0100 (B), and the result is 4 of course. then, execute the b1. B = 30 statement. The binary code of 30 is 00011110. The same program only assigns the first three digits (note that B defines the valid digits as three digits) to B, in BA1, B is 110 (B), and the result is-2. Why? Well, we define B as an int type, that is, a signed integer. If you want to define it as an unsignedint, you must write unsignedint in this way, the second-digit of a signed integer is the sign bit, which is used to indicate positive and negative (1 indicates negative, 0 indicates positive). For B, the program uses the nth-bit (1) of B as the symbol bit, that is, B should be a negative number, while the latter is its value (10 (B )), note that the negative number in the computer is expressed in the form of a supplementary code. In this assignment, B is indeed 110 (it is a supplementary code, according to the "I. e. Anti-" rule, the result is-2 in decimal format. when a is assigned 0100 (B), the first-digit is 0, which is interpreted as a number. for example, if we use ba1. B = 7, what is the value of ba1. B? The binary value of 7 is 0111, and the first three digits are directly given to B. Because it is a negative number, the first three digits are read in the form of a supplementary code when reading the data, which is-1.
In short-sentence: Use a bit to understand a bit domain.
The next step is to use memcpy to copy the memory of BA1, so we should use the bit to consider the bit domain. The following is an analysis:
First, the value of sizeof (bitseg1) is 4 bytes. Remember that the problem will be explained in detail later.
Run memcpy (& BA1, STR, sizeof (bitseg1) to copy the content in the memory of the first four bytes in STR to ba1, let's take a look at the memory bit information of STR (represented in hexadecimal notation ):
0x0012ff74: 30 31 32 33
Where 0x0012ff74 indicates the starting position of the STR array address. hexadecimal values such as 30,31, 32,33 indicate '0', '1', '2', and '3' respectively ', of course they are acii values.
The memory bit information of BA1 after copy is as follows:
0x0012ff7c: 3031 32 33
Because BA1 also occupies 4 bytes of space, there will be no memory overflow. memcpy just copies the corresponding memory to ba1. bit information is similar to STR information.
Now, let's write the binary values of 30 (h): 00110000. A of BA1 occupies the first four places, and B occupies the next three places, A should be 0011 (B), that is, 3 in decimal format, B is 000 (B), that is, 0 in decimal format, but the output result is a = 0, B = 3, why? In fact, the processor defines that the first four bits of a byte refer to the four bits from right to left, instead of the four bits from left to right. Therefore, a should be 0000 (B ), B should be 011 (B ).
2. byte alignment
Return to the number of bytes left above, that is, the result of sizeof (bitseg1) is 4 bytes. it is reasonable to say that the valid bits of bitseg1 are 7 bits, but for the Fast Running of the program, an important means is to reduce the number of read/write times in the memory, therefore, the sample processor reads the data in the memory to the Register in multiples of bytes. Therefore, if the program alignment the data in bytes, the memory read/write time can be effectively reduced, what do you want to do with the 7-bit read-only memory of the processor? It would be better to-read eight digits.
There are rules for byte alignment. In a 32-bit system, the compiler performs byte alignment by type based on their bit width. In VC:
Char
The offset must be a multiple of sizeof (char), that is, 1.
Int
The offset must be a multiple of sizeof (INT), that is, 4.
Float
The offset must be a multiple of sizeof (float), that is, 4.
Long
The offset must be a multiple of sizeof (long), that is, 4.
Double
The offset must be sizeof (double) or 8