Re: Aliasing in C99

Discussion in 'C Programming' started by James Kuyper, May 31, 2012.

  1. James Kuyper

    James Kuyper Guest

    On 05/31/2012 10:01 AM, David Brown wrote:
    > I am trying to figure out how to get aliasing to work correctly according
    > to the C99 rules. For example, converting between a float and its binary
    > representation.
    > float negPCast(float x) {
    > uint32_t u = *((uint32_t *) &x);
    > u ^= 0x80000000u;
    > return *((float *) &u);
    > }
    > In the absence of type-based aliasing, this will negate a float using
    > just a simple xor operation (ignore any issues with endianness, int
    > sizes, NaNs, etc., since this is just an example).
    > The pointer typecasting here will break strict aliasing rules, and is
    > therefore not valid C99. (I'm guessing that in this case, most compilers
    > will generate code that works as desired - but I'm looking for strictly
    > conforming methods.)
    > It is possible to re-implement it using type-punning unions:
    > float negUnion(float x) {
    > union { float f; uint32_t u; } uf;
    > uf.f = x;
    > uf.u ^= 0x80000000;
    > return uf.f;
    > }
    > This doesn't use pointer typecasting, but I believe type-punning unions
    > are undefined in C but implemented "properly" in most compilers.

    The C99 standard explicitly clarifies (though only in a non-normative
    footnote) that reading the value of a member different from the one last
    written to results in reinterpretation of the bytes making up that
    object according to the new type. In other words, it matches exactly
    what most C compilers have done all along. As long as you're willing to
    make a host of unportable assumptions about the representation of
    'float' and 'uint32_t', your code should work.

    > It is also possible to use pointers to unions in casts:
    > float negUnionPCast(float x) {
    > typedef union { float f; uint32_t u; } UF;
    > uint32_t u = ((UF*) &x)->u;
    > u ^= 0x80000000u;
    > return ((UF*) &u)->f;
    > }
    > I /think/ pointer casts like this are not subject to strict aliasing
    > rules, but I don't know if the union usage is valid.

    If you had an actual union object, conversions of pointers to it into
    pointers to the member types would be unproblematic. However, doing it
    this way could be a problem. If, for instance, float has an alignment
    requirement of 2, while uint32_t has an alignment requirement of 4, then
    UF will also have an alignment requirement of 4. In that case &x might
    not have the right alignment to allow conversion to UF*.

    A union is allowed to have unnamed padding bytes. For instance, on a
    64-bit machine, it might speed things up to pad this union to 64 bits,
    allowing it to be accessed using 64-bit operations. "When a value is
    stored in an object of structure or union type, including in a member
    object, the bytes of the object representation that correspond to any
    padding bytes take unspecified values." ( This will be
    problematic since *(UF*)&x is not an actual union object containing
    padding bytes that you have permission to set.
    James Kuyper
    James Kuyper, May 31, 2012
    1. Advertisements

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Glen Low

    C99 complex numbers and aliasing

    Glen Low, Aug 3, 2004, in forum: C Programming
    David R Tribble
    Aug 20, 2004
  2. Mike

    C99, strict aliasing

    Mike, Jul 20, 2010, in forum: C Programming
    Tim Rentsch
    Jul 21, 2010
  3. Eric Sosman

    Re: Aliasing in C99

    Eric Sosman, May 31, 2012, in forum: C Programming
    Tim Rentsch
    May 31, 2012
  4. Xavier Roche

    Re: Aliasing in C99

    Xavier Roche, May 31, 2012, in forum: C Programming
    Xavier Roche
    May 31, 2012
  5. Tim Rentsch

    Re: Aliasing in C99

    Tim Rentsch, May 31, 2012, in forum: C Programming
    Tim Rentsch
    Jun 1, 2012

Share This Page