Memory Alignment in C Structures

I am working on a 32-bit machine, so I believe that the memory alignment should be 4 bytes. Let's say I have a structure:

typedef struct { unsigned short v1; unsigned short v2; unsigned short v3; } myStruct; 

the actual size is 6 bytes, and I suppose the aligned size should be 8, but sizeof(myStruct) returns me 6.

However, if I write:

 typedef struct { unsigned short v1; unsigned short v2; unsigned short v3; int i; } myStruct; 

actual size is 10 bytes, aligned is 12, and this time sizeof(myStruct) == 12 .

Can someone explain what the difference is?

+49
c ++ c memory-alignment structure-packing
Mar 25 2018-11-11T00:
source share
10 answers

At least on most machines, the type only aligns with the border, as large as the type itself [Edit: you cannot really require more alignment than this because you must be able to create arrays and you cannot insert padding into an array]. In your short implementation, apparently 2 bytes and int 4 bytes.

This means that your first structure is aligned with a 2-byte boundary. Since all members have 2 bytes apiece, no padding is added between them.

The second contains a 4-byte element that aligns with the 4-byte boundary. Since it is preceded by 6 bytes, 2 bytes of padding are inserted between v3 and i , giving 6 bytes of data in short s, two bytes of padding and another 4 bytes of data in int for a total of 12.

+45
Mar 25 '11 at 17:19
source share
β€” -

Forget about the different members, even if you write two structures whose members are exactly the same, the difference is that the order in which they are declared is different, then the size of each structure can be (and often) different.

For example, see this,

 #include <iostream> using namespace std; struct A { char c; char d; int i; }; struct B { char c; int i; //note the order is different! char d; }; int main() { cout << sizeof(A) << endl; cout << sizeof(B) << endl; } 

Compile it with gcc-4.3.4 and you get this output:

 8 12 

That is, the sizes are different from each other, although both structures have the same elements!

Ideone Code: http://ideone.com/HGGVl

The bottom line is that the standard does not say how debugging should be performed, and therefore compilers can make any decisions, and you cannot assume that all compilers make the same decision.

+16
Mar 25 '11 at 17:23
source share

By default, values ​​are aligned according to their size. So a 2-byte value like a short is aligned on a 2-byte boundary, and a 4-byte value like int is aligned on a 4-byte boundary

In your example, 2 padding bytes are added before i to ensure that i falls into a 4-byte boundary.

(The whole structure is aligned on the border, at least as large as the largest value in the structure, so your structure will be aligned with the 4-byte border.)

Actual rules vary by platform - the Wikipedia page on Data Structure Alignment contains more detailed information.

Compilers usually allow you to manage packaging through (for example) #pragma pack .

+13
Mar 25 '11 at 17:20
source share

First, while the fill specification is supplemented by the compiler, the OS also imposes some rules regarding alignment requirements. This answer assumes you are using gcc, although the OS may vary

To determine the space occupied by a given structure and its elements, you can follow these rules:

First, suppose that a structure always starts with an address that is correctly aligned for all data types.

Then for each entry in the structure:

  • The minimum space required is the raw size of the element specified by sizeof(element) .
  • The element alignment requirement is the alignment requirement for the base element type. Remarkably, this means that the alignment requirement for the char[20] array is the same as the requirement for a simple char .

Finally, the alignment requirement of the structure as a whole is the maximum value of alignment requirements for each of its elements.

gcc will insert padding after the given element to ensure that the next (or structure, if we are talking about the last element) are correctly aligned. He will never reorder the elements in the structure, even if it will save memory.

Now the alignment requirements themselves are also a bit odd.

  • 32-bit Linux requires 2-byte data types to have 2-byte alignment (their addresses must be even). All larger data types must have 4-byte alignment (addresses end with 0x0 , 0x4 , 0x8 or 0xC ). Note that this also applies to types that are larger than 4 bytes (for example, double and long double ).
  • The 32-bit version of Windows is more stringent, if the type of K-bytes is in size, it must be byte-aligned. This means that a double can only be placed at an address ending in 0x0 or 0x8 . The one exception to this is a long double , which is still 4-byte aligned, even if it is actually 12 bytes.
  • For Linux and Windows on 64-bit machines, the K byte type must be byte-aligned. Again, long double is an exception and must be aligned by 16 bytes.
+4
Mar 25 '11 at 18:41
source share

Assuming that:

 sizeof(unsigned short) == 2 sizeof(int) == 4 

Then I personally would use the following (your compiler may be different):

 unsigned shorts are aligned to 2 byte boundaries int will be aligned to 4 byte boundaries. typedef struct { unsigned short v1; // 0 bytes offset unsigned short v2; // 2 bytes offset unsigned short v3; // 4 bytes offset } myStruct; // End 6 bytes. // No part is required to align tighter than 2 bytes. // So whole structure can be 2 byte aligned. typedef struct { unsigned short v1; // 0 bytes offset unsigned short v2; // 2 bytes offset unsigned short v3; // 4 bytes offset /// Padding // 6-7 padding (so i is 4 byte aligned int i; // 8 bytes offset } myStruct; // End 12 bytes // Whole structure needs to be 4 byte aligned. // So that i is correctly aligned. 
+4
Mar 25 '11 at 18:41
source share

Each data type must be aligned on its own size memory boundary. Thus, short should be aligned on the 2-byte boundary, and int should be on the 4-byte boundary. Similarly, a long long would have to be on an 8-byte boundary.

+2
Mar 25 '11 at 17:18
source share

In your first structure, since each element is short , the entire structure can be aligned at short borders, so no indentation is needed at the end.

In the second structure, int (supposedly 32 bits) should be word aligned, so it inserts indents between v3 and i to align i .

+2
Mar 25 '11 at 17:20
source share

The reason for the second sizeof(myStruct) is 12 is the padding that is inserted between v3 and i to align i with the 32-bit border. There are two bytes.

Wikipedia explains the laying and alignment quite clearly.

+1
Mar 25 2018-11-11T00:
source share

The standard does not say much about the structure of structures with full types - this is before the compiler. He decided that he needed int to start from the border to access it, but since he had to address the cross-border memory for shorts, there was no need to insert them

0
Mar 25 '11 at 17:18
source share

It looks like it is bound to bounderies based on the size of each var, so the address is a multiple of the size it is accessed (so the shorts are aligned with 2, ints aligned to 4, etc.) if you moved one of the shorts after int , sizeof(mystruct) should be 10. Of course, it all depends on the compiler used and what settings it uses in turn.

0
Mar 25 '11 at 17:21
source share



All Articles