Adding a variable in char array in hex

53 Views Asked by At

So I am currently working on project and I need to make a hex array which I later send over serial. This hex array has some fixed parts, for example it begins with F0 always but in the middle I need to have variable data. What would be the easiest way to add variables to this hex array?

Here is a rough example of what I want to do:

F0 (2 byte long variable) (1 byte variable) (4 byte long variable) 0F

Example:

F0 00 01 FF 00 00 00 01 0F

So ideally this is something im looking for: unsigned char data[] = {0xF0,Data1,Data2,Data3,0x0F};

2

There are 2 best solutions below

1
MikeCAT On

Assuming the stream uses the same endianness as the machine sending the data, you can copy data in variables using memcpy() function.

#include <stdio.h> /* printf */
#include <string.h> /* memcpy */
#include <stdint.h> /* uint8_t, uint16_t, uint32_t */

int main(void) {
    /* prepare data */
    /* assuming little endian */
    uint16_t Data1 = UINT16_C(0x0100);
    uint8_t Data2 = UINT8_C(0xff);
    uint32_t Data3 = UINT32_C(0x01000000);

    /* copy data */
    unsigned char data[1 + 2 + 1 + 4 + 1];
    data[0] = 0xf0;
    memcpy(data + 1, &Data1, 2);
    memcpy(data + 3, &Data2, 1);
    memcpy(data + 4, &Data3, 4);
    data[8] = 0x0f;

    /* check data */
    for (int i = 0; i < 9; i++) {
        printf("%02X ", data[i]);
    }
    putchar('\n');

    return 0;
}
1
gulpr On

Here you have a universal function which will form your array not depending on the machine's endianness

typedef enum 
{
    BIG_END,
    LITTLE_END,
}endian_t;

size_t put16(void *arr, const unsigned short var1, const endian_t endianess)
{
    unsigned char *uca = arr;
    if(endianess == LITTLE_END) {uca[0] = var1 & 0xff; uca[1] = (var1 >> 8) & 0xff;}
    else {uca[1] = var1 & 0xff; uca[0] = (var1 >> 8) & 0xff;}
    return 2;
}

size_t put32(void *arr, const unsigned long var1, const endian_t endianess)
{
    unsigned char *uca = arr;
    if(endianess == LITTLE_END) 
    {
        uca[0] = var1 & 0xff; uca[1] = (var1 >> 8) & 0xff; 
        uca[2] = (var1 >> 16) & 0xff; uca[3] = (var1 >> 24) & 0xff;
    }
    else 
    {
        uca[3] = var1 & 0xff; uca[2] = (var1 >> 8) & 0xff; 
        uca[1] = (var1 >> 16) & 0xff; uca[0] = (var1 >> 24) & 0xff;
    }
    return 4;
}

void *formArray(void *arr, const unsigned short var1, const unsigned char var2, const unsigned long var3, const endian_t endianess)
{
    unsigned char *uca = arr;

    *uca++ = 0xf0;
    uca += put16(uca, var1, endianess);
    *uca++ = var2;
    uca += put32(uca, var3, endianess);
    *uca = 0x0f;
    return arr;
}

https://godbolt.org/z/14oWYsKzj

Compilers are very good in optimizing it:

put16:
        mov     eax, esi
        xchg    al, ah
        dec     edx
        cmovne  esi, eax
        mov     eax, 2
        mov     WORD PTR [rdi], si
        ret
put32:
        mov     eax, esi
        dec     edx
        bswap   eax
        cmove   eax, esi
        mov     DWORD PTR [rdi], eax
        mov     eax, 4
        ret