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
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.