public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* How to type-pun and why
@ 2006-06-12 15:05 Mattias Engdegård
  2006-06-12 15:18 ` Gabriel Dos Reis
  2006-06-12 15:23 ` Andrew Haley
  0 siblings, 2 replies; 6+ messages in thread
From: Mattias Engdegård @ 2006-06-12 15:05 UTC (permalink / raw)
  To: gcc-help

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.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: How to type-pun and why
  2006-06-12 15:05 How to type-pun and why Mattias Engdegård
@ 2006-06-12 15:18 ` Gabriel Dos Reis
  2006-06-12 15:24   ` Perry Smith
  2006-06-12 15:23 ` Andrew Haley
  1 sibling, 1 reply; 6+ messages in thread
From: Gabriel Dos Reis @ 2006-06-12 15:18 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: gcc-help

 Mattias Engdegård <mattias@virtutech.se> writes:

| 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.

that union trick is invalid as well, from the standard point of view.
However, GCC makes a guarantee that it will be supported.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: How to type-pun and why
  2006-06-12 15:05 How to type-pun and why Mattias Engdegård
  2006-06-12 15:18 ` Gabriel Dos Reis
@ 2006-06-12 15:23 ` Andrew Haley
  2006-06-12 18:04   ` Mattias Engdegård
  1 sibling, 1 reply; 6+ messages in thread
From: Andrew Haley @ 2006-06-12 15:23 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: gcc-help

Mattias Engdegård writes:
 > 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

It's a gcc extension to ISO C.  

 > - 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.

I doubt it.  We have to keep it working becasue so much library code
requires it.

 > 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.

Andrew.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: How to type-pun and why
  2006-06-12 15:18 ` Gabriel Dos Reis
@ 2006-06-12 15:24   ` Perry Smith
  2006-06-12 16:01     ` Gabriel Dos Reis
  0 siblings, 1 reply; 6+ messages in thread
From: Perry Smith @ 2006-06-12 15:24 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: Mattias Engdegård, gcc-help

Could he add a "volatile" keyword to fix it (from the standard point  
of view)?

On Jun 12, 2006, at 10:18 AM, Gabriel Dos Reis wrote:

>  Mattias Engdegård <mattias@virtutech.se> writes:
>
> | 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.
>
> that union trick is invalid as well, from the standard point of view.
> However, GCC makes a guarantee that it will be supported.
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: How to type-pun and why
  2006-06-12 15:24   ` Perry Smith
@ 2006-06-12 16:01     ` Gabriel Dos Reis
  0 siblings, 0 replies; 6+ messages in thread
From: Gabriel Dos Reis @ 2006-06-12 16:01 UTC (permalink / raw)
  To: Perry Smith; +Cc: Mattias Engdegård, gcc-help

On Mon, 12 Jun 2006, Perry Smith wrote:

| Could he add a "volatile" keyword to fix it (from the standard point
| of view)?

I don't see how the standard guarantees that "volatile" will make it
work.

In general, when there is a type rule violation, "volatile" isn't the
answer.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: How to type-pun and why
  2006-06-12 15:23 ` Andrew Haley
@ 2006-06-12 18:04   ` Mattias Engdegård
  0 siblings, 0 replies; 6+ messages in thread
From: Mattias Engdegård @ 2006-06-12 18:04 UTC (permalink / raw)
  To: gcc-help

Andrew Haley <aph@redhat.com> writes:

>It's a gcc extension to ISO C.  

I only found "union casts" among the relevant extensions, but perhaps they
imply that the union trick work? (I'm reluctant to use union casts as they
are illegal outside gcc, but the "union trick" seems to be customary.)

It is tempting to abbreviate the union trick by using pointers, like:

  double d = something;
  uint64_t x = ((union { double d; uint64_t x; } *)&d)->x;

which _seems_ to work - but this is purely anecdotal evidence.
Would this also be guaranteed by the same gcc extension?

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2006-06-12 18:04 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-06-12 15:05 How to type-pun and why Mattias Engdegård
2006-06-12 15:18 ` Gabriel Dos Reis
2006-06-12 15:24   ` Perry Smith
2006-06-12 16:01     ` Gabriel Dos Reis
2006-06-12 15:23 ` Andrew Haley
2006-06-12 18:04   ` Mattias Engdegård

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).