On Wed, 29 Jun 2005 10:22:13 +0200, Grumble wrote:
>> The code I've written below breaks an 8 byte double into two 4 byte
>> unsigned integers via a union. How should this code be modified so it
>> conforms to C's aliasing rules?
>>
>> #include <assert.h>
>> #include <stdint.h>
>> #include <stdlib.h>
>> #include <stdio.h>
>>
>> union u {
>> double f64;
>> uint32_t u32[2];
>> };
>>
>> int main() {
>> assert(sizeof(double)==
;
>> double val=strtod("1.23", NULL);
>> printf("%i %i\n", ((union u) val).u32[0], ((union u) val).u32[1]);
>> return 0;
>> }
>
> I am not sure it is safe to cast 'double' to 'union u'.
>
> In C89, writing to member f64, then reading from member u32 has
> implementation-defined behavior - 6.5.2.3 #5.
I suspect aliasing rules are better specified in C99 (6.5 #7):
An object shall have its stored value accessed only by an lvalue
expression that has one of the following types:
-- a type compatible with the effective type of the object,
-- a qualified version of a type compatible with the effective type of
the object,
-- a type that is the signed or unsigned type corresponding to the
effective type of the object,
-- a type that is the signed or unsigned type corresponding to a
qualified version of the effective type of the object,
-- an aggregate or union type that includes one of the aforementioned
types among its members (including, recursively, a member of a
subaggregate or contained union), or
-- a character type.
Doesn't the second to last point mean that writing to member f64 then
reading from member u32 is well specified in C99?
If so is this approach conforming:
double val=strtod("1.23", NULL);
union u tmp;
tmp.f64=val;
printf("%i %i\n", tmp.u32[0], tmp.u32[1]);
(This eliminates the dubious casts, which is aways a good sign!)
Regards,
Adam