Some code I had needed to do integer operations on (the bits of) floating-point values. The naive double d = something; uint64_t x = *(uint64_t *)&d; gives a type aliasing diagnostic in 4.1, and rightly so. However, attempting to "fix" this by adding an alias-anything intermediate pointer to void or char, uint64_t x = *(uint64_t *)(void *)&d; suppresses the diagnostic but still won't work properly - gcc does not admit that x depends on d, so the assignment of d sometimes ends up after that of x. Using a union intermediate instead, union { double d; uint64_t x; } u; u.d = something; uint64_t x = u.x; works as expected, but I would like to know why - if it is a matter of luck with the current implementation it might cease working when the compiler changes or becomes more aggressive in the future. As far as I can tell from the Standard, it could be argued that none of the above versions are allowed at all, so it's not obvious to me why one should be permitted but not another. I would be grateful for any help with references. The ABI for the platforms I am interested in give guarantees concerning the representation and alignment of the types involved, of course.