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

Store multiple chars in a long and recover them

下面的代码用于将多个值压缩成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->code 字符是字符而不是无符号字符(尽管值总是正数)?

此外,在理想情况下,long 的值将在 .NET DLL 中恢复。可以在 C# 中这样做吗?

C# 有一个 8 位值的 byte 类型,但其他逻辑是相似的。

您的 | 逻辑看起来不错(除了您应该将 smallX 移动 16 并将 smallY 移动 0)

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

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

类似

((unsigned __int64) item->code[0]) << 56

应该会更好。

我认为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#。如果您对此有任何疑问,请提问。希望对您有所帮助。