Search code examples
carraysuint8t

How to copy uint8_t array in char array in c


I would copy a uint8_t array in a char array. I tried different solutions with: cast, memcopy, strcpy... but it does not work!!! My little example is:

uint32_t num = 123456789;
printf("\n num: %"PRIu32 "\n", num);
uint32_t x;
uint8_t a[4];
char b[4];

num=htonl(num);

a[0]=num;
a[1]=num>>8;
a[2]=num>>16;
a[3]=num>>24;

b[0] = a[0];
b[1] = a[1];
b[2] = a[2];
b[3] = a[3];



printf("\nA: %x %x %x %x", a[0],a[1],a[2],a[3]);
printf("\nB: %x %x %x %x", b[0],b[1],b[2],b[3]);


x= b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24;

x=ntohl(x);
printf("\n x vale: %"PRIu32 "\n", x);
}

The prints are:

num: 123456789
A: 7 5b cd 15
B: 7 5b ffffffcd 15
x: 123457023

Why I get a differente number in x?


Solution

  • You have to modify your code a little to be sure to handle some undefined behavior, such as signed int value overflow.

    #include <stdio.h>
    #include <stdint.h>
    #include <inttypes.h>
    #include <arpa/inet.h>
    
    int main()
    {
        uint32_t num = 123456789;
        printf("\n num: %" PRIu32 "\n", num);
        uint32_t x;
        uint8_t a[4];
        unsigned char b[4];
    
        num=htonl(num);
    
        a[0] = num & 0x000000FFu;
        a[1] = (num & 0x0000FF00u) >> 8;
        a[2] = (num & 0x00FF0000u) >>16;
        a[3] = (num & 0xFF000000u) >>24;
    
        b[0] = a[0];
        b[1] = a[1];
        b[2] = a[2];
        b[3] = a[3];
    
    
        printf("\nA: %x %x %x %x", a[0],a[1],a[2],a[3]);
        printf("\nB: %x %x %x %x", b[0], b[1], b[2], b[3]);
    
    
        x = b[0] | (b[1] & 0x000000FFu)<<8 | (b[2] & 0x000000FFu)<<16 | (b[3] & 0x000000FFu)<<24;
    
        x = ntohl(x);
    
        printf("\n x vale: %" PRIu32 "\n", x);
    
        return 0;
    }
    

    As you can see:

    1. b array is declared as unsigned char to avoid undefined behavior. It also correct values printed by 3rd printf in your code.
    2. Inserting value into a array it is more clear if you mask bits you want to move before shift them in the correct position.
    3. When you calculate x value you are performing left shift on 8 bit variables. So you are loosing all bits after 8 shift. &ing them with a 32 bit HEX literal you can be sure to use the correct size for bit shift and for ors

    About point 3, as @2501 pointed out, you must use u for literals to be sure to avoid UB on platform where int has a size smaller than 32 bts or where signed int has trap values. See 6.4.4.1. p5 of standard.