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 t
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, always use unsigned types as the base.
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 assigned int
or the same type asunsigned 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 001
- has int
value 110
- has int
value -211
- has int
value -1In 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;