2012-04-25 13 views
14

Tengo un número int sin firmar (2 bytes) y deseo convertirlo a unsigned char type. De mi búsqueda, me parece que la mayoría de las personas recomiendan hacer lo siguiente:C - unsigned int a unsigned char array conversion

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

¿Es el enfoque correcto? Lo pregunto porque el carácter sin signo es de 1 byte y hemos convertido datos de 2 bytes en 1 byte.

Para evitar la pérdida de datos, quiero crear una matriz de caracteres sin signo [] y guardar los bytes individuales en la matriz. Estoy atascado en la siguiente:

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] ?? 
} 

Además, ¿Cómo podemos convertir el unsigned char [2] de nuevo a unsigned int.

Muchas gracias.

+0

posible duplicado de [firmado corto a byte en C++] (http://stackoverflow.com/questi ons/10288109/signed-short-to-byte-in-c) –

Respuesta

16

Puede utilizar memcpy en ese caso:

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

Además, ¿cómo sería convertir el unsigned char [2] de nuevo a unsigned int.

De la misma manera, simplemente invierta los argumentos de memcpy.

15

¿Qué tal:

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

La operación inversa se deja como ejercicio.

7

¿Qué le parece usar una unión?

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

Por supuesto, la matriz de caracteres lo suficientemente grande como para contener un valor mayor tiene que ser exactamente tan grande como este valor en sí mismo. Así que usted puede simplemente pretender que este valor más grande es ya un conjunto de caracteres:

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 

(Una vez que entienda lo que está pasando, que se puede hacer sin ninguna variable, todo a casting)

+2

Si '12345678' cabe en' unsigned int' y 'sizeof (unsigned int) == 2', entonces' CHAR_BIT' es más grande de lo normal ;-) –

+0

¡Culpo a la sociedad de 32 bits por consentirme! –

2

Sólo necesita extraer esos bytes usando bitwise & operator. OxFF es una máscara hexadecimal para extraer un byte. Por favor, busque en varias operaciones de bits aquí - http://www.catonmat.net/blog/low-level-bit-hacks-you-absolutely-must-know/

Un programa de ejemplo es el siguiente:

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

Salida:

$ gcc 1.c 
$ ./a.out 
c[0] = 22 
c[1] = 11 
i = 1122 
$ 
+1

Querías cambiar num & 0xFF00 por 8, ¿verdad? (num & 0xFF00) >> 8. De lo contrario, solo tiene un entero de 16 bits donde el byte bajo pasa a ser cero. Aún no tienes un byte. Alternativamente, puedes cambiar: num >> 8; – abelenky

+0

@abelenky Estás en lo cierto ... lo pasaste por alto! –

4

Realmente depende de su objetivo: ¿Por qué quiere convertir este a un unsigned char? En función de la respuesta a que hay diferentes maneras de hacer esto:

  • Truncar: Esto es lo que estaba recomendado.Si solo está tratando de exprimir datos en una función que requiere un unsigned char, simplemente eche uchar ch = (uchar)x (pero, por supuesto, tenga cuidado con lo que sucede si su int es demasiado grande).

  • Endian específico: Use esto cuando su destino requiera un formato específico. Por lo general, el código de red le gusta todo lo que se convierte en matrices de caracteres big endian:

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

    lo hará.

  • Máquina endian. Úselo cuando no exista un requisito de endianness, y los datos solo ocurrirán en una máquina. El orden de la matriz cambiará a través de diferentes arquitecturas. La gente por lo general se encargan de esto con union s:

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

    con memcpy:

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

    o con la elección cada vez más peligroso sencilla (que es un comportamiento indefinido, y se estrella en numerosos sistemas):

    char *ch = (unsigned char *)&x;