长期存储多个字符并恢复它们
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#。如果您对此有任何疑问,请提问。希望对您有所帮助。
下面的代码用于将多个值压缩成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#。如果您对此有任何疑问,请提问。希望对您有所帮助。