Search code examples
cuniontype-punningc-standard-library

Issue using Type Punning with union


I wanted to learn more about type punning and aliasing. So I use the code provide by the GCC documentation at option -fstric-aliasing like below :

union a_union{
    int i;
    double d;
};

int f(){
    union a_union t;
    t.d=3.0;

    return t.i
}

/*what I add*/
int main(int argc, char *argv[])
{
    printf("%d\n",f());
    return 0;
}

I expected nothing special but I get only 0. So I test with different value for t.d but no change. I test this code on Debian 9, with gcc 6.3, without option. I also try with option -fno-strict-aliasing same result

If someone can I explain, why I get only 0 that would be great


Solution

  • The sizes of the members do not match in any common systems. int is usually nowadays 32 bits and double 64 bits. Because of little-endian storage, the zero bits at the end of the 3.0000000000 correspond to those of the int member.

    Try this one instead:

    #include <inttypes.h>
    #include <stdio.h>
    
    union q_union{
        uint64_t i;
        double d;
    };
    
    _Static_assert(sizeof (union q_union){}.i == sizeof (union q_union){}.d,
         "The sizes of double and uint64_t must match");
    
    uint64_t f(void) {
        union q_union t;
        t.d = 3.0;
        return t.i;
    }
    
    int main(int argc, char *argv[])
    {
        printf("%" PRIu64 "\n", f());
        printf("%#" PRIx64 "\n", f());
        return 0;
    }
    

    outputs:

    4613937818241073152
    0x4008000000000000