首页 > 解决方案 > XCode 和 _bittest 函数

问题描述

我有一个为 Win32 开发的小 C++ 项目,我想将它移植到 OSX。该代码使用类似的函数_bittest_bittest64但我在 XCode 头文件中没有找到相同的函数。

这些功能有什么替代品?可能有很好的工作 polyfills。该项目确实是一个遗产,目前不需要额外的性能。

标签: c++macoswinapiportingintrinsics

解决方案


_bittest和 _bittest64符号是编译器内在函数,它们发出位测试指令,特别是x86bt,以检查从零开始的索引处的位值。

对于内存操作数,bt具有疯狂的 CISC 位串行为,其中位索引可以超出寻址模式选择的内存的 dword/qword。这很慢,也是编译器首先将操作数加载到寄存器中的原因。但这就是 MSVC 内在函数的用途。否则它不需要是内在的。

以下 C++ 匹配bt指令的 register-arg 版本的行为,将移位计数包装在寄存器宽度处,即有效地只查看低位。(如果是 <32 或 <64 ,这与 MSVC 内在相匹配。b)请参阅更新的代码和注释以讨论如何实现 MSVC 语义,使其能够在指向long或之外访问long long

还要注意它long在 x64 Windows ABI 中是 32 位类型,但在 x86-64 System V ABI 中是 64 位类型(您在 OS X 上使用它,除非您构建过时的 32 位代码)。您可能希望将代码更改为int32_tuint32_t避免在 each 中留下未使用的位long,具体取决于您使用它的方式。

inline
unsigned char bittest(long const *a, long b)
{
    auto const value{ *a };
    auto const mask{ 1L << (b&31) };
    auto const masked_value{ value & mask };
    return unsigned char{ masked_value != 0 };
}

inline
unsigned char bittest64(long long const *a, long long b)
{
    auto const value{ *a };
    auto const mask{ 1LL << (b&63) };
    auto const masked_value{ value & mask };
    return unsigned char{ masked_value != 0 };
}

我不知道任何具有相同功能的 GCC 或 Clang 内在函数。如果需要,您可以求助于从函数实现发出汇编指令,但是bt使用内存操作数很慢,因此通常最好用纯 C++ 实现并让编译器做好。

更新:

在讨论了从内部函数发出的代码之后,很明显,之前提出的替换代码只涵盖了部分功能。特别是,内在函数允许在*a. 以下实现也说明了这一点。

inline
unsigned char bittest(std::int32_t const *a, std::int32_t b)
{
    auto const bits{ reinterpret_cast<unsigned char const*>(a) };
    auto const value{ bits[b >> 3] };
    auto const mask{ (unsigned char)(1 << (b & 7)) };
    return (value & mask) != 0;
}

inline
unsigned char bittest64(std::int64_t const *a, std::int64_t b)
{
    auto const bits{ reinterpret_cast<unsigned char const*>(a) };
    auto const value{ bits[b >> 3] };
    auto const mask{ (unsigned char)(1 << (b & 7)) };
    return (value & mask) != 0;
}

推荐阅读