C - беззнаковое преобразование массива без знака char
У меня есть unsigned int number (2 байта), и я хочу преобразовать его в unsigned char. Из моего поиска я считаю, что большинство людей рекомендуют делать следующее:
unsigned int x;
...
unsigned char ch = (unsigned char)x;
Правильный подход? Я спрашиваю, потому что unsigned char - 1 байт, и мы передали из двух байтовых данных в 1 байт.
Чтобы предотвратить потерю данных, я хочу создать массив unsigned char [] и сохранить отдельные байты в массиве. Я застрял в следующем:
unsigned char ch[2];
unsigned int num = 272;
for(i=0; i<2; i++){
// how should the individual bytes from num be saved in ch[0] and ch[1] ??
}
Кроме того, как мы преобразуем unsigned char [2] обратно в unsigned int.
Большое спасибо.
Ответы
Ответ 1
Вы можете использовать memcpy
в этом случае:
memcpy(ch, (char*)&num, 2); /* although sizeof(int) would be better */
Также, как бы преобразовать unsigned char [2] обратно в unsigned int.
Точно так же просто измените аргументы memcpy.
Ответ 2
Как насчет:
ch[0] = num & 0xFF;
ch[1] = (num >> 8) & 0xFF;
Обратная операция остается в виде упражнения.
Ответ 3
Как насчет использования объединения?
union {
unsigned int num;
unsigned char ch[2];
} theValue;
theValue.num = 272;
printf("The two bytes: %d and %d\n", theValue.ch[0], theValue.ch[1]);
Ответ 4
Конечно, массив символов, достаточно большой, чтобы содержать большее значение, должен быть таким же большим, как и это значение.
Поэтому вы можете просто притворяться, что это большее значение уже представляет собой массив символов:
unsigned int x = 12345678;//well, it should be just 1234.
unsigned char* pChars;
pChars = (unsigned char*) &x;
pChars[0];//one byte is here
pChars[1];//another byte here
(Как только вы поймете, что происходит, это можно сделать без каких-либо переменных, все просто кастинг)
Ответ 5
Это действительно зависит от вашей цели: почему вы хотите преобразовать ее в unsigned char
? В зависимости от ответа на это существует несколько разных способов сделать это:
-
Усекать. Это то, что было рекомендовано. Если вы просто пытаетесь сжать данные в функцию, которая требует unsigned char
, просто выберите uchar ch = (uchar)x
(но, конечно, остерегайтесь того, что произойдет, если ваш int слишком большой).
-
Конкретный endian. Используйте это, когда ваш пункт назначения требует определенного формата. Обычно сетевому коду нравится все, что преобразуется в массивы большого числа символов:
int n = sizeof x;
for(int y=0; n-->0; y++)
ch[y] = (x>>(n*8))&0xff;
сделает это.
-
Конечный компьютер. Используйте это, когда нет требования к требованию, и данные будут возникать только на одной машине. Порядок массива будет изменяться в разных архитектурах. Люди обычно заботятся об этом с помощью union
s:
union {int x; char ch[sizeof (int)];} u;
u.x = 0xf00
//use u.ch
с memcpy
:
uchar ch[sizeof(int)];
memcpy(&ch, &x, sizeof x);
или с вечно опасным простым литьем (это поведение undefined и сбои в многочисленных системах):
char *ch = (unsigned char *)&x;
Ответ 6
Вам просто нужно извлечь эти байты, используя bitwise & operator
. OxFF
- шестнадцатеричная маска для извлечения одного байта. Посмотрите здесь различные операции с битами - http://www.catonmat.net/blog/low-level-bit-hacks-you-absolutely-must-know/
Пример программы выглядит следующим образом:
#include <stdio.h>
int main()
{
unsigned int i = 0x1122;
unsigned char c[2];
c[0] = i & 0xFF;
c[1] = (i>>8) & 0xFF;
printf("c[0] = %x \n", c[0]);
printf("c[1] = %x \n", c[1]);
printf("i = %x \n", i);
return 0;
}
Вывод:
$ gcc 1.c
$ ./a.out
c[0] = 22
c[1] = 11
i = 1122
$