The rationale behind the rule has always been clear to me, but it can be difficult to decipher how the rule will be applied. Judging by some of the defect reports I've linked to it seems that even the people writing the standard are a bit confused. Defect report #236 is a good example of this (it's still not resolved after all these years as far as I know): Defect Report #236
Code:
#include <stdlib.h>#include <stdio.h>
void f(int *qi, double *qd) {
int i = *qi + 2;
*qd = 3.1; /* Can the compiler move this assignment to the top of function? */
*qd *= i;
printf("qd = %f\n", *qd);
return;
}
int main(void) {
void *vp;
int *pi;
double *pd;
vp = malloc(sizeof(int) + sizeof(double));
pi = vp;
*pi = 7;
pd = vp;
f(pi, pd);
free(vp);
return 0;
}
The committee responded with this:
Both programs invoke undefined behavior,
by calling function f with pointers qi and qd that have different types but designate the same region of storage. The translator has every right to rearrange accesses to *qi and *qd by the usual aliasing rules.
There is nothing in the standard that forbids this since the aliasing rule is entirely defined in terms of how you access memory; not what kind of pointers you have to it. No wonder I'm confused when even the people who are writing the standard can't get it right. With that said, common sense should dictate that you don't write code like the one in this post.