在编写代码时,我发现代码中有一件事与位域值与负整数的比较有关。
我有一个无符号的结构成员,其大小为一位,一个无符号的int。当我将负值与无符号int变量进行比较时,我得到的预期结果为1,但是当我将结构成员与负值进行比较时,得到的结果却为0。
#include <stdio.h>
struct S0
{
unsigned int bit : 1;
};
struct S0 s;
int main (void)
{
int negVal = -3;
unsigned int p = 123;
printf ("%d\n", (negVal > p)); /*Result as 1 */
printf ("%d\n", (negVal > s.bit));/*Result as 0 but expected 1 */
return 0;
}
我的疑问是,如果我将负值与unsigned int进行比较,则会发生平衡(隐式类型转换)。但是,如果我比较unsigned int的结构成员,为什么不进行隐式类型转换。如果我错过了位域的基础知识,可以纠正我吗?
答案 0 :(得分:5)
(将我的评论作为答案)
gcc 将s.bit
提升为 int ,因此(negVal > s.bit)
会(-3 > 0)
赋值为0
请参见Should bit-fields less than int in size be the subject of integral promotion?,但您的问题不是重复的问题。
(negVal > p)
之所以返回1,是因为 negVal 被提升为 unsigned 会产生较大的值,请参见Signed/unsigned comparisons
答案 1 :(得分:2)
为说明起见,以下使用32位int
和32位unsigned int
。
在negVal > p
中:
negVal
是值为{-3的int
。p
是值为{123的unsigned int
。>
和其他关系运算符的int
,unsigned int
和宽于这些整数的整数类型不变。对于其他整数类型,它表示:“如果int
可以代表原始类型的所有值(受位字段的宽度限制),则该值将转换为int
;否则,它将转换为unsigned int
。” negVal
是int
,因此整数促销没有改变。p
是unsigned int
,因此整数促销没有改变。int
和unsigned int
,int
被转换为unsigned int
。int
-3转换为unsigned int
得到4,294,967,293。 (转换的定义是,将UINT_MAX + 1
(即4,294,967,296)加到该值以使其达到范围内所需的次数,这相当于“包装”以4,294,967,296为模,或重新解释两者的补码表示形式。 −3作为unsigned int
。)negVal > p
变成了4294967293u > 123u
。在negVal > s.bit
中:
negVal
是值为{-3的int
。s.bit
是一个值为0的1位位字段。negVal
是int
,因此整数促销没有改变。s.bit
的位域比int
窄,因此它将由整数提升转换。这个一位的位字段可以表示0或1。这两个字段都可以用int
表示,因此规则“ If int
可以表示原始类型的所有值(如受宽度限制,对于位字段),该值将转换为int
”适用。int
会得出0。int
,因此不需要转换。negVal > s.bit
变成了-3 > 0
。