- What is meant by more strictly aligned pointer types ?
C 2018 6.2.8 5 says:
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.
In case you do not have a specification for “alignment,” C 2018 6.2.8 1 says:
Complete object types have alignment requirements which place restrictions on the addresses at which objects of that type may be allocated. An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated…
In effect, this means an object with alignment requirement A must start at an address that is a multiple of A.
- What does it mean?
Consider some pointer with value P. That is, P is the address to which the pointer points. For purposes of this answer, we take P to be a fully resolved address in the memory space. (Actual pointers may be represented with references to various base addresses or segments, as well as offsets from those bases or from the starts of segments.) When the pointer is convert to a pointer to a different object type, the new object type has some alignment requirement A. If P is a multiple of A, then P is correctly aligned for the object type, and the conversion produces some new valid pointer. (It is not necessarily a pointer that can be used to access an object of the new type, due to other rules in C.) If P is not a multiple of A, then the C standard does not define the behavior of the program. The conversion might not produce a valid pointer, it might produce a pointer adjusted to be correctly aligned, the program might abort, or the program might behave in ways you do not expect.
- How can we safely cast pointers to other types ?
Only convert a pointer to a pointer to a new object type if you know the source pointer is correctly aligned for the destination type.
Given char c;
, converting &c
to int *
is generally not safe because a char
may be given any starting address, but int
typically has an alignment requirement of four bytes in modern C implementations and at least two even in old C implementations. So there is a hazard that &c
is not suitably aligned for int
.
The alignment requirements for types vary between C implementations. If a pointer points to an object with an alignment type as strict or stricter than the new type, then you know it can be converted safely. Otherwise, the C implementation may provide means for testing the alignment. Commonly, converting to a uintptr_t
provides a representation of the address that can be tested to see if it is a multiple of the required alignment. The alignment requirement of a type can be obtained by evaluating _Alignof(type-name)
.