Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C: Converting unsigned char array to signed int (vice versa)

Tags:

arrays

c

I'm trying to convert an unsigned char array buffer into a signed int (vice versa).

Below is a demo code:

int main(int argv, char* argc[])
{
    int original = 1054;
    unsigned int i = 1054;
    unsigned char c[4];
    int num;

    memcpy(c, (char*)&i, sizeof(int));

    //num  = *(int*) c;                          // method 1 get
    memcpy((char *)&num, c, sizeof(int));        // method 2 get
    printf("%d\n", num);

    return 0;
}

1) Which method should I use to get from unsigned char[] to int?

method 1 get or method 2 get? (or any suggestion)

2) How do I convert the int original into an unsigned char[]?

I need to send this integer via a buffer that only accepts unsigned char[]

Currently what i'm doing is converting the int to unsigned int then to char[], example :

int g = 1054;
unsigned char buf[4];
unsigned int n;
n = g;
memcpy(buf, (char*)&n, sizeof(int));

Although it works fine but i'm not sure if its the correct way or is it safe?

PS. I'm trying to send data between 2 devices via USB serial communication (between Raspberry Pi & Arduino)

like image 610
Doe Joe Avatar asked Mar 14 '23 03:03

Doe Joe


2 Answers

Below approach will work regardless of endianness on machines (assuming sizeof(int)==4):

unsigned char bytes[4];
unsigned int n = 45;

bytes[3] = (n >> 24) & 0xFF;
bytes[2] = (n >> 16) & 0xFF;
bytes[3] = (n >> 8) & 0xFF;
bytes[0] = n & 0xFF;

Above code converts integer to byte array in little endian way. Here is link also with more information.

For reverse operation, see the answers here.

The approach you have with memcpy may give different results on different computers. Because memcpy will copy whatever is there in source address to destionation, and depending if computer is little endian or big endian, there maybe a LSB or MSB at the starting source address.

like image 143
Giorgi Moniava Avatar answered Apr 28 '23 07:04

Giorgi Moniava


You could store both int (or unsigned int) and unsigned char array as union. This method is called type punning and it is fully sanitized by standard since C99 (it was common practice earlier, though). Assuming that sizeof(int) == 4:

#include <stdio.h>

union device_buffer {
    int i;
    unsigned char c[4];
};

int main(int argv, char* argc[])
{
    int original = 1054;

    union device_buffer db;
    db.i = original;

    for (int i = 0; i < 4; i++) {
        printf("c[i] = 0x%x\n", db.c[i]);
    }
}

Note that values in array are stored due to byte order, i.e. endianess.

like image 23
Grzegorz Szpetkowski Avatar answered Apr 28 '23 06:04

Grzegorz Szpetkowski