C语言中对整数1按位取反得-2而非4294967294,如何获取目标值?
C语言位取反操作的疑问与解决
这是HackerRank的一道新手题,要求对32位表示的long类型数值进行位翻转并返回结果。例如,1的32位二进制为00000000 00000000 00000000 00000001,使用~操作符按位取反后应为11111111 11111111 11111111 11111110,对应数值4294967294,但实际得到的是-2。
尝试的代码:
long flippingBits(long n) { unsigned long m = n; unsigned long x = ~n; return x; }
结果仍为-2,仅用long类型或强制转换也无效。改用异或操作后成功:
long flippingBits(long n) { unsigned long m = n; unsigned long x = n ^ 4294967295; return x; }
为什么~1得到的是-2而非4294967294?
- C语言中整数默认是有符号类型,
1作为int(通常为32位),按位取反后得到的二进制是11111111 11111111 11111111 11111110。在补码表示的有符号整数规则里,最高位是符号位,1代表负数,将补码转原码需要取反加1,得到00000000 00000000 00000000 00000010,对应数值2,加上符号就是-2。 - 你的代码中
~n操作的是long类型的n,如果long是64位有符号类型,取反后会得到64位的全1(仅最低位为0),转换为有符号数时会被解释为-2,而你期望的是32位无符号的结果,直接返回会被当作有符号数处理,所以输出-2。
如何让~操作符返回4294967294?
要实现需求,需确保取反操作针对32位无符号整数,并正确处理类型转换:
- 使用标准32位无符号类型转换(需包含
<stdint.h>):
#include <stdint.h> long flippingBits(long n) { uint32_t unsigned_32 = (uint32_t)n; uint32_t flipped = ~unsigned_32; return (long)flipped; }
- 手动用掩码截断为32位无符号值:
long flippingBits(long n) { unsigned long flipped = ~n; // 4294967295即0xFFFFFFFF,保留低32位 flipped &= 4294967295UL; return (long)flipped; }
- 你之前的异或方法有效,是因为
4294967295是32位全1的无符号数,异或操作等价于对低32位按位取反,且无符号类型计算的结果不会被解释为负数,转换为long时自然得到正确的正数。
内容的提问来源于stack exchange,提问作者Coder88
相关产品推荐
相关产品推荐

