C中的按位"非"运算符返回签名结果

puc*_*chu 4 c linux gcc gnu99

考虑以下代码:

uint16_t a = ~ ( uint16_t ) 0;
int16_t  b = ~ ( int16_t ) 0;
printf (
    "%d %d %d %d\n",
    a  == ~ ( uint16_t ) 0,
    a  == ( uint16_t ) ( ~ ( uint16_t ) 0 ),
    b  == ~ ( int16_t ) 0,
    b  == ( int16_t ) ( ~ ( int16_t ) 0 )
);
Run Code Online (Sandbox Code Playgroud)

输出是:

0 1 1 1

海湾合作委员会发出警告a == ~ ( uint16_t ) 0:

由于数据类型的范围有限,比较总是假的[-Wtype-limits]

为什么按位"非"运算符尝试返回有符号值?我怎么能防止这种情况?

Mik*_*our 9

为什么按位"不"运算符试图返回有符号值?

因为没有操作员在小于的类型上工作int; 当用作操作数时,会提升较小的类型(包括uint16_tif int超过16位).如果原始类型的所有值都可以表示,就像它们在这里一样,那么促销将是.intint

我怎么能防止这种情况?

你不能; 这就是语言的运作方式.您必须将运算符的结果转换为所需的类型,或者在初始化时隐式转换,或者使用强制转换a显式转换.请注意,申请之前不需要演员表~; 但为了获得最大的可移植性,在执行按位逻辑时应该坚持使用无符号类型:

uint16_t a = ~0u;
printf("%d\n", a == (uint16_t)~0u);  // Should print 1
Run Code Online (Sandbox Code Playgroud)