Comparison of Unsigned bit field value with signed values
(move my remark as an answer)
gcc promotes s.bit
to an int, so (negVal > s.bit)
does (-3 > 0)
valuing 0
See Should bit-fields less than int in size be the subject of integral promotion? but your question is not a duplicate of it.
(negVal > p)
returns 1 because negVal is promoted to unsigned producing a big value, see Signed/unsigned comparisons
For illustration, the following uses a 32-bit int
and a 32-bit unsigned int
.
In negVal > p
:
negVal
is anint
with value −3.p
is anunsigned int
with value 123.- C 2018 6.5.8 3, which is discusses
>
and the other relational operators, tells us that the usual arithmetic conversions are performed on the operands. - 6.3.1.8 1 defines the usual arithmetic conversions. For integer types, the first step of the usual arithmetic conversions is to perform the integer promotions on each operand.
- 6.3.1.1 2 defines the integer promotions.
int
,unsigned int
, and integer types wider than these are unchanged. For other integer types, it says: ”If anint
can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to anint
; otherwise, it is converted to anunsigned int
.” - Since
negVal
is anint
, it is unchanged by the integer promotions. - Since
p
is anunsigned int
, it is unchanged by the integer promotions. - The next step in the usual arithmetic conversions is to convert one operand to the type of the other. For
int
andunsigned int
, theint
is converted tounsigned int
. - Converting the
int
−3 tounsigned int
results in 4,294,967,293. (The conversion is defined to add or subtractingUINT_MAX + 1
, which is 4,294,967,296, to the value as many times as necessary to bring it in range. This is equivalent to “wrapping” modulo 4,294,967,296 or to reinterpreting the two’s complement representation of −3 as anunsigned int
.) - After the conversions, the expression
negVal > p
has become4294967293u > 123u
. - This comparison is true, so the result is 1.
In negVal > s.bit
:
negVal
is anint
with value −3.s.bit
is a one-bit bit-field with value 0.- As above, the usual arithmetic conversions are performed on the operands.
- As above, the first step of the usual arithmetic conversions is to perform the integer promotions on each operand.
- Since
negVal
is anint
, it is unchanged by the integer promotions. - Since
s.bit
is a bit-field narrower than anint
, it will be converted by the integer promotions. This one-bit bit-field can represent either 0 or 1. Both of these can be represented by anint
, and therefore the rule “If anint
can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to anint
” applies. - Converting 0 to
int
results in 0. - The next step in the usual arithmetic conversions would be to convert one operand to the type of the other. Since both operands are now
int
, no conversion is needed. - After the conversions, the expression
negVal > s.bit
has become-3 > 0
. - This comparison is false, so the result is 0.