Как преобразовать 4-байтовый массив `char` в одну переменную типа `unsigned long`?

#c

Вопрос:

 union sUnion {
    unsigned long hex;
    float var;
};

void Testcode(void)
{
    char rdata[4] = { 0xd7, 0xa3, 0x40, 0xc1 };         // to DEC: -12.04
    char ctemp[100];

    union sUnion r;
    r.hex = 0xc140a3d7;       //<=== ??????

    sprintf(ctemp, "hex = %x, float = %f", r.hex, r.var);
}
 

Я хочу поместить данные из rdata в r.hex переменную, чтобы получить результат -12.04

Комментарии:

1. Есть sizeof (unsigned long) ли 4 в вашей системе? (Также вам, вероятно, следует сделать rdata тип элемента s unsigned char вместо char )

2. в основном r.hex = (rdata[3] << 24) | (rdata[2] << 16) | (rdata[1] << 8) | (rdata[0] << 0); .

3. Большое вам спасибо! Моя проблема решена!

4. @tehos помните, что такого рода решение, хотя легко и быстро, вызывает неопределенное поведение, и работает только, если: 1) платформа с прямым порядком байтов; 2) float является IEEE754 binary32 и sizeof(float) == 4 ; 3) sizeof(unsigned long) == 4 ; 4) CHAR_BIT == 8 (последняя может быть проигнорирован, если ваша программа будет работать только на Windows или POSIX-совместимых платформ). Таким образом, это не рекомендуется, особенно если вам приходится отправлять/получать данные по сети.

Ответ №1:

Если утверждение не выполняется, измените тип целого числа

 _Static_assert (sizeof(unsigned long) == 4, "assert1");
#define INTLENGTH sizeof(unsigned long)

//endianess independent
unsigned long covert1(void *varr, int endianness)
{
    unsigned char *arr = varr;
    unsigned long resu<

    #define MAXINDEX (INTLENGTH -1)

    if(endianess)
        result = (unsigned long)arr[0]   ((unsigned long)arr[1] << 8)   ((unsigned long)arr[2] << 16)   ((unsigned long)arr[3] << 24);
    else
        result = (unsigned long)arr[MAXINDEX - 0]   ((unsigned long)arr[MAXINDEX - 1] << 8)   ((unsigned long)arr[MAXINDEX - 2] << 16)   ((unsigned long)arr[MAXINDEX - 3] << 24);
    return resu<
}

//arr has to have seme endianness as integers
unsigned long covert(void *arr)
{
    unsigned long resu<
    memcpy(amp;result, arr, sizeof(result));
    return resu<
}