[C] structure alignment

xiaoxiao2021-03-06  104

http://community.9cbs.net/expert/faq/faq_index.asp?id=182474 In the structure, each member of the compiler is the structure allocates space according to its natural alignment; each member is in accordance with them The order in which the declaration is stored in memory, the address of the first member is the same as the address of the entire structure. By default, the C compiler allocates a space for each variable or a data unit, for example, the following structures, the following structures, Struct Test {char X1; Short X2; Float X3; Char X4; }; The first member X1 of the structure, its offset address is 0, occupying the first byte. The second member X2 is a short type, and its start address must be 2 bytes of theoretical, so the compiler fills an empty byte between X2 and X1. The third member X3 and the fourth member X4 of the structure are just on its natural parallel address, and there is no additional padding bytes in front of them. In the TEST structure, the member X3 requires 4-byte alignment, which is the maximum parallel unit required in all members of the structure, so the natural relationship condition of the TEST structure is 4 bytes, and the compiler is filled in the member X4. 3 Empty byte. The entire structure is occupied by 12 bytes. Changing the default allocation strategy for the C compiler can change the default association conditions by the following two methods: • Use pseudo-instructions #pragma pack ([n]) • Use the command line parameter #pragma Pack when compiling ([N]) The directive allows you to select a relationship policy taken by the compiler to the data allocation space: For example, after using the #pragma pack (1) pseudo instruction, the spatial allocation of each member of the TEST structure is in accordance with one word. The section is aligned with #pragma pack (push) // Save Alignment #pragma Pack (1) #pragma Pack (POP) compiler is 8-byte alignment defaults; ============== ============================================================================================================================================================================================================= ============= http: //data.gameres.com/Message.asp? Topicid = 13636 What is memory alignment

Consider the following structure:

Struct foo {char C1; Short S; CHAR C2; INT i;}; assuming that the member of this structure is compact in memory, suppose the address of the C1 is 0, then the address of S should be 1, the address of C2 is 3, i's address is 4. That is, C1 00000000, S 00000001, C2 00000003, i 00000004.

However, we write a simple program in Visual C / C 6:

Struct Foo A; Printf ("C1% P, S% P, C2% P, I% P / N", (Void *) & a.c1 - (unsigned int) & A, (Unsigned INT) (void *) & a.s - (unsigned int) & a, (unsigned int) & a.c2 - (unsigned int) & A, (unsigned int) (void *) & a.i - (unsigned int) & a); operation, output: C1 00000000, S 00000002, C2 00000004, i 00000008. Why is this this? This is the problem caused by memory alignment.

Why do there be memory?

