Search code examples
cconstantslanguage-lawyerundefined-behaviorstrict-aliasing

Is it okay for int** and const int** to alias?


It is my understanding that something like this is okay:

const int ci = 42;
const int *cip = &ci;
int *ip = (int *)cip;
int j = *ip;

What about this?

const int ci = 42;
const int *cip = &ci;
const int **cipp = &cip;
int **ipp = (int **)cipp;
int j = **ipp;

Solution

  • The expression *ipp is an lvalue of type int *, however it is being used to access an object of effective type const int *. (Namely, cip).

    According to the letter of the standard, it is a strict aliasing violation: the list of allowed types to alias does not include aliasing T * as const T * or vice versa.

    The closest exception is this one: (C11 6.5/6 excerpt)

    • a qualified version of a type compatible with the effective type of the object

    "qualified version" is clearly defined by C11 6.2.5/26:

    Each unqualified type has several qualified versions of its type, corresponding to the combinations of one, two, or all three of the const, volatile, and restrict qualifiers. The qualified or unqualified versions of a type are distinct types that belong to the same type category and have the same representation and alignment requirements. A derived type is not qualified by the qualifiers (if any) of the type from which it is derived.

    So the exception is that T may be aliased as const T and vice versa, but there is no similar exception for pointers to aliasable types. const T * is not a qualified version of T *.


    However there is of course the footnote:

    The intent of this list is to specify those circumstances in which an object may or may not be aliased

    I couldn't say whether the intent of the rule is for const T * and T * to be aliasable or not. It seems unclear to me what the purpose of specifying that T * and const T * have "the same representation and alignment requirements" (6.2.5/28) would be if it is not aliasable.