以下代码用于压缩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#中执行此操作?
答案 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#。如果您对此有任何疑问,请询问。我希望我能提供帮助。