如何将 uint64_t 存储在数组中?
How can one store a uint64_t in an array?
我正在尝试将 crc64 校验和的 uint64_t
表示存储为数组。
校验和将始终类似于 uint64_t res = 0x72e3daa0aa188782
,因此我希望将其存储为数组 char digest[8]
,其中 digest[0]
为 72,digest[1]
为e3...digest[7]
是 82.
我尝试looping/dividing将数字打散,但如果它是一个更小的整数会更合适,并且如果起点是 Base-10,因为起点是 Base-16,输出应该是上面描述的内容。
更新: 我删除了无意义的代码并希望我能接受所有三个答案,因为它们都按照我的要求做了。移位是我希望得到的答案,所以这就是它被接受的原因。
你应该使用除以 256,而不是除以 10:
unsigned char digest[sizeof(uint64_t) / sizeof(char)];
for (int i = sizeof(digest) - 1; i >= 0; i--) {
digest[i] = res % 256; // get the last byte
res /= 256; // get the remainder
}
// for demo purposes
for (int i = 0; i < sizeof(digest); i++) {
printf("%x ", digest[i]);
}
// 72 e3 da a0 aa 18 87 82
我想你可以在这里使用 union
。
union foo {
uint64_t u64;
uint8_t u8[8];
};
这使您不必进行任何转换。您可以使用 foo.u64
访问 64 位值或使用 foo.u8[0]
到 foo.u8[7]
.
访问 8 位值
移位和按位AND也可以做你需要的。例如
unsigned char digest[8];
int shift = 56;
for (int i = 0; i < 8; ++i)
{
digest[i] = (res >> shift) & 0xff;
shift -= 8;
}
如果可以更改 res
的值,另一种方法是:
for (int i = 7; i >= 0; --i)
{
digest[i] = res & 0xff;
res >>= 8;
}
显然,如果您除以 10,您将得到十进制数字,而不是您预期的数字。在这种情况下,您只想获取 uint64_t
的基础位,这可以通过简单的 memcpy
来完成。但是您希望字节按大端顺序排列,因此您还需要先转换为大端
uint64_t number = 0x72e3daa0aa188782ull;
#ifdef __unix__
uint64_t number_be = htonll(number);
#else
uint64_t number_be = htobe64(number);
#endif
char digest[8];
memcpy(&digest, &number_be , sizeof number);
在 C 中也可以用联合来完成
union Digest
{
uint64_t res;
char bytes[8];
} digest;
digest.res = htonll(0x72e3daa0aa188782ull); // or htobe64
// now just use digest.bytes[]
这些只需要几条机器指令,因此比仅仅为了获得 8 个字节而循环 8 次要快得多
试试这个:
#define INIT_LIST \
201234567890123456, \
12345678901234567890, \
98765432109876543, \
65432109887, \
12345234512345, \
217631276371261627, \
12354123512453124, \
2163521442531, \
2341232142132321, \
1233432112
#define STR_(...) #__VA_ARGS__
#define STR(x) STR_(x)
int main (void)
{
uint64_t numbers[10] = { INIT_LIST };
char array[] = STR(INIT_LIST);
puts(array);
}
我正在尝试将 crc64 校验和的 uint64_t
表示存储为数组。
校验和将始终类似于 uint64_t res = 0x72e3daa0aa188782
,因此我希望将其存储为数组 char digest[8]
,其中 digest[0]
为 72,digest[1]
为e3...digest[7]
是 82.
我尝试looping/dividing将数字打散,但如果它是一个更小的整数会更合适,并且如果起点是 Base-10,因为起点是 Base-16,输出应该是上面描述的内容。
更新: 我删除了无意义的代码并希望我能接受所有三个答案,因为它们都按照我的要求做了。移位是我希望得到的答案,所以这就是它被接受的原因。
你应该使用除以 256,而不是除以 10:
unsigned char digest[sizeof(uint64_t) / sizeof(char)];
for (int i = sizeof(digest) - 1; i >= 0; i--) {
digest[i] = res % 256; // get the last byte
res /= 256; // get the remainder
}
// for demo purposes
for (int i = 0; i < sizeof(digest); i++) {
printf("%x ", digest[i]);
}
// 72 e3 da a0 aa 18 87 82
我想你可以在这里使用 union
。
union foo {
uint64_t u64;
uint8_t u8[8];
};
这使您不必进行任何转换。您可以使用 foo.u64
访问 64 位值或使用 foo.u8[0]
到 foo.u8[7]
.
移位和按位AND也可以做你需要的。例如
unsigned char digest[8];
int shift = 56;
for (int i = 0; i < 8; ++i)
{
digest[i] = (res >> shift) & 0xff;
shift -= 8;
}
如果可以更改 res
的值,另一种方法是:
for (int i = 7; i >= 0; --i)
{
digest[i] = res & 0xff;
res >>= 8;
}
显然,如果您除以 10,您将得到十进制数字,而不是您预期的数字。在这种情况下,您只想获取 uint64_t
的基础位,这可以通过简单的 memcpy
来完成。但是您希望字节按大端顺序排列,因此您还需要先转换为大端
uint64_t number = 0x72e3daa0aa188782ull;
#ifdef __unix__
uint64_t number_be = htonll(number);
#else
uint64_t number_be = htobe64(number);
#endif
char digest[8];
memcpy(&digest, &number_be , sizeof number);
在 C 中也可以用联合来完成
union Digest
{
uint64_t res;
char bytes[8];
} digest;
digest.res = htonll(0x72e3daa0aa188782ull); // or htobe64
// now just use digest.bytes[]
这些只需要几条机器指令,因此比仅仅为了获得 8 个字节而循环 8 次要快得多
试试这个:
#define INIT_LIST \
201234567890123456, \
12345678901234567890, \
98765432109876543, \
65432109887, \
12345234512345, \
217631276371261627, \
12354123512453124, \
2163521442531, \
2341232142132321, \
1233432112
#define STR_(...) #__VA_ARGS__
#define STR(x) STR_(x)
int main (void)
{
uint64_t numbers[10] = { INIT_LIST };
char array[] = STR(INIT_LIST);
puts(array);
}