【问题标题】:Please help me understand this bit-wise manipulation of pointer values请帮助我理解指针值的这种按位操作
【发布时间】:2011-04-26 21:42:47
【问题描述】:

我无法理解为什么 addr 被类型转换为 long,然后用表达式补充。基本上涉及 peekAddr 计算的整行

void *addr;
char *peekAddr ;
peekAddr = (char *) ((long)addr & ~(sizeof(long) - 1 ) ) ;
peekWord = ptrace( PTRACE_PEEKDATA, pid, peekAddr, NULL ) ;

【问题讨论】:

标签: c++ c bit-manipulation


【解决方案1】:
sizeof (long)     = (0)00000100
sizeof(long)-1    = (0)00000011
~(sizeof(long)-1) = (1)11111100

所以 2 位设置为 0 使地址与 4 个字节对齐。此外,它主要用于地址已经增加 sizeof(long)-1

【讨论】:

    【解决方案2】:

    它被转换为long,因为(1)你不能在void*上执行任何操作,除了转换它和(2)在作者的平台上,void*值恰好适合@ 987654324@。他真的应该改用uintptr_tsize_t

    这段代码的作用:

    sizeof(long) - 1
    

    很可能是 3 或 7,具体取决于平台。

    ~(sizeof(long) - 1)
    

    是一个位掩码,选择除最后几位之外的所有位。

    ((long)addr & ~(sizeof(long) - 1))
    

    addr 向下舍入/对齐以解决long 大小的块。舍入是因为最后 lg(3) 或 lg(7) 位为零,而其余位是从 addr 复制的(其中 lg 是整数二进制对数)。

    【讨论】:

    • 吹毛求疵:不是最后 3 位或 7 位被清除,而是低 2 位和 3 位分别被清除。 (因为 3 是 11 二进制,7 是 111 二进制。)
    • 最后一句话中没有。 :)
    • @greyfade:这有点尴尬 ;) 已修复,感谢您指出。
    【解决方案3】:

    这是一种非常丑陋、不可移植的做法

    peakAddr = (char *)addr - ((uintptr_t)addr & -(uintptr_t)sizeof(long));
    

    请注意,原始版本不仅依赖于指向long 和返回的指针的成功往返转换,还依赖于size_tsizeof 运算符的结果类型)具有相同的宽度或更宽比long。如果不是,则使用~ 生成的位掩码将在高位零扩展并删除部分指针。

    基本上,您应该记住,您在其中发现的任何程序都是错误代码,而不是将其视为想法的来源...

    【讨论】:

      【解决方案4】:

      您基本上使 peekAddr 始终与 sizeof(long) 地址对齐。该行生成一个位掩码和二进制并将其发送到 peek 地址。 该行从 peekAddr 中删除了最后一个 sizeof(long)-1 位。

      马里奥

      【讨论】:

        【解决方案5】:

        这将在某些编译器上出现错误,其中sizeof(long) < sizeof(char*),例如微软的。

        sizeof(long)-1 正在创建一个与long 的大小相对应的位掩码。这个技巧只适用于 2 的幂数。前面的 ~ 将其反转,所以现在它是所有地址位的掩码,当您尝试对齐地址时应该保持不变。按位& 正在清除地址的低位以使其对齐。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-06-15
          • 1970-01-01
          • 2013-05-10
          相关资源
          最近更新 更多