About Memory Alignment

Source: Internet
Author: User
Tags data structures pack

Consider the following structure:

struct FOO
{
Char C1;
Short S;
Char C2;
int i;
};

Assuming that the members of this structure are in the compact in memory, assuming that the address of C1 is 0, then the address of S should be 1,C2 's address is 3,i's address is 4. Is
C1 00000000, S 00000001, C2 00000003, I 00000004.

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

struct Foo A;
printf ("C1%p, S%p, C2%p, I%p\n",
(unsigned int) (void*) &a.c1-(unsigned int) (void*) &a,
(unsigned int) (void*) &A.S-(unsigned int) (void*) &a,
(unsigned int) (void*) &a.c2-(unsigned int) (void*) &a,
(unsigned int) (void*) &a.i-(unsigned int) (void*) &a);
Run, Output:
C1 00000000, S 00000002, C2 00000004, I 00000008.

Why is this. This is the problem caused by memory alignment.

Why there is a memory alignment

The following excerpt from the Intel architecture Manual.
Words, two words, and four words on natural boundaries do not need to be aligned in memory. (for words, two words, and four words, the natural boundary is an even address, an address that can be divisible by 4, and an address that can be divisible by 8.) )
In any case, in order to improve the performance of the program, data structures (especially stacks) should be aligned as far as possible on natural boundaries. The reason is that in order to access the misaligned memory, the processor requires two memory access; However, the aligned memory access requires only one access.
A word or two-word operand spans a 4-byte boundary, or a four-word operand crosses 8-byte boundaries and is considered misaligned, requiring two bus cycles to access memory. A word starting address is an odd but not crossed word boundary that is considered aligned and can be accessed in a bus cycle.
Some instructions for manipulating a double four word require that the memory operand be aligned on the natural boundary. If the operands are not aligned, the instructions will produce a generic protection exception (#GP). A four-word natural boundary is an address that can be divisible by 16. The other four-word instruction allows for misaligned access (no generic protection exception), however, additional memory bus cycles are required to access the misaligned data in memory.

The compiler's handling of memory alignment

By default, the C + + compiler defaults to the memory alignment of the structure, the member data in the stack. As a result, the above program output becomes:
C1 00000000, S 00000002, C2 00000004, I 00000008.
The compiler moves the misaligned members backward, aligning each member to the natural boundary, which also causes the entire structure to grow in size. Although a bit of space is sacrificed (there are holes among members), performance is improved.
It is for this reason that we cannot assert sizeof (foo) = 8. In this example, sizeof (foo) = = 12.

How to avoid the impact of memory alignment

Then, can not only achieve the goal of improving performance, but also to save a little space. There is a little bit of skill to use. For example, we can change the above structure to:

struct BAR
{
Char C1;
Char C2;
Short S;
int i;
};
As a result, each member is aligned on its natural boundary, thereby avoiding the compiler's automatic alignment. In this example, sizeof (bar) = = 8.

This technique has an important role to play, especially when this structure is provided to third parties for development use as part of the API. Third-party developers may change the default alignment options for the compiler, causing the structure to use some sort of alignment in your published DLL, but using a different alignment for third-party developers. This can lead to major problems.
For example, the Foo structure, our DLL uses the default alignment option, to the Ziwei
C1 00000000, S 00000002, C2 00000004, I 00000008, at the same time sizeof (foo) = 12.
And a third party closes the alignment option, causing
C1 00000000, S 00000001, C2 00000003, I 00000004, at the same time sizeof (foo) = 8.

How to use the alignment options in C + +

The compilation options in VC6 are/zp[1|2|4|8| ,/ZP1 is aligned with a 1-byte boundary and, accordingly,/ZPN represents an n-byte boundary alignment. N-byte boundary alignment means that the address of a member must be arranged on the integer multiple address of the member's size or on an integer multiple address of n, taking the smallest value in them. Is
Min (sizeof (member), N)
In fact, a 1-byte boundary alignment also indicates that there is no hole between the members of the structure.
The/ZPN option is applied to the entire project, affecting all of the structures participating in the compilation.
To use this option, you can open the Engineering Properties page in VC6, the C + + page, and select the Code generation category, which can be selected in struct member alignment.

To use alignment options specifically for certain structure definitions, you can use the #pragma pack to compile directives. The instruction syntax is as follows:
#pragma pack ([show] | [Push | pop] [, identifier], N)
The meaning is the same as the/ZPN option. Like what:

#pragma packs (1)
struct Foo_pack
{
Char C1;
Short S;
Char C2;
int i;
};
#pragma pack ()

Stack memory Alignment

We can observe that the alignment of the stack in VC6 is not affected by the alignment options of the struct members. (It's a different thing). It is always aligned and aligned on a 4-byte boundary.

Validating code

#include <stdio.h>

struct FOO
{
Char C1;
Short S;
Char C2;
int i;
};

struct BAR
{
Char C1;
Char C2;
Short S;
int i;
};

#pragma packs (1)
struct Foo_pack
{
Char C1;
Short S;
Char C2;
int i;
};
#pragma 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) (void*) &c1-(unsigned int) (void*) &i,
(unsigned int) (void*) &s-(unsigned int) (void*) &i,
(unsigned int) (void*) &C2-(unsigned int) (void*) &i,
(unsigned int) (void*) &i-(unsigned int) (void*) &i);

    printf ("struct Foo C1%p, S%p, C2%p, I%p\n",
          (unsigned int) (void*) &a.c1-(unsigned int) (void*) &a,
          (unsigned int) (void*) &A.S-(unsigned int) (void*) &a,
          (unsigned int) (void*) &a.c2-(unsigned int) (void*) &a,
          (unsigned int) (void*) &a.i-(unsigned int) (void*) &a);

    printf ("struct bar C1%p, C2%p, S%p, I%p\n",
          (unsigned int) (void*) &b.c1-(unsigned int) (void*) &b,
          (unsigned int) (void*) &b.c2-(unsigned int) (void*) &b,
          (unsigned int) (void*) &B.S-(unsigned int) (void*) &b,
          (unsigned int) (void*) &B.I-(unsigned int) (void*) &b);

printf ("struct Foo_pack C1%p, S%p, C2%p, I%p\n",
(unsigned int) (void*) &p.c1-(unsigned int) (void*) &p,
(unsigned int) (void*) &p.s-(unsigned int) (void*) &p,
(unsigned int) (void*) &p.c2-(unsigned int) (void*) &p,
(unsigned int) (void*) &p.i-(unsigned int) (void*) &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;
}

Output results:

Stack C1 0000000C, S 00000004, C2 00000008, I 00000000
struct Foo C1 00000000, S 00000002, C2 00000004, I 00000008
struct Bar C1 00000000, C2 00000001, S 00000002, I 00000004
struct Foo_pack C1 00000000, S 00000001, C2 00000003, I 00000004
sizeof Foo is 12
sizeof Bar is 8
sizeof Foo_pack is 8
Press any key to continue

Finished text

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.