C语言如何提取unsigned long变量的中间位段?现有写法是否正确?
结论
你的写法是错误的,且你对小端序的担忧属于误区。
原有代码的问题
- 位运算操作的是变量的逻辑数值,和内存存储的大小端序完全无关,大小端只会影响直接访问内存字节的场景,你对
addr直接做位与、位移操作不需要考虑字节序。 - 原有代码仅做了位与保留对应位段,但没有将目标位段右移到数值低位,赋值给更短的无符号类型时,超出类型宽度的高位会被直接截断,最终得到的结果就是0:
- 你给
offset_middle赋值的addr & 0xFFFF0000得到的是逻辑上左移16位的中间16位值,赋值给16位的u16时,高于16位的部分会被丢弃,最终结果为0 - 你给
offset_high赋值的addr & 0xFFFFFFFF0000得到的是逻辑上左移32位的高32位值,赋值给32位的u32时,高于32位的部分会被丢弃,最终结果为0
- 你给
正确且简洁的写法
不需要写长串的F,通过位移+低位掩码即可实现:
// 低16位直接取,掩码只需要写4个F offset_low = addr & 0xFFFFU; // 中间16位先右移16位,再取低16位 offset_middle = (addr >> 16) & 0xFFFFU; // 高32位直接右移32位,赋值给u32时会自动截断保留低32位,不需要额外加掩码 offset_high = addr >> 32;
如果完全不想写连续的F,也可以用位运算动态生成掩码:
// 通用逻辑:取addr从第shift位开始的width位 #define GET_BITS(addr, shift, width) ((addr >> shift) & ((1U << width) - 1)) offset_low = GET_BITS(addr, 0, 16); offset_middle = GET_BITS(addr, 16, 16); offset_high = GET_BITS(addr, 32, 32);
内容的提问来源于stack exchange,提问作者user15973135
相关产品推荐
相关产品推荐

