tomslu tomslu -4 years ago 92
C Question

Signed bit field represantation

I made a bit field with a field sized 1 bit, and used

int
instead of
unsigned
. Later on when i tried to check the value of the field i found that the value was -1.
I used this code to check the binary represantation and the value of my bit field:

#include <stdio.h>
#include <stdlib.h>

union {
struct {
int bit:1;
} field;
int rep;
} n;

int main() {

int c, k;
n.field.bit=1;
for (c = 31; c >= 0; c--)
{
k = n.rep >> c;

if (k & 1)
printf("1");
else
printf("0");
}

printf("\n %d \n", n.field.bit);

return 0;
}


the output was:
00000000000000000000000000000001

-1

In that case, why is the value of my bit field is -1 and is it always be a negative number when i use signed int instead of unsigned ?

Answer Source

You shouldn't ever use plain int as the bitfield type if you're expecting something about the value besides that it can hold n bits - according to the C11 standard it is actually implementation-defined whether int in a bit-field is signed or unsigned 6.7.2p5:

5 Each of the comma-separated multisets designates the same type, except that for bit-fields, it is implementation-defined whether the specifier int designates the same type as signed int or the same type as unsigned int.

In your case the int designates the same type as signed int; this is the default in GCC:

Whether a “plain” int bit-field is treated as a signed int bit-field or as an unsigned int bit-field (C90 6.5.2, C90 6.5.2.1, C99 and C11 6.7.2, C99 and C11 6.7.2.1).

By default it is treated as signed int but this may be changed by the -funsigned-bitfields option.

Then it is implementation defined whether the signed numbers are in one's complement, or two's complement - if they're in one's complement, then the only value that can be stored in 1 bit is the sign bit, thus 0; so signed bit field of one bit doesn't make sense on one's complement. However, your system uses 2's complement - this is e.g. what GCC always uses:

Whether signed integer types are represented using sign and magnitude, two’s complement, or one’s complement, and whether the extraordinary value is a trap representation or an ordinary value (C99 and C11 6.2.6.2).

GCC supports only two’s complement integer types, and all bit patterns are ordinary values.

and thus the bit values 1 and 0 are interpreted in terms of signed two's complement numbers: the former has sign bit set, so it is negative (-1) and the latter doesn't have a sign bit set so it is non-negative (0).

Thus for a signed bit-field of 2 bits, the possible bit patterns and their integer values on a 2's complement machine are

  • 00 - has int value 0
  • 01 - has int value 1
  • 10 - has int value -2
  • 11 - has int value -1

In an n-bit-field, the minimum signed number is - 2^(n - 1) and the maximum is 2^(n-1) - 1.

Now, when arithmetic is performed on a signed integer operand whose rank is less than int, it is converted to an int first, and thus the value -1 is sign-extended to full-width int; the same happens for default argument promotions; the value is sign-extended to a (full-width) int when it is passed in to printf.

Thus if you expect a sensible value from one bit bitfield, use either unsigned bit: 1; or alternatively if this is to be understood as a boolean flag, _Bool bit: 1;

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download