1

I would like to convert a 64 bit unsigned int into an array of uint8_t in C.

kimbanu27
  • 27
  • 2
  • its a nice task. please post your code so we can review and try to help. are you familiar with big/little endian and bitwise c operators ? post what you have already tried and what problems uve faced – Adam May 24 '20 at 07:04
  • A *bitfield* comes to mind... or a `union` between `uint8_t[8]` and `uint64_t` would also work. – David C. Rankin May 24 '20 at 07:06
  • What do you mean by "breaking down"? Example: If the value is 12345 (hex: 0x3039) will the array be {1, 2, 3, 4, 5} or will it be {0x30 , 0x39} or somethin different? – Support Ukraine May 24 '20 at 07:54
  • I'm surprised that this Q got 3 upvotes. SO users must be in a real good mood today – Support Ukraine May 24 '20 at 07:56

3 Answers3

2

Use a union:

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

int main(int argc, char *argv[])
  {
  union
    {
    uint64_t t_var;
    uint8_t  a_var[8];
    } u_var;

  u_var.t_var = 0x1122334455667788;

  printf("u_var.t_var = 0x%"PRIx64"\n", u_var.t_var);

  for(int i = 0 ; i < 8 ; ++i)
    printf("u_var.a_var[%d] = 0x%"PRIx8"\n", i, u_var.a_var[i]);

  return 0;
  }

which outputs

u_var.t_var = 0x1122334455667788
u_var.a_var[0] = 0x88
u_var.a_var[1] = 0x77
u_var.a_var[2] = 0x66
u_var.a_var[3] = 0x55
u_var.a_var[4] = 0x44
u_var.a_var[5] = 0x33
u_var.a_var[6] = 0x22
u_var.a_var[7] = 0x11

onlinegdb here

1

One solution is to use bitwise AND in conjunction with the bitshift operator:

#include <stdio.h>
#include <stdint.h>

int main() {
    uint64_t var = 0x1122334455667788;

    uint8_t array[8] = {
        (var & 0x00000000000000FFull) >>  0,
        (var & 0x000000000000FF00ull) >>  8,
        (var & 0x0000000000FF0000ull) >> 16,
        (var & 0x00000000FF000000ull) >> 24,
        (var & 0x000000FF00000000ull) >> 32,
        (var & 0x0000FF0000000000ull) >> 40,
        (var & 0x00FF000000000000ull) >> 48,
        (var & 0xFF00000000000000ull) >> 56
    };

    for (uint8_t i = 0; i < 8; ++i) {
        printf("%d %2.2x\n", i, array[i]);
    }

    return 0;
}
Marco
  • 7,007
  • 2
  • 19
  • 49
  • 1
    why you have answered him? we are just waiting for him to post his try! i doubt if he or she tried to solve this problem. i think in such cases we need to wait and to see if the OP did something at all – Adam May 24 '20 at 07:12
  • @Adam I wanted to comment `What have you tried?` but SO wouldn't let me and suggested to flag, downvote or move on. So I answered and moved on ;) – Marco May 24 '20 at 07:30
  • i just want to see his or her try! but i am going with you i will post an answer. since you did it with bit wise shif operator i will doit with bitfields. i wiil voteup your answer. hope you will up vote my answer as well :) – Adam May 24 '20 at 08:36
  • 4
    `(var>>0) & 0xff, ..., (var >> 24) & 0xff, ... (var >> 56) & 0xff` has simpler constants, but using a loop like `for (int i = 0; i < 8; i++) array[i] = (var >> (8 * i)) & 0xff;` is easiest to read (leaving the compiler free to choose to unroll it). – Paul Hankin May 24 '20 at 08:53
0

solving the problem with Bitfields, since bitwise shift already covered.

typedef unsigned char uint8_t;
typedef unsigned long long uint64_t; /*assuming that long long is 64 bit on your machine*/
typedef struct SPLITER{
    uint64_t Byte0 : 8;
    uint64_t Byte1 : 8;
    uint64_t Byte2 : 8;
    uint64_t Byte3 : 8;
    uint64_t Byte4 : 8;
    uint64_t Byte5 : 8;
    uint64_t Byte6 : 8;
    uint64_t Byte7 : 8;
}SPLITER;

int main()
{
    uint64_t f = 0xffffff;
    uint8_t arr[8];
    SPLITER X = {f,f>>8,f>>16,f>>24,f>>32,f>>40,f>>48,f>>56};
    /*fill array elements with the bitfields we already splited*/
    memcpy(arr, &f, 8); /*we can doit with memcpy its more ilegant and efficient*/
    
    for(uint8_t j =0; j < 8; ++j)
    {
        printf("%X\n",arr[j]); /*print the array in hex format*/
    }

    return 0;
}
Community
  • 1
  • 1
Adam
  • 2,820
  • 1
  • 13
  • 33
  • 1
    `memcpy(arr, &f, 8);` is an easier way to write this code. (Also note that `uint8_t` and `uint64_t` are defined in `stdint.h`). – Paul Hankin May 24 '20 at 08:49
  • @PaulHankin - great comment. thank you. i will fix it. hope that you find my answer useful. – Adam May 24 '20 at 08:51
  • 1
    `typedef unsigned char uint8_t;` *don't do that*, include `` instead. – chqrlie May 24 '20 at 20:09