TypedEf struct {uint32 NumeLements; union {uint32 ObjectHandle;} entry;} str_array, * pstr_Array;
There are also two #pragma packs (push, 1) #pragma pack (POP) #pragma pack ([n]) This instruction specifies the compact alignment of the structure and the federation. The structure of a complete conversion unit and the combined compact alignment is set by / z P option. Compact alignment P a c e Compile instructions in the data sheet setting. This compilation indication takes effect at the first structure or joint description thereof. This compilation indication is invalid for the definition. When you use #pragma pack (n), the N is 1, 2, 4, 8 or 1 6 here. Each struct member after the first structural member is stored in a smaller member type or N-byte limits. If you use a non-reflected #pragma Pack, the structural member is compact to the value specified in / z P. The default / z P compact value is / z P 8. The compiler also supports the following enhanced grammar: #pragma pack ([[{PUSH | POP},] [Identifier,]]] [N]) If the different components use the PACK compile indication to specify different compact alignment, this syntax allows you Combining program components into a separate conversion unit. The P a C K compilation indication with the P U S h parameter is stored in an internal compiler stack each appearing. The parameter table of the compilation indication is read from left to right. If you use P U s H, the current compact value is stored; if you give a N value, this value will become a new compact value. If you specify an identifier, you select a name, then the identifier will link with this new compact value. Each appearance with a PO C k compilation indication with a P O P-parameter will retrieve the value of the internal compiler stack top and make the value a new compact alignment value. If you use the P O P parameter and the internal compiler stack is empty, the compact value is a value given by the command line, and will generate a warning message. This value will become a new compact value if you use P O P and specify a value. If you use a POP and specify an identifier, all the values stored in the stack will be deleted from the stack until a matching identifier is found, the compact value related to the identifier is also removed from the stack, and this is only The compact value exists before the identifier enters the stack becomes a new compact value. If the matching identifier is not found, the compact value set by the command line will be used, and one level warning will be generated. The default is more compact alignment 8. P a c K compiles the new enhancement to write the header file to ensure that the compact value before and after the header is encountered. 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;}