为何将~0强制转换为unsigned long会得到全1位模式?
为什么
(unsigned long) ~0会得到全8字节1? 拆解整个过程的关键逻辑:
- 第一步:
0是有符号int类型(4字节),~0对其每一位取反后,二进制为11111111 11111111 11111111 11111111。按照有符号int的补码规则,这个值等价于**-1**,而非“无符号的全1值”。 - 第二步:将有符号int的
-1转换为unsigned long(8字节)时,C语言规定:有符号数转无符号数,结果为该值对2^N取模(N是目标无符号类型的总位数,此处为64)。-1 mod 2^64的结果是2^64 -1,对应十六进制就是0xFFFFFFFFFFFFFFFF——也就是全8字节的1。
你理解偏差的核心原因
你误以为~0是“4字节无符号全1值”,转换时会高位补0,但实际上~0是有符号int类型的-1,转无符号类型时遵循补码符号扩展规则,而非零扩展,最终得到全位1的结果。
如果想要得到你预期的0x00000000FFFFFFFF,可以把0声明为无符号int:
(unsigned long) ~0U
这里0U是unsigned int类型,~0U得到unsigned int的全1(值为0xFFFFFFFF),转换到unsigned long时会进行零扩展,高位补0,最终就是你想要的结果。
补充:K&R getbits函数里的~(~0 << n)
这个表达式的目的是生成低n位全1的掩码。~0作为int的-1,左移n位后得到高位全1、低n位全0的有符号int值,再取反就得到低n位全1的掩码。在当时的环境下(比如16位int),这个写法比直接写0xFFFF更通用,能适配不同的int位数。
内容的提问来源于stack exchange,提问作者Hermit
相关产品推荐
相关产品推荐

