Basically, is this code legal when strict aliasing is enabled?
void f(int *pi) {
void **pv = (void **) π
*pv = NULL;
}
Here, we access an object of one type (int*
) through a pointer of another type (pointer to void *
), so I would say that it is indeed a strict-aliasing violation.
But a sample attempting to highlight the undefined behavior makes me doubt (even if it does not prove that it is legal).
First, if we alias int *
and char *
, we can get different values depending on the optimization level (so it is definitely a strict-aliasing violation):
#include <stdio.h>
static int v = 100;
void f(int **a, char **b) {
*a = &v;
*b = NULL;
if (*a)
// *b == *a (NULL)
printf("Should never be printed: %i\n", **a);
}
int main() {
int data = 5;
int *a = &data;
f(&a, (char **) &a);
return 0;
}
$ gcc a.c && ./a.out
$ gcc -O2 -fno-strict-aliasing a.c && ./a.out
$ gcc -O2 a.c && ./a.out
Should never be printed: 100
But the very same sample with void **
instead of char **
does not exhibit the undefined behavior:
#include <stdio.h>
static int v = 100;
void f(int **a, void **b) {
*a = &v;
*b = NULL;
if (*a)
// *b == *a (NULL)
printf("Should never be printed: %i\n", **a);
}
int main() {
int data = 5;
int *a = &data;
f(&a, (void **) &a);
return 0;
}
$ gcc a.c && ./a.out
$ gcc -O2 -fno-strict-aliasing a.c && ./a.out
$ gcc -O2 a.c && ./a.out
Is it just accidental? Or is there an explicit exception in the standard for void **
?
Or maybe just the compilers handle void **
specifically because in practice (void **) &a
is too common in the wild?