Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it well-defined behavior to address a 32-bit `int` using a bitfield inside a union?

Consider the following small program, which uses a union to assign the bits of an integer directly rather than using bit operations. The print statements print correctly, but that does not mean it will always work.

Is this well-defined behavior in C?

#include <stdio.h>
#include <inttypes.h>


union IntBitField{
    int32_t foo;

    struct bitfield {
        unsigned int BIT0:1;
        unsigned int BIT1:1;
        unsigned int BIT2:1;
        unsigned int BIT3:1;
        unsigned int BIT4:1;
        unsigned int BIT5:1;
        unsigned int BIT6:1;
        unsigned int BIT7:1;
        unsigned int BIT8:1;
        unsigned int BIT9:1;
        unsigned int BIT10:1;
        unsigned int BIT11:1;
        unsigned int BIT12:1;
        unsigned int BIT13:1;
        unsigned int BIT14:1;
        unsigned int BIT15:1;
        unsigned int BIT16:1;
        unsigned int BIT17:1;
        unsigned int BIT18:1;
        unsigned int BIT19:1;
        unsigned int BIT20:1;
        unsigned int BIT21:1;
        unsigned int BIT22:1;
        unsigned int BIT23:1;
        unsigned int BIT24:1;
        unsigned int BIT25:1;
        unsigned int BIT26:1;
        unsigned int BIT27:1;
        unsigned int BIT28:1;
        unsigned int BIT29:1;
        unsigned int BIT30:1;
        unsigned int BIT31:1;
    } bar;
} FooBar;
int main(){
    FooBar.foo = 0;
    printf("Size of the union: %zu\n", sizeof(union IntBitField));
    printf("Before setting any bits %"PRId32"\n", FooBar.foo);
    FooBar.bar.BIT31 = 1; // Highest order bit
    printf("Set BIT31 %"PRId32"\n", FooBar.foo);
}

I have looked at this question and this question, as well as this question but I am still uncertain.

like image 249
merlin2011 Avatar asked Mar 14 '23 02:03

merlin2011


1 Answers

The answer is the code will always compile/run (it that sense it is "standard"), but it is not "portable" in the sense that the value of foo on the last line is not guaranteed. Different compiler implementations can store the bit fields in different bits of the memory, which is to say the memory foo references. In fact, when considering padding the bit field might not even completely overlap foo.

This is what the first answer you link to is trying to say.

like image 135
Brad Avatar answered Apr 06 '23 10:04

Brad