Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Signed bit field represetation

Tags:

c

bit-fields

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 ?

like image 427
Tom Slutsky Avatar asked Mar 01 '17 09:03

Tom Slutsky


2 Answers

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

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

like image 163

When you call a variadic argument function (like printf) some arguments are promoted. For example bit-fields undergoes an integer promotion where it is promoted to an ordinary int value. That promotion brings with it sign extension (because your base type for the bit-field is signed). This sign extension will make it -1.

When using bit-fields, almost always use unsigned types as the base.

like image 27
Some programmer dude Avatar answered Oct 03 '22 11:10

Some programmer dude