如何确定32位/ 64位值是否具有某个16位值?

时间:2015-08-19 16:15:23

标签: c++ c bit-manipulation

问题

考虑以下32位和64位值:

  uint32_t iVal32 = 0x AB CD 12 34;
  uint64_t iVal64 = 0x AB CD 12 34 56 78 CA BE;
  1. 如何确定iVal32是否包含某个16位(字)值? 让我们说0xCD12
  2. 如何确定iVal64是否包含某个16位(字)值? 让我们说0x3456
  3. 更新1(稍后添加)

    • 0xCD12 要检查的字值可能位于每个字边界iVal32的任意位置。
    • 0x3456 要检查的字值可能位于每个字边界iVal64的任意位置。

    更新2(稍后添加)

    我承认这个问题存在一个荒谬的错误。在我之前的示例中,要检查的单词值不在iVal32iVal64的单词边界中。因此,我的更正是:

    • 对于iVal32,要检查的字词值可以是0xABCD0x1234。因此,例如,0xCD12中找不到iVal32
    • 对于iVal64,要检查的字词值可以是以下之一:0xABCD0x12340x56780xCABE。因此,例如,0xCD12中找不到0x34560x78CAiVal64

    说明

    • 解决方案旨在用于在Unicode字符串中搜索16位字符的函数中。在x86中,该函数一次读取两个字符;在x64中,该函数一次读取四个字符。
    • 我问这个是因为我注意到glibc strchr()(适用于8位字符)的实现尝试一次测试一个长字,但我并不能很好地理解代码。 / LI>

4 个答案:

答案 0 :(得分:1)

if

答案 1 :(得分:1)

不完全清楚OP想要的是什么,但是给出了描述和后续评论,其中包含以下内容:

#include <iostream>
#include <stdint.h>
using namespace std;

bool contains(uint16_t item, uint32_t source);
bool contains(uint16_t item, uint64_t source);

int main()
{
    uint32_t iVal32 = 0xABCD1234;
    uint64_t iVal64 = 0xABCD12345678CABELL;

    cout << contains(0x1234, iVal32) << endl;
    cout << contains(0xABCD, iVal32) << endl;

    cout << contains(0xABCD, iVal64) << endl;
    cout << contains(0x1234, iVal64) << endl;
    cout << contains(0x5678, iVal64) << endl;
    cout << contains(0xCABE, iVal64) << endl;   
    return 0;
}

bool contains(uint16_t item, uint32_t source)
{
    for (int i = 16 ; i >= 0 ; i -= 16)
    {
        if (((source << i) >> 16) == item)
        {
           return true;
        }    
    }
    return false;
}

bool contains(uint16_t item, uint64_t source)
{
    for(int i = 48 ; i >= 0 ; i -= 16)
    {
        if (((source << i) >> 48) == item)
        {
            return true;
        }
    }
    return false;
}

答案 2 :(得分:1)

这是32位的可能解决方案。 -1返回32位值中16位值的位位置, 如果32位值不包含16位值,则为#include <stdio.h> #include <stdint.h> uint32_t iVal32 = 0xABCD1234; uint64_t iVal64 = 0xABCD12345678CABE; int find_pos(uint32_t value, uint16_t pattern) { int i; for (i = 0; i < 32; i+=4) { uint32_t v = (value & (0xFFFF << i)); uint32_t p = (pattern << i); if (v == p) return i; } return -1; } int main () { printf("i = %i\n", find_pos(iVal32, 0xCD12)); return 0; }

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

uint32_t iVal32 = 0xABCD1234;
uint64_t iVal64 = 0xABCD12345678CABE;

#define find_pos(value, pattern, width)             \
({                                                  \
    int i;                                          \
    int found = 0;                                  \
                                                    \
    for (i = 0; i < width; i+=4) {                  \
        typeof(value) v = (value & (0xFFFF << i));  \
        typeof(value) p = (pattern << i);           \
        if (v == p) {                               \
            found = 1;                              \
            break;                                  \
        }                                           \
    }                                               \
                                                    \
    if (!found)                                     \
        i = -1;                                     \
    i;                                              \
})

#define find_pos32(value, pattern) \
    find_pos(value, pattern, 32)

#define find_pos64(value, pattern) \
    find_pos(value, pattern, 64)

int main ()
{
    printf("i = %i\n", find_pos32(iVal32, 0xCD12));
    printf("i = %i\n", find_pos64(iVal64, 0x678C));

    return 0;
}

<强>更新

以下是使用宏的32位和64位的可能解决方案。

{{1}}

答案 3 :(得分:1)

David的回答略有不同,非分支。

bool contains (uint32_t haystack, uint16_t needle)
{
    uint32_t h1 = (haystack ^ needle) & 0xFFFF;
    haystack >>= 16;
    uint32_t h2 = haystack ^ needle; // No need for mask.
    // If and only if needle was in haystack, h1 or h2 will now be 0
    return (h1*h2) == 0;
}

两个XOR,一个移位,一个掩码,一个乘法和一个可能是免费的比较。只需要3个寄存器。 x64的明显扩展计算h1*h2*h3*h4,但计算正在运行的产品可能更有效,因此我们不需要4个中间结果的寄存器。 (一个不错的优化器也会这样做)。

由于没有快捷方式评估,这有时可能需要更多指示,但缺乏快捷方式评估也意味着没有分支。我敢打赌,对于字符串搜索,这是一个净胜利。

有点偏离主题,问题提到了x86。 SSE是那里的逻辑选项,特别是对于64位。