简体   繁体   中英

How can one store a uint64_t in an array?

I am trying to store a uint64_t representation of a crc64 checksum as an array.

The checksum will always be like uint64_t res = 0x72e3daa0aa188782 , so the I want that to be stored as an array, char digest[8] , where digest[0] is 72, digest[1] is e3... digest[7] is 82.

I attempted looping/dividing to break up the number, but that would be more appropriate if it was a smaller integer, and if the starting point was Base-10, as the starting point is Base-16, the output should but what is described above.


Update: I removed the nonsensical code and wish I can accept all three answers, as they all did what I asked. The bit shifting is what I was hoping to get as an answer so it is why it is accepted.

You should use division by 256, not by 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 

Shifting and bit-wise AND can also do what you need. For instance

unsigned char digest[8];
int shift = 56;
for (int i = 0; i < 8; ++i)
{
    digest[i] = (res >> shift) & 0xff;
    shift -= 8;
}

If it's okay to change the value of res another approach is:

for (int i = 7; i >= 0; --i)
{
    digest[i] = res & 0xff;
    res >>= 8;
}

Obviously if you divide by 10 you'll get the decimal digits instead of what you expected. In this case you just want to get the underlying bits of uint64_t which can be done with a simple memcpy . But you're expecting the bytes in big endian order so you'll also need to convert to big endian first

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);

In C it can also be done with a union

union Digest
{
    uint64_t res;
    char bytes[8];
} digest;
digest.res = htonll(0x72e3daa0aa188782ull); // or htobe64
// now just use digest.bytes[]

These need only a few machine instructions, hence would be far faster than looping 8 times just to get the 8 bytes

I think you can just use a union here.

union foo {
    uint64_t u64;
    uint8_t u8[8];
};

This saves you from having to do any conversion. You can access the 64-bit value using foo.u64 or the 8-bit values using foo.u8[0] to foo.u8[7] .

try this:

#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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM