You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

线性地址目录位与页位提取的位掩码使用问题

问题成因

((1 << x) -1) << y生成的是对齐到原始比特位置的掩码,和目标地址做按位与操作,仅能实现「清零所有非目标区间比特位」的效果,不会改变目标比特位所在的位置。
提取偏移量时能得到正确结果,是因为偏移量的起始位y=0,按位与后目标位段天然处于最低位,不需要额外移位就能得到纯数值。提取目录、页这类高位段时,按位与得到的结果保留了目标位段的原始位置,低位全补0,本质是「目标位段数值左移y位」的结果,自然不是预期的纯位段值。
另外原代码的目录位段掩码参数也有误:32位地址的22~31位共10个连续比特,x应该取10,不是9。

正确实现方式

提取连续比特位段需要两个步骤:

  1. 用对齐掩码和地址做按位与,清零所有非目标位
  2. 将按位与的结果右移y位,把目标位段平移到最低位,得到纯数值

三个位段的正确实现代码如下:

#include <stdint.h>
#include <stdio.h>

// 偏移量:0~11位,共12位,起始位y=0
#define GET_OFFSET(addr) (((addr) & (((1u << 12) - 1) << 0)) >> 0)
// 页位段:12~21位,共10位,起始位y=12
#define GET_PAGE(addr)   (((addr) & (((1u << 10) - 1) << 12)) >> 12)
// 目录位段:22~31位,共10位,起始位y=22
#define GET_DIR(addr)    (((addr) & (((1u << 10) - 1) << 22)) >> 22)

int main(void)
{
    uint32_t addr = 0x12345678;
    printf("dir: %#x, page: %#x, offset: %#x", 
        GET_DIR(addr), 
        GET_PAGE(addr), 
        GET_OFFSET(addr));
    // 输出:dir: 0x48, page: 0x345, offset: 0x678
    return 0;
}

注意事项

所有移位操作必须使用无符号整数类型,避免有符号数算术右移时补符号位,导致结果错误。

内容的提问来源于stack exchange,提问作者Daniel Shwa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 23:36:08