Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do pointer casts maintain alignment properties?

Say, I have an aligned array

alignas(X) char arr[sizeof(X)];

Is the pointer

X * ptr = reinterpret_cast<X*>(arr);

guaranteed to be properly aligned according to the alignment requirements of X?

It seems obvious that this is the case, however it does not appear to be obvious from the C++ standard.

I don't find anything in the standard that would prevent a compiler to align a struct of the form

struct X
{
    int16_t a;
    int32_t b;
    int16_t c;
};

like this in memory:

+-+-+-+-+-+-+-+-+
|a|a|b|b|b|b|c|c|
+-+-+-+-+-+-+-+-+
     ^
     aligned to 32-boundary

so that the objects of type X are aligned in such a way that no padding is needed and b is aligned correctly at the same time to a 32-bit boundary. The statement (N4713, § 6.6.5.1)

An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated.

is not violated by that and I don't see any other statement in the standard that violates it.

like image 972
Ralph Tandetzky Avatar asked May 21 '19 14:05

Ralph Tandetzky


Video Answer


2 Answers

Your structure should have an exotic alignment: it should be 16 bit aligned but not 32 aligned. Mathematically speaking, its address should be of the form 32*n+16, with n an integer.

This is forbidden by the language, a 32 bit alignment should satisfy a 16 bit alignment. Said differently any 16bit aligned structure should fit in a 32 bit aligned storage region, but your 16bit aligned structure don't. See [basic.align]/5:

Alignments have an order from weaker to stronger or stricter alignments. Stricter alignments have larger alignment values. An address that satisfies an alignment requirement also satisfies any weaker valid alignment requirement.

like image 176
Oliv Avatar answered Oct 19 '22 11:10

Oliv


The authors of the Standard didn't seek to explicitly prohibit things they thought were impossible. If one compilation units contains a structure like the one you gave:

struct {
  uint16_t a;
  uint32_t b;
  uint16_t c;
} x;

and a compiler isn't omniscient about all the ways that x or structures with identical layout might be used throughout the rest of the program, it will have no choice but to make the offset of b be a multiple of b's alignment. I don't think the Standard explicitly says that the layout of a structure cannot be observably affected by the ways in which it is used, but I think that's because they didn't think a compiler where layouts could vary in that fashion would be able to uphold the Common Initial Sequence guarantees.

like image 27
supercat Avatar answered Oct 19 '22 12:10

supercat