Search code examples
c++unionsbit-fields

Why is the size of the union greater than expected?


#include <iostream>
    typedef union dbits {
        double d;
        struct {
            unsigned int M1: 20;
            unsigned int M2: 20;
            unsigned int M3: 12;
            unsigned int E: 11;
            unsigned int s: 1;
        };
    };
    int main(){
        std::cout << "sizeof(dbits) = " << sizeof(dbits) << '\n';
    }

output: sizeof(dbits) = 16, but if

    typedef union dbits {
        double d;
        struct {
            unsigned int M1: 12;
            unsigned int M2: 20;
            unsigned int M3: 20;
            unsigned int E: 11;
            unsigned int s: 1;
        };
    };

Output: sizeof(dbits) = 8

Why does the size of the union increase?

In the first and second union, the same number of bits in the bit fields in the structure, why the different size?

I would like to write like this:

typedef union dbits {
    double d;
    struct {
        unsigned long long M: 52;
        unsigned int E: 11;
        unsigned int s: 1;
    };
};

But, sizeof(dbits) = 16, but not 8, Why? And how convenient it is to use bit fields in structures to parse bit in double?


Solution

  • members of a bit field will not cross boundaries of the specified storage type. So

            unsigned int M1: 20;
            unsigned int M2: 20;
    

    will be 2 unsigned int using 20 out of 32 bit each.

    In your second case 12 + 20 == 32 fits in a single unsigned int.

    As for your last case members with different storage type can never share. So you get one unsigned long long and one unsigned int instead of a single unsigned long long as you desired.

    You should use uint64_t so you get exact bit counts. unsigned int could e anything from 16 to 128 (or more) bit.

    Note: bitfields are highly implementation defined, this is just the common way it usually works.