Signed bit field represetation

You should never 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, C99 and C11 6.7.2, C99 and C11

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

Thus any sane program always specifies either signed int or unsigned int, depending on which is appropriate for the current use case.

Then it is implementation defined whether the signed numbers are in one’s complement, or two’s complement – or perhaps sign and magnitude – if they’re in one’s complement or s-and-m, then the only value that can be stored in 1 bit is the sign bit, thus 0; so signed bit field of one bit probably makes sense only with 2’s complement.

Your system seems to use 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

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;

Leave a Comment