[several snips done in the following, for compactness]
>>> [on the matter of using a casted pointer]
>>
>> For the same reason (among others) you were concerned in the
>> first place, ie, aliasing rules. You have something that is a
>> float, and in particular a float not in a union, and you access
>> it through a pointer to a union type!
I should have been more specific about my reaction. The wording
of the effective type rules is rather clumsy. I think it's hard
to make a convincing argument either way, based just on that
wording and nothing else. Despite that, I think it's reasonable
to make an educated guess as to the intention behind what was
actually written, and that would go like this: on the one hand
we have a simple variable, ie, not in a union (or struct), and on
the other hand we have an access to a member of a union (struct
member access would be equivalent); we know that the standalone
variable cannot possibly be in a struct or union, whereas member
access _must_ refer to an actual struct or union object, and
therefore the two objects in question must be distinct, ie, no
aliasing can definedly occur between them.
To repeat myself, I wouldn't call this an ironclad argument,
reasoning as it does based somewhat on speculating about the
underlying intention. However, I think the basic reasoning
is convincing enough so that some implementations might take
the same view, and that's why I think it's a grey area, and
consequently best avoided.
> Casts to unions are discussed in the gcc documentation as a gcc
> extension, and are safe to use (carefully) with gcc - but while I
> often use various gcc ports, I also use other compilers, so gcc
> extensions are not a solution.
Even if casts to unions were universally available, casting
a pointer to a non-compound type (ie, not a struct or union)
to a pointer to a compound type is a totally different beast,
because casting to a union (or struct) operates on values,
whereas pointer casting implicitly operates on object
representations and may have resulting aliasing issues.
Casting that works on values can never, in and of itself,
have even potential aliasing issues; casting that works
on pointers always can.
>> However, if you
>> aren't comfortable using compound literals, we can still
>> write a simple function using a direct, functional style
>> (disclaimer: not compiled):
>>
>> float
>> negate_float( float x ){
>> typedef union { unsigned u; float f; } UF;
>> const UF f = { .f = x }, u = { .u = f.u ^ 0x80000000 };
>> return u.f;
>> }
>>
>
> I'd split the line in two:
> const UF f = (UF) { .f = x };
> const UF u = (UF) { .u = f.u ^ 0x80000000 };
I'm fine with either one line or two. Any developer worth his
salt should be able to read either form with no difficulty, and
I think it's wrong to be overly dogmatic about a "one declaration
per line" rule. That said, the specific case here is (for me at
least) below the threshold of arguing one way or another.
Incidentally, it's usually a good rule in newsgroup postings
to use multiple spaces rather than tabs for indentation (and
for that matter all other uses too).
> Then I think it is clear even to people unfamiliar with
> compound literals.
Note that the function body I wrote did not use compound
literals, but just regular initialization. Your two lines
above could (and perhaps should) have been written thusly:
const UF f = { .f = x };
const UF u = { .u = f.u ^ 0x80000000 };
I expect most developers would prefer this writing to the
earlier alternative.
If compound literals are okay for your audience, it seems
natural to avoid the temporary variable 'f', which is used
in only one place; that would allow one declaration instead
of two:
const UF u = { .u = 0x80000000 ^ (UF){ .f = x }.u };
But then I think you know where this is going. :)
> Thanks for your suggestions and comments.
You're welcome, it's good to know they have been helpful.