Как скопировать массив uint8_t в массив char в c

Я бы скопировал массив uint8_t в массив char. Я пробовал разные решения с: cast, memcopy, strcpy... но это не работает!!! Мой маленький пример:

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);
}

Отпечатки:

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

Почему я получаю другое число в х?

2 ответа

Решение

Вы должны немного изменить свой код, чтобы быть уверенным, что он будет обрабатывать неопределенное поведение, такое как signed int переполнение значения.

#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;
}

Как вы видете:

  1. b массив объявлен как unsigned char чтобы избежать неопределенного поведения. Также корректируются значения, напечатанные 3-м printf в вашем коде.
  2. Вставка значения в a Для массива более понятно, если вы маскируете биты, которые хотите переместить, прежде чем сдвинуть их в правильное положение.
  3. Когда вы рассчитываете x значение, которое вы выполняете влево 8 bit переменные. Таким образом, вы теряете все биты после 8 смен. и с их 32 bit HEX literal Вы можете быть уверены, что используете правильный размер для сдвига битов и для ors

Что касается пункта 3, как указывает @2501, вы должны использовать u для литералов, чтобы избежать UB на платформе, где int имеет размер меньше 32 бит или где подписанный int имеет значения ловушки. См. 6.4.4.1. р5 стандарт.

Я не понимаю, почему звонок memcpy не должно работать. Просто проверьте CHAR_BIT == 8 чтобы быть уверенным char определяется как 8-битный тип (некоторые реализации определяют char быть 16 бит большой), а затем позвонить memcpy(b, a, sizeof(b) / sizeof(b[0])), Это должно к подвоху. Не забудьте включить string.h за memcpy а также limits.h за CHAR_BIT,


Как уже отмечали другие, у вас все еще могут возникнуть проблемы с подписанием char также определена реализация. Поэтому вы должны объявить b как unsigned char предотвратить неопределенное поведение.

Чтобы сэкономить 100%, вы также должны проверить, что a а также b имеют одинаковый размер, чтобы не было ошибок времени выполнения.

Другие вопросы по тегам