Как скопировать массив 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;
}
Как вы видете:
b
массив объявлен какunsigned char
чтобы избежать неопределенного поведения. Также корректируются значения, напечатанные 3-мprintf
в вашем коде.- Вставка значения в
a
Для массива более понятно, если вы маскируете биты, которые хотите переместить, прежде чем сдвинуть их в правильное положение. - Когда вы рассчитываете
x
значение, которое вы выполняете влево8 bit
переменные. Таким образом, вы теряете все биты после 8 смен. и с их32 bit HEX literal
Вы можете быть уверены, что используете правильный размер для сдвига битов и дляor
s
Что касается пункта 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
имеют одинаковый размер, чтобы не было ошибок времени выполнения.