1. Huge role of struct
In the face of a person's large C/C ++ program, we can evaluate the programming experience of the author simply by looking at the usage of struct. Because a large C/C ++ program is bound to involve some (or even a large number) structure for data combination, these structures can combine the original meaning of a whole of data. To some extent, whether or not struct will be used, and how to use struct is a sign that a developer has rich development experience.
In the C/C ++ programming of network protocols, communication control, and embedded systems, what we often want to transmit is not a simple byte stream (char array ), it is a combination of multiple types of data, in the form of a struct.
Experienced developers often store all the content to be transmitted in a char array in sequence, and transmit network packets and other information through pointer offset. This programming method is complex and error-prone. Once the control mode and communication protocol change, the program must be modified in great detail.
An experienced developer uses struct flexibly. For example, assume that three packets need to be transmitted in the network or control protocol, in the format of packetA, packetB, and packetC:
Struct structA
{
Int;
Char B;
};
Struct structB
{
Char;
Short B;
};
Struct structC
{
Int;
Char B;
Float c;
}
An excellent program designer designed the message to be transmitted in this way:
Struct CommuPacket
{
Int iPacketType; // Message Type flag
Union // one of the three messages is sent each time.
{
Struct structA packetA;
Struct structB packetB;
Struct structC packetC;
}
};
During packet transmission, the entire struct CommuPacket is directly transmitted.
Assume that the original form of the sending function is as follows:
// PSendData: the first address of the byte stream to be sent. iLen: The length to be sent.
Send (char * pSendData, unsigned int iLen );
The sender can directly call sendCommuPacket, an instance of struct CommuPacket, as follows:
Send (char *) & sendCommuPacket, sizeof (CommuPacket ));
Assume that the original form of the receiving function is as follows:
// PRecvData: the first address of the byte stream to be sent. iLen: The length to be received.
// Return value: the actual number of bytes received
Unsigned int Recv (char * pRecvData, unsigned int iLen );
The receiver can directly make the following calls to save the received data to a recvCommuPacket instance in struct CommuPacket:
Recv (char *) & recvCommuPacket, sizeof (CommuPacket ));
Then determine the Message Type for corresponding processing:
Switch (recvCommuPacket. iPacketType)
{
Case PACKET_A:
... // Class A Message Processing
Break;
Case PACKET_ B:
... // Class B Message Processing
Break;
Case PACKET_C:
... // Class C Message Processing
Break;
}
The most noteworthy of the above procedures is
Send (char *) & sendCommuPacket, sizeof (CommuPacket ));
Recv (char *) & recvCommuPacket, sizeof (CommuPacket ));
Forced type conversion in: (char *) & sendCommuPacket, (char *) & recvCommuPacket, get the address first, and then convert it to the char type pointer, so that you can directly use the function for processing byte streams.
Using this forced type conversion, we can also facilitate programming. For example, to initialize the memory of sendCommuPacket to 0, we can call the standard library function memset () as follows ():
Memset (char *) & sendCommuPacket, 0, sizeof (CommuPacket ));
2. struct member alignment
Companies such as Intel and Microsoft once had a similar interview question:
1. # include <iostream. h>
2. # pragma pack (8)
3. struct example1
4 .{
5. short;
6. long B;
7 .};
8. struct example2
9 .{
10. char c;
11. example1 struct1;
12. short e;
13 .};
14. # pragma pack ()
15. int main (int argc, char * argv [])
16 .{
17. example2 struct2;
18. cout <sizeof (example1) <endl;
19. cout <sizeof (example2) <endl;
20. cout <(unsigned int) (& struct2.struct1)-(unsigned int) (& struct2)
<Endl;
21. return 0;
22 .}
What is the input result of the program?
The answer is:
8
16
4
Do not understand? Still do not understand? Here is one by one:
2.1 Nature
Struct is a composite data type. Its components can be both basic data types (such as int, long, float, and so on) variables, it can also be a data unit of some composite data types (such as array, struct, union, etc. For struct, the compiler automatically alignment member variables to improve the computing efficiency. By default, the compiler allocates space for each member of the struct according to its natural (natural alignment) condition. Each member is stored in the memory in the declared order. The address of the first member is the same as that of the entire structure.
Natural alignment (natural alignment) is the default alignment, which refers to alignment Based on the largest member of the struct.
For example:
Struct naturalalign
{
Char;
Short B;
Char c;
};
In the above struct, short is the largest in size and the length is 2 bytes. Therefore, char members a and c in the struct are aligned in units of 2. sizeof (naturalalign) the result is 6;
If changed:
Struct naturalalign
{
Char;
Int B;
Char c;
};
The result is obviously 12.
2.2 specify the peer
Generally, you can use the following method to change the default peer condition:
· Using Pseudo commands # pragma pack (n), the compiler will be aligned according to n Bytes;
· Use the pseudo command # pragma pack () to cancel the custom byte alignment.
Note: If the value of n specified in # pragma pack (n) is greater than the size of the largest member in the structure, the structure does not take effect, and the structure is still bounded by the member with the largest size.
For example:
# Pragma pack (n)
Struct naturalalign
{
Char;
Int B;
Char c;
};
# Pragma pack ()
When n is 4, 8, or 16, the alignment is the same, and the sizeof (naturalign) result is 12. When n is 2, it plays a role, making sizeof (naturalalign) Result 8.
In the VC ++ 6.0 compiler, we can specify its peer mode (see figure 1), and select projetct> setting> C/C ++ menu in sequence, specify the peer mode in struct member alignment.
Figure 1: specifying the peer mode in VC ++ 6.0
In addition, through _ attribute (aligned (n), the struct member can be aligned on the n-byte boundary, but it is rarely used, therefore, we will not explain it in detail.
2.3 answers to interview questions
So far, we can answer Intel and Microsoft interview questions comprehensively.
Line 1 in the Program # pragma pack (8) although the ing is specified as 8, since the maximum size of members in struct example1 is 4 (long variable size is 4 ), therefore, struct example1 is still bounded by 4 bytes, and the size of struct example1 is 8, that is, the output result of 18th rows;
Struct example2 contains struct example1. the maximum size of simple data members contained in struct example1 is 2 (short variable e), but it contains struct example1, in struct example1, the maximum member size is 4, and struct example2 should also be bounded by 4. # The peer bound in pragma pack (8) does not work for struct example2 either, therefore, the output result of 19 rows is 16;
Because the members in struct example2 are 4-aligned, the char variable c should be followed by three null values, and the latter is the memory space of the member struct1, the output result of 20 rows is 4.
3. deep differences between struct and C ++
In C ++, struct has the "class" function. The difference between struct and the keyword class is that the default access permission for member variables and functions in struct is public, while the class is private.
For example, define the struct class and class:
Struct structA
{
Char;
...
}
Class classB
{
Char;
...
}
Then:
Struct A;
A. a = a; // access the public member, valid
ClassB B;
B. a = a; // access the private member, invalid
Many documents have written here that all the differences between struct and class in C ++ have been given. In fact, it is not true. Note that:
Struct in C ++ maintains full compatibility with struct in C (which complies with the original intention of C ++-"a better c"). Therefore, the following operations are legal:
// Define struct
Struct structA
{
Char;
Char B;
Int c;
};
StructA a = {a, a, 1}; // assign the initial value directly when defining
That is, struct can assign an initial value to the member variable {} directly during definition, while the class cannot, the author emphasizes this point in the classic bibliography thinking C ++ 2nd edition.
4. Precautions for struct Programming
Take a look at the following program:
1. # include <iostream. h>
2. struct structA
3 .{
4. int iMember;
5. char * cMember;
6 .};
7. int main (int argc, char * argv [])
8 .{
9. structA instant1, instant2;
10. char c =;
11. instant1.iMember =