tipos - C-int sin signo a conversión de matriz de caracteres sin signo
tipos de datos primitivos en c (6)
Tengo un número int sin firmar (2 bytes) y quiero convertirlo en un tipo de char sin firmar. De mi búsqueda, encuentro que la mayoría de las personas recomiendan hacer lo siguiente:
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 pasamos de datos de 2 bytes a 1 byte.
Para evitar cualquier pérdida de datos, quiero crear una matriz de caracteres sin firmar [] y guardar los bytes individuales en la matriz. Estoy atascado en lo 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 convertiríamos el carácter unsigned [2] de nuevo a unsigned int .
Muchas gracias.
¿Qué hay de 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]);
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 simplemente puedes pretender que este valor más grande ya es una serie 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 entiendes lo que está sucediendo, se puede hacer sin ninguna variable, solo con el casting)
Puedes usar memcpy
en ese caso:
memcpy(ch, (char*)&num, 2); /* although sizeof(int) would be better */
Además, cómo se convertiría el carácter unsigned [2] de nuevo a unsigned int.
De la misma manera, basta con revertir los argumentos de memcpy.
Qué tal si:
ch[0] = num & 0xFF;
ch[1] = (num >> 8) & 0xFF;
La operación inversa se deja como ejercicio.
Realmente depende de tu objetivo: ¿por qué quieres convertir esto en un unsigned char
? Dependiendo de la respuesta a esta pregunta, hay varias formas diferentes de hacer esto:
Truncado : Esto es lo que se recomendó. Si solo está tratando de comprimir los datos en una función que requiere un
unsigned char
, simplemente lanceuchar 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;
Will hace eso.
Maquina endian . Use esto cuando no exista un requisito de endianidad y los datos solo se producirán en una máquina. El orden de la matriz cambiará a través de diferentes arquitecturas. La gente suele ocuparse de esto con la
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 el siempre simple y peligroso casting (que es un comportamiento indefinido y se bloquea en numerosos sistemas):
char *ch = (unsigned char *)&x;
Solo necesitas extraer esos bytes usando bitwise & operator
. OxFF
es una máscara hexadecimal para extraer un byte. Mire las distintas 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
$