C - преобразование массива unsigned int в unsigned char

У меня есть число int без знака (2 байта), и я хочу преобразовать его в тип unsigned char. Проведя поиск, я обнаружил, что большинство людей рекомендуют делать следующее:

 unsigned int x;
 ...
 unsigned char ch = (unsigned char)x;

Правильный подход? Я спрашиваю, потому что unsigned char - это 1 байт, а мы преобразовали 2 байта в 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.

Большое спасибо.


person Jake    schedule 25.04.2012    source источник
comment
возможный дубликат подписан коротким байтом в c ++   -  person Paul R    schedule 25.04.2012


Ответы (6)


В этом случае вы можете использовать memcpy:

memcpy(ch, (char*)&num, 2); /* although sizeof(int) would be better */

Кроме того, как преобразовать unsigned char [2] обратно в unsigned int.

Таким же образом просто поменяйте аргументы memcpy на противоположные.

person jpalecek    schedule 25.04.2012

Как насчет:

ch[0] = num & 0xFF;
ch[1] = (num >> 8) & 0xFF;

Обратное действие оставим в качестве упражнения.

person cnicutar    schedule 25.04.2012

Как насчет использования союза?

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]);
person abelenky    schedule 25.04.2012

Это действительно зависит от вашей цели: почему вы хотите преобразовать это в unsigned char? В зависимости от ответа на этот вопрос есть несколько разных способов:

  • Усечь: это то, что было рекомендовано. Если вы просто пытаетесь втиснуть данные в функцию, для которой требуется unsigned char, просто приведите uchar ch = (uchar)x (но, конечно, остерегайтесь того, что произойдет, если ваш int слишком велик).

  • Конкретный порядок байтов: используйте этот параметр, если для пункта назначения требуется определенный формат. Обычно сетевой код любит все, что преобразовано в массивы символов с прямым порядком байтов:

    int n = sizeof x;
    for(int y=0; n-->0; y++)
        ch[y] = (x>>(n*8))&0xff;
    

    будет делать это.

  • Машинный порядок байтов. Используйте это, когда нет требования к порядку байтов, и данные будут находиться только на одном компьютере. Порядок массива будет меняться в зависимости от архитектуры. Обычно об этом заботятся с помощью unions:

    union {int x; char ch[sizeof (int)];} u;
    u.x = 0xf00
    //use u.ch 
    

    с memcpy:

    uchar ch[sizeof(int)];
    memcpy(&ch, &x, sizeof x);
    

    или с постоянно опасным простым приведением типов (которое является неопределенным поведением и дает сбой во многих системах):

    char *ch = (unsigned char *)&x;
    
person Dave    schedule 25.04.2012

Конечно, массив символов, достаточно большой, чтобы содержать большее значение, должен быть точно таким же большим, как само это значение. Таким образом, вы можете просто представить, что это большее значение уже является массивом символов:

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

(Как только вы поймете, что происходит, это можно будет сделать без каких-либо переменных, все просто кастинг)

person Agent_L    schedule 25.04.2012
comment
Если 12345678 вписывается в unsigned int и sizeof(unsigned int) == 2, то CHAR_BIT больше обычного ;-) - person Steve Jessop; 25.04.2012
comment
Я виню 32-битное общество в том, что оно меня балует! - person Agent_L; 25.04.2012

Вам просто нужно извлечь эти байты с помощью 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 
$
person Sangeeth Saravanaraj    schedule 25.04.2012
comment
Вы хотели сдвинуть num & 0xFF00 на 8, верно? (число & 0xFF00) ›› 8. В противном случае у вас есть 16-битное целое число, младший байт которого равен нулю. У вас все еще нет байта. Вы также можете просто сдвинуть: num ›› 8; - person abelenky; 25.04.2012