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 
$