chbaker0 chbaker0 - 5 months ago 14
C++ Question

Is it legal to alias a char array through a pointer to int?

I know that the following is explicitly allowed in the standard:

int n = 0;
char *ptr = (char *) &n;
cout << *ptr;

What about this?

alignas(int) char storage[sizeof(int)];
int *ptr = (int *) &storage[0];
*ptr = 0;
cout << *ptr;

Essentially, I'm asking if the aliasing rules allow for a sequence of chars to be accessed through a pointer to another type. I'd like references to the portions of the standard that indicate one way or another if possible.

Some parts of the standard have left me conflicted; (3.10.10) seems to indicate it would be undefined behavior on the assumption that the dynamic type of
is not
. However, the definition of dynamic type is unclear to me, and the existence of
would lead me to believe that this is possible.


The code int *ptr = (int *) &storage[0]; *ptr = 0; causes undefined behaviour by violating the strict aliasing rule (C++14 [basic.lval]/10)

The objects being accessed have type char but the glvalue used for the access has type int.

The "dynamic type of the object" for a char is still char. (The dynamic type only differs from the static type in the case of a derived class). C++ does not have any equivalent of C's "effective type" either, which allows typed objects to be "created" by using the assignment operator into malloc'd space.

Regarding correct use of std::aligned_storage, you're supposed to then use placement-new to create an object in the storage. The use of placement-new is considered to end the lifetime of the char (or whatever) objects, and create a new object (of dynamic storage duration) of the specified type, re-using the same storage. Then there will be no strict aliasing violation.

You could do the same thing with the char array, e.g.:

alignas(int) char storage[sizeof(int)];
int *ptr = new(storage) int;
*ptr = 0;
cout << *ptr;

Note that no pseudo-destructor call or delete is required for built-in type int. You would need to do that if using a class type with non-trivial initialization. Link to further reading