Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

For example, consider the following:

Assume that int is 4-byte aligned, and long is 8-byte aligned.

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

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

  • P refers to a byte of padding
  • A refers to a byte of a
  • B refers to a byte of b
  • C refers to a byte of c

In this case, sizeof(example) is 24.

but another way of doing it would be the following: AAAABBBBBBBBCCCC with the whole structure having alignment such that the address of the starting byte mod 8 = 4 (not sure how to say this more succinctly)

in this case, there is no padding needed, so you save 8 bytes per instance.

My question is, are compilers allowed to do this(by the standard)? Do they actually do this? I've always seen alignment discussed simply in bytes.

like image 222
Bwmat Avatar asked Nov 23 '13 19:11

Bwmat


People also ask

What is alignment requirement?

Every complete object type has a property called alignment requirement, which is an integer value of type size_t representing the number of bytes between successive addresses at which objects of this type can be allocated. The valid alignment values are non-negative integral powers of two.

What does 4 byte aligned mean?

A 1-byte variable (typically a char in C/C++) is always aligned. A 2-byte variable (typically a short in C/C++) in order to be aligned must lie at an address divisible by 2. A 4-byte variable (typically an int in C/C++) must lie at an address divisible by 4 and so on.

What does it mean to be 8 byte aligned?

An object that is "8 bytes aligned" is stored at a memory address that is a multiple of 8. Many CPUs will only load some data types from aligned locations; on other CPUs such access is just faster.

What does it mean to be 16 byte aligned?

This effectively means that the address of the memory your data resides in needs to be divisible by the number of bytes required by the instruction. So in your case the alignment is 16 bytes (128 bits), which means the memory address of your data needs to be a multiple of 16.


1 Answers

A struct cannot have alignment requirements that are less strict than the alignment requirements of its members. If a member of the struct is 8-byte aligned, then the struct needs to be at least 8-byte aligned. If the struct is 8-byte aligned, then in your example, the second member would not be 8-byte aligned, since it is offset four bytes from the beginning of an 8-byte aligned struct, so it wouldn't meet the requirements.

The possible alternative would be to put padding at the beginning of the struct, but this is not allowed:

C++03 9.2p17

A pointer to a POD-struct object, suitably converted using a reinterpret_cast, points to its initial member (...) and vice-versa. [Note: There might therefore be unnamed padding within a POD-struct object, but not at its beginning, as necessary to achieve proper alignment.]

Another possible alternative would be (as your are suggesting) to have the 8-byte alignment actually mean ((address%8)==4) (as opposed to (address%8)==0). If that were the case though, then your 8-byte aligned long would have the same requirement. It isn't possible to have types with both (address%8)==0 and (address%8)==4 alignment, since there would be no way to generically allocate memory that meets both alignment requirements. Since the long would have this special alignment requirement as well, you still wouldn't be able to avoid the padding.

like image 193
Vaughn Cato Avatar answered Oct 14 '22 00:10

Vaughn Cato