C语言交换无符号整数相邻比特对的代码问题排查
问题根因
交换相邻比特对的核心逻辑是正确的,错误来自掩码常量的位宽不匹配:
- 代码中使用的
0xAAAAAAAA、0x55555555是32位长度的整型常量,在通用32位int平台上会被默认判定为32位unsigned int类型。 - 32位掩码和64位
uint64_t类型的输入做位运算时,会被零扩展为64位值,此时掩码高32位全为0,直接将输入值高32位的所有比特清零,后续移位、或操作都无法保留高32位的有效计算结果,最终返回值高32位为0,和观测到的错误结果完全吻合。
修正方案
将掩码替换为64位等宽的正确值,同时添加ULL后缀显式声明常量为unsigned long long(64位无符号整型),确保掩码覆盖64位输入的全部比特位:
uint64_t bit_swap(uint64_t value) { return ((value & 0xAAAAAAAAAAAAAAAAULL) >> 1) | ((value & 0x5555555555555555ULL) << 1); }
代码逻辑说明:
0xAAAAAAAAAAAAAAAAULL:64位下所有奇数序号比特(从0开始计数,第1、3……63位)为1的掩码,与运算提取所有奇数位比特后右移1位,移动到相邻偶数位0x5555555555555555ULL:64位下所有偶数序号比特(第0、2……62位)为1的掩码,与运算提取所有偶数位比特后左移1位,移动到相邻奇数位- 两部分结果做或运算,即可得到所有相邻比特对交换完成的结果。
针对测试用例bit_swap(0x1111111111111111):输入每个字节的二进制为00010001,所有有效1都在偶数位,左移1位后每个字节变为00100010即0x22,最终返回值为0x2222222222222222,符合预期。
提示:做不同位宽无符号整数的位运算时,使用的掩码必须和目标操作数位宽一致,最好显式添加类型后缀,避免因C语言默认的整型常量类型匹配、整数提升规则引发非预期的截断、符号扩展问题。
内容的提问来源于stack exchange,提问作者FreeAntiVirus
相关产品推荐
相关产品推荐

