Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 Nov 2002 16:52:22 +0100 (CET)
From:      Harti Brandt <brandt@fokus.gmd.de>
To:        Andrew Gallatin <gallatin@cs.duke.edu>
Cc:        Harti Brandt <brandt@fokus.gmd.de>, <FreeBSD-current@FreeBSD.ORG>
Subject:   Re: gcc 3.2.1 optimization bug ?
Message-ID:  <20021111163918.Y13339-100000@beagle.fokus.gmd.de>
In-Reply-To: <15823.48873.236346.943980@grasshopper.cs.duke.edu>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 11 Nov 2002, Andrew Gallatin wrote:

AG>
AG>Harti Brandt writes:
AG> > On Mon, 11 Nov 2002, TOMITA Yoshinori wrote:
AG> >
AG> > This is probably not a bug, but a feature. You are not expected to access
AG> > a variable through a pointer to a non-compatible type. int and short are
AG> > not compatible. (see your ISO C standard on this topic).
AG> >
AG> > Try to use ntohl(), htonl() for your problem.
AG> >
AG>
AG>On a similar theme, I assume the following is also not safe:
AG>
AG>static __inline u_int64_t
AG>__bswap64 (u_int64_t x)
AG>{
AG>  u_int64_t ret;
AG>  u_int32_t *x_ptr, *ret_ptr;
AG>
AG>  x_ptr = (u_int32_t *)&x;
AG>  ret_ptr = (u_int32_ *)&ret;
AG>  ret_ptr[0] = __bswap32 (x_ptr[1]);
AG>  ret_ptr[1] = __bswap32 (x_ptr[0]);
AG>
AG>  return ret;
AG>}
AG>
AG>
AG>But does using a union make it safe?
AG>
AG>static __inline u_int64_t
AG>__bswap64 (u_int64_t x)
AG>{
AG>  union
AG>  {
AG>    u_int64_t u64;
AG>    u_int32_t u32[2];
AG>  }
AG>  ret, old;
AG>
AG>  old.u64 = x;
AG>  ret.u32[0] = __bswap32 (old.u32[1]);
AG>  ret.u32[1] = __bswap32 (old.u32[0]);
AG>  return ret.u64;
AG>}
AG>
AG>
AG>FWIW, both *seem* to work correctly using gcc version 3.2.1 and high
AG>optimization.

Well, I just had a long discussion with a collegue about the topic. The
main problem is in the ISO-C standard, section 6.7 point 4 which states:

All declarations in the same scope that refer to the same object or
function shall specify compatible types.

This makes any fiddeling with a pointer of a type, that is different from
the type of the variable illegal. It also makes fiddeling with unions and
structs illegal. As far as I understand types are compatible when they
have the same type and type qualifiers. Structs are partly compatible when
they start with fields of the same type. So the only way to legally swap
integer values of any size is via arithmetic. Of course unions and
pointers may work with the given compiler version and optimisation level.
But, nothing in the standard guarantees you anything.

It may be possible that 6.5 (7) the last sentence allows you to access your
32-bit or 64-bit value character-wise (although I'm not sure).

harti

G>
AG>Thanks,
AG>
AG>Drew
AG>

-- 
harti brandt, http://www.fokus.gmd.de/research/cc/cats/employees/hartmut.brandt/private
              brandt@fokus.gmd.de, brandt@fokus.fhg.de


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20021111163918.Y13339-100000>