长期存储多个字符并恢复它们

时间:2015-04-06 16:49:44

标签: c# c++ bit-manipulation bitwise-operators

以下代码用于压缩long中的多个值。 long用作C ++ unordered_map中的键。它允许我使用带有数字的地图而不是复杂的结构和每个属性上的ifs。地图搜索尽可能高效。

DWORD tmpNo = object->room->details->No;

unsigned char compactNo = tmpNo ;

unsigned __int16 smallX = object->x;
unsigned __int16 smallY = object->y;

unsigned __int64 longCode = 0;

longCode   =    (item->code[0] << 56) |
                (item->code[1] << 48) | 
                (item->code[2] << 40) | 
                (compactNo     << 32) |
                (smallX        << 24) |
                (smallY        <<  8);

我使用的是|操作员在这里正确

要恢复这些值,我尝试了:

unsigned char c0    = key >> 56; 
unsigned char c1    = key >> 48; 
unsigned char c2    = key >> 40; 
等等,但它没有用。

是因为原始item-&gt;代码字符是字符而不是无符号字符(虽然值总是正数)?

此外,在理想的世界中,长的值将在.NET DLL中恢复。是否可以在C#中执行此操作?

3 个答案:

答案 0 :(得分:1)

C#对于8位值具有byte类型,但逻辑相似。

您的|逻辑看起来很好(除非您将smallX移动16并将smallY移至0)

答案 1 :(得分:1)

如果你给出一个完整的例子,那会有所帮助。

但假设item->code[0]是char或int(有符号或无符号),则需要在移位之前将其转换为64位类型,否则最终会出现未定义的行为和错误的答案。

这样的东西
((unsigned __int64) item->code[0]) << 56

应该更好。

答案 2 :(得分:1)

我认为 stdint.h 对于理解这种实现非常有用(大小整数非常有意义)。所以这是代码:

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

int8_t getValue8(int index, uint64_t container) {
    return (uint8_t)((container >> (index * 8)) & 0XFF);
}

void setValue8(int index, uint64_t* container, uint8_t value) {
    // get left part of container including the last byte (cleared by ~0xFF mask) to be used by value
    int shift = index * 8;
    uint64_t mask = (uint64_t) ~0xFF;
    uint64_t left = (*container >> shift) & mask;
    left = (left | value) << shift;

    // right part of container (complement)
    mask = ((uint64_t)1 << ++shift) - 1;
    uint64_t right = *container & mask;

    // update container
    *container = left | right;
}

int main() {
    uint64_t* container;    // container: can contain 8 chars (64-bit sized container)
    uint64_t containerValue = 0;
    int n = 8;              // n value must be <= 8 considering a 64-bit sized container
    uint8_t chars[n];       // eight char values to be stored

    // add/set values to container
    container = &containerValue;
    int i;
    for (i = 0; i < n; ++i) {
        chars[i] = (uint8_t)((i+1)*10);
        setValue8(i, container, chars[i]);
        printf("setValue8(%d, container, %d)\n", i, chars[i]);
    }

    // get values from container
    for (i = 0; i < n; ++i) {
        printf("getValue8(%d, container)=%d\n", i, getValue8(i, *container));
    }

    return 0;
}

代码仅使用位掩码和一些按位操作,因此您可以轻松地将其移植到C#。如果您对此有任何疑问,请询问。我希望我能提供帮助。