关于《A book on C》中提取32位表达式间隔位函数的疑问
解答《A book on C》第7章第6题的两个疑问
我来帮你拆解这两个疑问,这类底层位操作题确实容易因为表述模糊让人困惑:
1. 「extract every other bit position」的具体含义
这个表述的标准理解是:从32位值中每隔一位提取一个比特,最终将这16个提取出的比特按原顺序组成一个16位结果。通常有两种常见的提取规则(题目没明确的话,一般默认取奇数索引位,这里的索引从0开始,bit0是最低位):
举你给出的32位例子:00000001 00000000 00000000 10011110(对应十六进制0x10009E)
- 如果提取所有奇数索引位(bit31, bit29, bit27,..., bit1):
逐个提取对应位置的比特:
bit31=0, bit29=0, bit27=0, bit25=0, bit23=0, bit21=0, bit19=0, bit17=1
bit15=0, bit13=0, bit11=0, bit9=0, bit7=1, bit5=0, bit3=1, bit1=1
把这些比特按顺序拼接成16位,结果就是00000001 00001011(十六进制0x10B,十进制267) - 如果是提取偶数索引位(bit30, bit28,..., bit0):
提取后得到的比特是:
bit30=0, bit28=0,..., bit16=0;bit14=0,..., bit8=0;bit6=0, bit4=1, bit2=1, bit0=0
拼接结果是00000000 00001100(十六进制0x0C,十进制12)
一般这类题目默认取奇数索引位(高位方向的每隔一位),你可以结合上下文或者后续测试用例验证。
2. 兼容16位(2字节)字长机器的处理方式
16位机器的核心限制是:原生int类型只有16位,无法直接存储32位值。解决这个矛盾的思路是用两个16位变量模拟32位值,拆分处理后再合并结果:
- 把32位输入拆成高16位和低16位两个部分,用两个
unsigned int(16位)存储 - 分别对高16位和低16位执行“提取每隔一位”的操作:
比如对16位值提取奇数位,可以用位掩码0xAAAA(二进制1010101010101010)与操作,然后右移1位,得到8位结果 - 把高16位处理后的8位结果左移8位,和低16位处理后的8位结果做或操作,最终得到16位的返回值
举个适配16位机的代码思路:
unsigned short extract_32bit(unsigned short high, unsigned short low) { // 处理高16位:提取奇数位,右移1位得到8位 unsigned short high_part = (high & 0xAAAA) >> 1; // 处理低16位:提取奇数位,右移1位得到8位 unsigned short low_part = (low & 0xAAAA) >> 1; // 合并成16位结果 return (high_part << 8) | low_part; }
如果是在32位机上,直接用32位变量处理即可,比如用掩码0xAAAAAAAA与原数,再右移1位得到16位结果。
确实,《A book on C》的部分习题表述偏简洁,不像Kochan的书那样直白,遇到这种情况结合底层位操作的常见场景来推导就好。
内容的提问来源于stack exchange,提问作者SON TO
相关产品推荐
相关产品推荐

