Search code examples
c++cstructbit-fields

c bitfields strange behaviour with long int in struct


i am observing strange behaviour when i run the following code. i create a bitfield by using a struct, where i want to use 52 bits, so i use long int. The size of long int is 64 bits on my system, i check it inside the code. Somehow when i try to set one bit, it alwas sets two bits. one of them is the one i wanted to set and the second one is the index of the first one plus 32. Cann anybody tell me, why is that?

#include <stdio.h>

typedef struct foo {
  long int x:52;
  long int:12;
};

int main(){
  struct foo test;
  int index=0;
  printf("%ld\n",sizeof(test));
  while(index<64){
    if(test.x & (1<<index))
      printf("%i\n",index);
    index++;
  }
  test.x=1;
  index=0;
  while(index<64){
    if(test.x & (1<<index))
      printf("%i\n",index);
    index++;
  }
  return 0; 
}

Sry forgot to post the output, so my question was basicly not understandable... The Output it gives me is the following:

8

0

32


Solution

  • index is of type int, which is probably 32 bits on your system. Shifting a value by an amount greater than or equal to the number of bits in its type has undefined behavior.

    Change index to unsigned long (bit-shifting signed types is ill-advised). Or you can change 1<<index to 1L << index, or even 1LL << index.

    As others have pointed out, test is uninitialized. You can initialize it to all zeros like this:

     struct foo test = { 0 };
    

    The correct printf format for size_t is %zu, not %ld.

    And it wouldn't be a bad idea to modify your code so it doesn't depend on the non-portable assumption that long is 64 bits. It can be as narrow as 32 bits. Consider using the uint_N_t types defined in <stdint.h>.

    I should also mention that bit fields of types other than int, unsigned int, signed int, and _Bool (or bool) are implementation-defined.