Is it possible for a type to have alignment requirements other than "n-byte alignment",

For example, consider the following:

Suppose int is 4-byte aligned and long is 8-byte.

struct example { int a; long b; int c; }; 

The obvious way for the compiler to put this in memory would be: AAAAPPPPBBBBBBBBCCCCPPPP with the whole structure having 8-byte alignment.

  • P refers to fill byte
  • A refers to byte
  • B refers to byte b
  • C refers to byte c

In this case, sizeof (example) is 24.

but another way to do this would be as follows: AAAABBBBBBBBCCCCCC with the whole structure having alignment, so the address of the initial byte mod 8 = 4 (not sure how to say it more briefly)

in this case, you do not need to fill, so you save 8 bytes per instance.

My question is, are compilers allowed to do this (by standard)? Do they really do it? I always saw that alignment was discussed simply in bytes.

+7
c ++ memory-alignment
source share
3 answers

A structure cannot have alignment requirements that are less stringent than alignment requirements for its members. If the structure member is 8-byte aligned, then the structure must be at least 8-byte aligned. If the 8-byte structure is aligned, then in your example, the second member will not be aligned by 8 bytes, since it is offset four bytes from the beginning of the 8-byte aligned structure, so it will not meet the requirements.

A possible alternative would be to add a pad at the beginning of the structure, but this is not allowed:

C ++ 03 9.2p17

A pointer to an object of the POD structure properly transformed using reinterpret_cast points to its initial member (...) and vice versa. [Note. Thus, in the case of a POD structure object, but not at the beginning, an unnamed padding may be required if necessary to achieve proper alignment.]

Another possible alternative would be (as you assume) that 8-byte alignment would actually mean ( (address%8)==4) (as opposed to (address%8)==0 ). If that were the case, then your 8-byte aligned long would have the same requirement. It is not possible to have types with alignment (address%8)==0 and (address%8)==4 , as there will be no general way to allocate memory that satisfies both alignment requirements. Since long will have this special alignment requirement, you still cannot escape filling.

+2
source share

You forget about arrays. In the general case, as you suggest, should the compiler make sure that the "starting byte mod 8 = 4" in the case of an array for each element of the array?

Remember that C requires that a true value be true for any array object of type T a[N]

 sizeof a == sizeof *a * N 

This means that any addition contained within the entire object of array a must come from separate elements of type T Arrays cannot add their own additions.

In other words, the compiler cannot just remember the correct alignment of individual structure objects. In fact, it should include padding in structural objects and consider this addition as part of the sizeof for this structure object.

Your AAAABBBBBBBBCCCC is "good" because when such objects are stored compactly in an array (without additional filling), they all align correctly if the very first element of the array is correctly aligned. But how do you expect to achieve the correct alignment for the first element if the memory of the array is allocated, for example, malloc . malloc does not know anything about the type for which memory is allocated, which means that it cannot adapt its behavior to the specific alignment requirements of your type.

+2
source share

The compiler will try to align each element by adding an addition. As a rule, the maximum alignment depends on the compiler and processor (for example, usually you do not have alignments, such as 256 byte alignment). This maximum alignment is not even present in the standard, so it is possible that the compiler aligns structures of size 2048 ...

As DyP said in the comments, gcc can pack it as:

 AAAA PPPP BBBB BBBB CCCC PPPP 

Living example .

Please note that he can pack it in another way (try from double to Ideone and compare with Stacked-Crooked ).

If you don't want padding, you can use the preprocessor directive:

 #pragma pack 

It is compatible with gcc and MSVC .

At the same time, the same version of gcc used for the previous example packs it as:

 AAAA BBBB BBBB CCCC 

Living example .

0
source share

All Articles