x86-64 上检查指针范围是不是跨越 N 字节对齐地址的最快方法?

Posted

技术标签:

【中文标题】x86-64 上检查指针范围是不是跨越 N 字节对齐地址的最快方法?【英文标题】:Fastest method on x86-64 to check if pointer range straddles an N byte aligned address?x86-64 上检查指针范围是否跨越 N 字节对齐地址的最快方法? 【发布时间】:2012-09-04 22:03:26 【问题描述】:

给定一个指向 T 的指针,我想确定 T 是否跨越 N 字节对齐的地址。在实践中,我真的只关心 0-5 字节大小的对象是跨越 8 字节还是 16 字节边界,但我写了这个通用版本:

template<class T, unsigned long N>
bool straddlesBoundary(T* obj)

    unsigned long before = (unsigned long)obj & ~(N-1);
    unsigned long after  = ((unsigned long)obj + sizeof(T) - 1) & ~(N-1);
    return before != after;

基本上,将地址向下舍入到最近的 N 字节对齐地址,然后将指针增量 T 减去 1 的大小(因为在下一个边界右结束的 T 不算作跨接)并向下舍入到最近的 N 字节对齐地址,如果它们匹配,你就知道它不会跨越。

有没有更快的方法来做到这一点?这是我自己编的,不知道有没有标准检查。

编辑:注意,我假设 T 小于 N。

【问题讨论】:

好吧,#define ~(N-1) BA 并相应地替换会有所帮助。 你为什么在乎?您是否测量过程序的性能并发现这是一个瓶颈? @MikeSeymour N 在编译时是已知的,所以这样做不会为您节省一些计算吗?或者任何编译器都会自动优化它? @MattPhillips:对不起,“什么?”,我的意思是“你是什么意思?”。 ~(N-1) 不是有效的宏名称,即使是,用未定义的名称替换它只会使编译失败。如果您的意思是将出现的~(N-1) 替换为BA,然后添加#define BA ~(N-1) 以使预处理器撤消更改,那么您将在预处理后得到相同的代码。无论如何,~(N-1)N 一样是编译时常量,因此无需尝试优化该计算。 @MikeSeymour Doh!!大声笑是的,那只是一个错字。不要经常使用#defines。我的意思是在编译时将~(N-1) 替换为BA。您的其他意见已得到适当记录。 【参考方案1】:

你可以这样做:

unsigned long offset = (unsigned long)obj & (N-1);
return offset > N - sizeof(T);

(与您一样,此代码仅在 N 是 2 的幂时才有效。)

【讨论】:

哦,呵呵。这绝对更好:) 我会等一会儿检查是否接受,看看是否有其他答案进来...... @JosephGarvin:如果您可以使用 std::uintptr_t from &lt;cstdint&gt;,您应该使用它。 现在我再看一遍,我认为它不正确。 'offset' 将是一个大指针地址,只有一些底部位清零。我想你的意思是“offset = obj - ((unsigned long)obj & ~(N-1))”?那还是去掉“~”? @AntoineMathys: true,但前提是 N 是编译时常量。

以上是关于x86-64 上检查指针范围是不是跨越 N 字节对齐地址的最快方法?的主要内容,如果未能解决你的问题,请参考以下文章

在 x86-64 上,32 位应用程序是不是比 64 位应用程序有性能优势?

Linux x86-64 上物理内存中的用户空间和内核之间是不是存在显式拆分?

X86-64 汇编学习1

X86-64 汇编学习1

X86-64 汇编学习1

如果 x86-64 中没有兼容模式开关,我是不是保证不会遇到非 64 位指令?