Start with the problem
# Include
Void main ()
{
Union
{
Struct
{
Unsigned short s1: 3;
Unsigned short s2: 3;
Unsigned short s3: 3;
} X;
Char c;
} V;
V. c = 100;
Printf ("% d/n", v. x. s3 );
}
A: 4 B: 0 C: 3 D: 6
The answer is.
But the answer I run in TURBO C is 1.
Is the running result different because of the turbo c version?
I used it in TURBO C V2.0. What is 4 or 1?
What is the result of running v. x. s1 and v. x. s2 in turbo c V2.0?
What does ":" In unsigned short s1: 3; mean?
-----------------------------
Bit Structure
The bitwise structure is a special structure. When you need to access Multiple Digits of one byte or word by bit, the bitwise structure is more convenient than the bitwise operator. The bit structure is defined as follows:
Struct bit structure name {
Data type variable name: integer constant;
Data type variable name: integer constant;
}-Bit structure variable;
Where: the data type must be int (unsigned or signed ). The integer constant must be a non-negative integer in the range of 0 ~ 15 indicates the number of binary bits, that is, the number of bits. The variable name is a selection item and can be left unspecified. This is required for arrangement.
For example, a single-digit structure is defined below.
Struct {
Unsigned incon: 8;
Unsigned txcolor: 4;
Unsigned bgcolor: 3;
Unsigned blink: 1;
} Ch;
The access of the bitwise structure member is the same as that of the structure member.
For example, to access the bgcolor member in the structure of the above sample bit, you can write it as follows:
Ch. bgcolor
Note:
1. The member in the bit structure can be defined as unsigned or signed. However, when the member length is 1, it is considered as the unsigned type. Because a single bit cannot have symbols.
2. The members in the bit structure cannot use arrays and pointers, but the bit structure variables can be arrays and pointers. If they are pointers, their member access methods are the same as the structure pointers.
3. The total length (number of digits) of the bit structure is the sum of the digits defined by each bit member and can exceed two bytes.
4. A structure member can be used with other structure members.
For example:
Struct info {
Char name [8];
Int age;
Struct addr address;
Float pay;
Unsigned state: 1;
Unsigned pay: 1;
} Workers ;'
The structure of the above example defines information about a slave. There are two bit structure members, each of which has only one bit. Therefore, only one byte is occupied, but two pieces of information are saved. The first byte indicates the state of the worker, the second digit indicates whether the salary has been paid. The bit structure can save storage space.
Answers to questions
The structure struct x has three members s1, s2, and s3 each member occupies 3 bits, and the structure is union with char c;
Char generally occupies one byte (8 bit, 100 binary value: 01100100, so the third bit after s1 (6, 7, 8 bit): 100, s2 is the middle three (3, 4, 4, 5 bit) is 100 s3 is 01, so printf ("% d/n", v. x. s3) is 1, and the other is 4. Currently, most systems place low bitwise in front, while the declaration of the structure's median field is generally to declare the high bitwise first.
100 binary is 001 100 100
The lowest position is the highest position.
001 ---- s3
100 ---- s2
100 ---- s1
So the result should be 1.
If it is declared as low, then:
001 ---- s1
100 ---- s2
100 ---- s3
Result 4
What does ":" In unsigned short s1: 3; mean?
It refers to the positioning segment. 3 indicates that s1 occupies 3bit.
Why is it 4?
Struct
{
Unsigned short s1: 3; // one byte. Although it is scheduled to be 3 bits, the storage space of the system is at least one byte.
Unsigned short s2: 3; // one byte
Unsigned short s3: 3; // one byte
} X;
In this way, the maximum member in union is three bytes, and the final result is to memory alignment (alignment is a multiple of 4). It is 4.
Bit domain:
When storing some information, it does not need to occupy a full byte, but only needs to occupy a few or one binary bit. For example, when storing a switch value, there are only two States: 0 and 1. Use one binary digit. To save storage space and simplify processing, the C language also provides a data structure called "bit domain" or "bit segment ". The so-called "bit field" refers to dividing the binary character in a byte into several different regions and showing the digits of each region. Each domain has a domain name, which allows operations by domain name in the program. In this way, several different objects can be represented by a byte binary field. 1. Definition of a bit field and description of a bit field variable the definition of a bit field is similar to that of a structure, in the form:
Struct bit domain structure name
{Bit domain list };
The format of the bit domain list is: type description Character Domain Name: Bit domain Length
For example:
Struct bs
{
Int a: 8;
Int B: 2;
Int c: 6;
};
The description of bitfield variables is the same as that of structure variables. You can first define and then describe, and define or directly describe these three methods. For example:
Struct bs
{
Int a: 8;
Int B: 2;
Int c: 6;
} Data;
It indicates that data is a bs variable, which occupies two bytes in total. Where a occupies 8 places, B occupies 2 places, and c occupies 6 places. The definitions of bit domains are described as follows:
1. A single-byte field must be stored in the same byte and cannot span two bytes (this limit seems to be limited to char type ). If the remaining space of one byte is insufficient to store another domain, it should be stored from the next unit. You can also intentionally start a domain from the next unit. For example:
Struct bs
{
Unsigned a: 4
Unsigned: 0/* airspace */
Unsigned B: 4/* stored from the next unit */
Unsigned c: 4
}
In the definition of this bit field, a occupies 4 bits in the first byte, And the last 4 bits enter 0 to indicate that it is not used. B starts from the second byte and occupies 4 bits, and c occupies 4 bits.
2. Because the bit field cannot span two bytes, the length of the bit field cannot exceed the length of one byte, that is, it cannot exceed 8-bit binary.
3. A bit domain can be a non-bit domain name. In this case, it is only used for filling or adjusting the position. An anonymous domain cannot be used. For example:
Struct k
{
Int a: 1
Int: 2/* The two digits cannot be used */
Int B: 3
Int c: 2
};
From the above analysis, we can see that the bit field is essentially a structure type, but its members are allocated by binary.
2. The use of bit domains is the same as that of structure members. The format is: Bit domain variable name • bit domain name can be output in various formats.
Main (){
Struct bs
{
Unsigned a: 1;
Unsigned B: 3;
Unsigned c: 4;
} Bit, * pbit;
Bit. a = 1;
Bit. B = 7; // Note: The value assignment of a bit field cannot exceed the maximum value that can be expressed by this field. For example, if B has only three bits, the maximum value that can be expressed is 7. If B is assigned 8, an error occurs.
Bit. c = 15;
Printf ("% d, % d, % d/n", bit. a, bit. B, bit. c );
Pbit = & bit;
Pbit-> a = 0;
Pbit-> B & = 3;
Pbit-> c = 1;
Printf ("% d, % d, % d/n", pbit-> a, pbit-> B, pbit-> c );
}
In the preceding example, the bit domain structure bs is defined. The three bit domains are a, B, and c. This section describes the bs type variable bit and the bs type pointer variable pbit. This indicates that pointers can also be used for bit fields.
The program's Lines 9, 10, and 11 assign values to the three single-digit domains. (It should be noted that the value assignment cannot exceed the promised range of the bit field) the program's 12th rows output the content of the three fields in integer format. Row 3 sends the bit address of the bit field variable to the pointer variable pbit. Row 14th re-assigns a value to bit field a as a pointer and assigns it to 0. Row 15th uses the compound bitwise operator "& =", which is equivalent to 7 in the original value of pbit-> B = pbit-> B & 3-bit Domain B, the bitwise AND operation result of 3 is 3 (111 & 011 = 011, And the decimal value is 3 ). Similarly, the compound bitwise operation "=" is used in Row 3 of the program, which is equivalent to pbit-> c = pbit-> c1, and the result is 15. The program output the values of the three fields in the pointer mode in Row 3.
Let's take a look at the following two struct definitions:
Struct foo2 {
Char a: 2;
Char B: 3;
Char c: 1;
};
Struct foo3 {
Char a: 2;
Char B: 3;
Char c: 7;
};
Let's print the size of the two struct. The result is:
Sizeof (struct foo2) = 1
Sizeof (struct foo3) = 2
Obviously we didn't expect it. If the two struct sizes should be 3 in accordance with the normal memory alignment rules, what is the problem? First of all, we can be certain through this phenomenon that the struct with a 'bit region' is not aligned according to each domain, but alignment is made by bundling some bit domain members together. Taking foo2 as an example, all the members of this struct are of the char type, and the total space occupied by the three bit fields is 6 bit <8 bit (1 byte ), in this case, the compiler will bind these three members together for alignment at the minimum space cost, which is why we get sizeof (struct foo2) = 1. Let's look at the structure foo3. Like foo2, the three member types are also char type, but the space occupied by the three member fields is 9 bit> 8 bit (1 byte ), here, the bitfield cannot span the basic type space of two members. In this case, the compiler binds the members a and B to align according to char, while c performs alignment separately based on char, in this way, there is actually a gap between B and c, but this is also the most space-saving method. Let's look at another struct definition:
Struct foo4 {
Char a: 2;
Char B: 3;
Int c: 1;
};
In foo4, although the space occupied by the three single-digit fields is 6 bit <8 bit (1 byte), the alignment coefficients of char and int are different and cannot be bundled together, isn't a and B bundled together aligned by char, and c aligned by int separately? We printed the sizeof (struct foo4) and found that the result is 8. That is to say, the compiler binds a, B, and c together and uses int as alignment. That is to say, when the size of a type is not enough, it will be aligned according to the largest type. This is aligned by int.
There are the following explanations on the Internet:
/*************************************** **********************************
C99 specifies that int, unsigned int, and bool can be bit domain types, but almost all compilers have extended this,
Other types are allowed.
The main purpose of bit domains is to compress storage. The general rules are as follows:
1) if the type of the adjacent bit field is the same and the sum of its bit width is smaller than the sizeof size of the type
Segments are stored next to the previous field until they cannot be accommodated;
2) If the field type of the adjacent bit field is the same, but the sum of its bit width is greater than the sizeof size of the type
Segment will start from the new storage unit, and its offset is an integer multiple of its type size. (The test shows that this segment is limited to char type, and integer data can be stored across domains)
3) if the types of adjacent bitfield fields are different, the implementations of each compiler are different.
Type, Dev-C ++ adopts the compression method;
4) do not compress fields that are interspersed with non-bit fields;
5) the total size of the entire struct is an integer multiple of the size of the widest basic type.
**************************************** ***********************************/
Struct s1
{
Int I: 8;
Int j: 4;
Int a: 3;
Double B;
};
Struct s2
{
Int I: 8;
Int j: 4;
Double B;
Int a: 3;
};
Printf ("sizeof (s1) = % d/n", sizeof (s1 ));
Printf ("sizeof (s2) = % d/n", sizeof (s2 ));
Result: 16, 24
In the first struct, I, j, and a occupy 15 digits, less than 8 bytes, aligned by double 8 bytes, 16 bytes in total
In the second struct, I and j occupy 12 digits, less than 8 bytes. They are aligned by 8 bytes. a is also aligned by 8 bytes, and double is 8 + 8 + 8 = 24 bytes.
Bit fields are defined as follows:
When storing some information, it does not need to occupy a full byte, but only needs to occupy a few or one binary bit. For example, when storing a switch value, there are only two States: 0 and 1. Use one binary digit. To save storage space and simplify processing, the C language also provides a data structure called "bit domain" or "bit segment ". The so-called "bit field" refers to dividing the binary character in a byte into several different regions and showing the digits of each region. Each domain has a domain name, which allows operations by domain name in the program. In this way, several different objects can be represented by a byte binary field. 1. Definition of a bit field and description of a bit field variable the definition of a bit field is similar to that of a structure, in the form:
Struct bit domain structure name
{Bit domain list };
The format of the bit domain list is: type description Character Domain Name: Bit domain Length
Bit fields are described as follows:
1. When the remaining space of one byte is insufficient to store another domain, it should be stored from the next unit. You can also intentionally enable a domain to start from the next unit, for example, using a domain name or a bit domain name without a bit.
2. The length of the bit field cannot exceed the length of the data type. For example, the int type can exceed 32-bit binary. Others say that the length cannot exceed 8 bits. I can implement the int: 32 bit domain length on my host (linux as4 system. Is it a bit domain that has been redefined?
3. A bit domain can be a non-bit domain name. In this case, it is only used for filling or adjusting the position. An anonymous domain cannot be used.
2. The use of a bit domain is the same as that of a structure member. The format is: Bit domain variable name-bit domain name.
Bit fields can be output in various formats.
For example:
1 # include <stdio. h>
2
3 int main ()
4 {
5 struct bs
6 {
7 char a: 1;
8 char B: 3;
9 char: 0;/* airspace */
10 char c: 4;
11 char: 6;/* bitwise domain name */
12 int e: 18;
13} _ attribute _ (packed);/* _ attribute _ (packed) must be added; otherwise, alignment will be different from expected results */
14
15 struct bs bit, * pbit;
16
17 printf ("size of char is % d/n", sizeof (char ));
18 printf ("size of int is % d/n", sizeof (int ));
19
20 printf ("size of bit is % d/n", sizeof (bit ));
21
22 return 0;
23}
The result 1 is as follows:
Size of char is 1
Size of int is 4
Size of bit is 4
If you change e: 18 in line 1 of the program to 19, the running result 2 is as follows:
Size of char is 1
Size of int is 4
Size of bit is 5
If you remove the _ attribute _ (packed) of the program's 13th rows, the running result 3 is as follows:
Size of char is 1
Size of int is 4
Size of bit is 8
Compare the running result 123 and we can see that:
1. The length of a bit field can be greater than 8. For details, see the data type. I tested each data type. The maximum length of each type is the length of its own type;
2. The role of airspace is invalid after _ attribute _ (packed) is added;
3. bits without _ attribute _ (packed) will align the data:
For example:
Struct bf
{
Char a: 5;
Int B: 27;
};
The number of bits in bf is 4. If the number of bits in a is changed to 6, the length of BITs in a and B is 32 longer than that in int. The int type is aligned according to the multiples of its own length, therefore, the number of bf bytes is changed to 8.
Similarly
Struct bf
{
Int B: 27;
Char a: 5;
}
The same conclusion exists.
If _ attribute _ (packed) is added, the system compresses the data without bf.