izac89
izac89

Reputation: 3930

Does the following code violate strict aliasing?

Does the following code violate strict aliasing?

int a = 0;
*((int *)((char *)&a)) = 1;

Why not? because we end up dereferencing the pointer of int a using int * which is legit

Why yes? because we cast the char * to int * and dereferencing it (the int *), which seems as a strict aliasing violation

Upvotes: 1

Views: 82

Answers (3)

zwol
zwol

Reputation: 140445

The strict aliasing rules do not care about intermediate casts. They only care about the type of the pointer ultimately used to access an object, and the original type of the object itself (technically its "effective type", but that's not important right now).

In your example code, you take the address of an int. The result has type int *. You cast that pointer to char *, you cast it again to int *, and only then do you dereference it. The type of the pointer used in the access is int * and the type of the object pointed to is int, so the strict aliasing rules have no problem.

You are correct that the strict aliasing rules are asymmetric with respect to char, but that only matters when either the type of the object itself is char or the type of the pointer used in the access is char:

char x[sizeof(int)] = { 0 };
*(int *)x = 1;  // undefined behavior

int y = 1234;
*(char *)y = 0; // valid; value of y becomes unspecified

Theoretically, a cast between two pointer types can lose information, but not when casting from some other type to char * and back again. Also, this is only relevant on computers that you are very unlikely to encounter nowadays. I can't actually remember an example.

Upvotes: 2

Sourav Ghosh
Sourav Ghosh

Reputation: 134286

No, it is not a violation.

because we cast the char * to int *

You are missing the part the the char * you mentioned was actually an int *. Thus, finally the access to an int type is made via a pointer to int - this is perfectly valid.

Upvotes: 1

dbush
dbush

Reputation: 223689

This code is valid. It is allowed to convert between two object pointer types and back provided there are not alignment issues, and converting to a char * is explicitly allowed to access an objects representation (i.e. read the individual bytes).

Section 6.3.2.3p7 of the C standard states:

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.

Since you covert from int * to char * then back to int *, there are no strict aliasing violations here.

Upvotes: 1

Related Questions