The following segments are selected from "Intel Architecture 32 Manual". Words, double words, and quad words do not need to be aligned in memory on the natural boundary. (For words, double words, and four words, the natural boundaries are even addresses, which can be 4 complete addresses, and the address that can be completely removed.) In any case, in order to improve the performance, data structure (especially Stack) should be aligned on the natural boundary as much as possible. The reason is that in order to access unsigned memory, the processor needs two memory access; however, the aligned memory access only needs to be accessed. A word or double word operance spans the 4-byte boundary, or a four-character operand spans the 8-byte boundary, which is considered to be unsigned, which requires two bus cycles to access memory. A word start address is an odd number but there is no leapfrog that is considered to be aligned, and can be accessed in a bus cycle. Some operational double four words require memory operations to align in the natural boundary. If the operand is not aligned, these instructions will generate a universal protection exception (#GP). The natural boundary of the double four word is the address that can be tied to the 16. Other operational double four words allow unconfigured access (no universal protection exception), however, additional memory bus cycles are required to access unsigned data in memory.

The compiler is processed by memory

By default, the C / C compiler defaults to the structure and the member data in the stack. Therefore, the above program output becomes: C1 00000000, S 00000002, C2 00000004, i 00000008. The compiler will move the unsigned member to the backward, and each member is aligned to the natural boundary, which has also caused the size of the entire structure to be large. Although it will sacrifice a little space (there is a void between members), performance is improved. It is also this reason, we can't assert SIZEOF (FOO) == 8. In this example, SIZEOF (FOO) == 12.

How to avoid the impact of memory

So, can you achieve the purpose of improving performance, save a little space? There is a little tip that can be used. For example, we can change the above structure:

Struct bar {char C1; char C2; short s; int i;}; so, each member is aligned with its natural boundary, thereby avoiding auto-alignment of the compiler. In this example, SizeOf (BAR) == 8.

This tip has an important role, especially when this structure is provided to third parties as part of the API. Third-party developers may change the default alignment option of the compiler to cause this structure to use some alignment in your released DLL, and where to use another alignment in the third party developer. This will lead to major problems. For example, the FOO structure, our DLL uses the default alignment option, aligned to C1 00000000, S 00000002, C2 00000004, i 00000008, while SIZEOF (FOO) == 12. The third party closes the alignment option, causing the C1 00000000, S 00000001, C2 00000003, i 00000004, while SIZEOF (FOO) == 8. How to use alignment options in C / C

The compilation options in the VC6 are / zp [1 | 2 | 4 | 8 | 16], / zp1 indicates that the 1-byte boundary is aligned, corresponding, / ZPN is aligned in the n-byte boundary. The N-byte boundary is aligned. The address of a member must be arranged on an integer multiple of the member's size or an integer multiple of N to take the minimum of them. That is: MIN (Sizeof (MEMBER), N) actually, and the 1-byte boundary is aligned with no vacuum between structural members. The / ZPN option is applied to the entire project, affecting all the structures involved in compilation. To use this option, you can open the engineering property page, C / C page in VC6, select the Code Generation classification, and select it in Struct Member Alignment.

To use the alignment option specifically for some structural definitions, you can use the #pragma Pack to compile instructions. The instruction syntax is as follows: #pragma pack ([Show] | [Push | POP] [, Identifier], N) meaning and / ZPN options are the same. such as:

#pragma pack (1) struct foo_pack {char C1; Short S; CHAR C2; INT i;}; # prgma pack ()

Stack memory

We can observe that alignment in the stack in VC6 is not affected by structural members alignment options. (Or two is two yards). It is always aligned and is aligned on the 4-byte boundary.

Verify code

#include

Struct foo {char C1; short s; char C2; int 1;

Struct bar {char C1; char C2; short s; int 1;};

#pragma pack (1) struct foo_pack {char C1; Short S; CHAR C2; INT i;}; # prgma pack ()

INT Main (int Argc, char * argv []) {char C1; short s; char C2; int I;

Struct foo a; struct bar b; struct foo_pack p;

Printf ("Stack C1% P, S% P, C2% P, I% P / N", (Unsigned int) & c1 - (unsigned int) & i, (unsigned int) (void * ) & S - (void *) & c2 - (unsigned int) & i, (unsigned int) & i - (unsigned int) (void * ) & i); Printf ("Struct Foo C1% P, S% P, C2% p, I% p / n", (unsigned int) & a.c1 - (unsigned int) (void *) & A, (unsigned int) & a.s - (unsigned int) & A, (unsigned int) & a.c2 - (unsigned int) & A, (unsigned int) (Void " *) & a.i - (unsigned int) (void *) & a);

Printf ("Struct Bar C1% P, C2% P, S% P, I% P / N", (Unsigned int) & b.c1 - (unsigned int) (void *) & b, (unsigned int) (void *) & b.c2 - (unsigned int) & b, (unsigned int) & b.s - (unsigned int) & b, (unsigned int) & b. I - (unsigned int) & b);

Printf ("Struct Foo_PACK C1% P, S% P, C2% P, I% P / N", (Unsigned Int) & P.c1 - (unsigned int) & p, (unsigned int) (void *) & p.S - (unsigned int) & p, (veryred int) & p.c2 - (unsigned int) & p, (unsigned int) & p. I - (unsigned int) & p);

Printf ("SIZEOF FOO IS% D / N", SIZEOF (FOO)); Printf ("SizeOf Bar IS% D / N", SIZEOF (BAR)); Printf ("SizeOf Foo_Pack IS% D / N", SIZEOF Foo_pack); Return 0;}

Finish

转载请注明原文地址:https://www.9cbs.com/read-98649.html

New Post(0)