En ocasiones, por motivos del protocolo utilizado en una comunicación, por la forma de acceder a la capa física o por cualquier otra razón similar, no podemos manejar directamente enteros de 4 bytes en nuestro programa, sino que debemos manejar valores de 1 sólo byte. No debemos preocuparnos, al fin y al cabo, podemos enviar un vector de 4 elementos de un tipo de dato que tenga 1 byte, por ejemplo, un carácter sin signo.
Gracias a la operación de desplazamiento de bits y al producto binario, la operación es casi inmediata. Veamos, la idea es guardar un entero de 4 bytes en un vector de 4 elementos de un byte de la siguiente manera:
Por lo tanto, para almacenar el entero en dicho vector nos limitaremos a hacer lo siguiente:
unsigned char v[4]; v[0] = (n >> 24) & 0xFF; v[1] = (n >> 16) & 0xFF; v[2] = (n >> 8 ) & 0xFF; v[3] = n & 0xFF;
Como véis, además de desplazar, multiplico por todo unos (FF) para asegurarnos de que el entero resultante se queda sólo con el byte que nos importa.
Ahora tenemos en base 256 un número de 4 bytes guardado en 4 cifras. ¿Cómo hacer la operación inversa? Muy simple, si en base 10 hacemos: unidades + decenas x 10 + centenas * 100… en nuestro caso tendríamos:
resultado = v[0] * 16777216 + v[1] * 65536 + v[2] * 256 + v[3];
https://www.youtube.com/embed/z-xGk9c_eOw Guionista y locutor: Manuel Ignacio López Quintero.Fecha de publicación: 31 de diciembre de 2024.
Ver comentarios
@Carazo, gracias por esta explicación, alguna vez puede que nos sea útil.
salu2
¿Y qué te parece esto?
unsigned char Vector[4];
memcpy(Vector, &n, 4*sizeof(char));
Como las 4 posiciones de Vector son contiguas, al copiar todo el contenido de n en la posición inicial todas quedan rellenas. La operación inversa es el memcpy en el sentido contrario, claro. ¿Algún fallo?
Multiplicando por 0XFF no te extenderá el signo de la constante (0xFFFFFFFF); que yo recuerde, ese es el comportamiento habitual. ¿No debería ser 0X00FF para evitarlo?
Saludos.
@Surgat: como dices, dependiendo de la arquitectura de la plataforma (little-endian o big-endian) podría fallar (https://www.linuxhispano.net/2010/05/13/conceptos-de-informatica-endian/).
@Morpheus: no te lo extiende (al menos en GCC) lo que sí es cierto es que si quieres asegurarte no es 00FF sino 000000FF (dos cifras hexadecimales para un byte).
En el ejemplo que se muestra con operadores a nivel de bit se guarda la información siguiendo el formato de Big endian (que es el empleado para formato de red), así que el memcpy realiza la misma operación.
No es necesario poner 4*(sizeof(char)) como tercer argumento en memcpy, pues el valor que coloquemos ahí se interpreta como N. de bytes.
Y por último cuando aplican la máscara (yo prefiero llamarlo así ;)) 0xFF no se necesita colocar 0's adicionales a la izquierda, ya que la operación se realiza desde el Bit menos significativo al mayor, dando como mencionas el primer byte que es el utilizado.
Saludos y ojalá publiquen más artículos como este.
@carazo: sea little endian o big endian, si la conversión de una forma a otra se hace con memcpy's inversos, dará igual. La diferencia sería que el MSB estaría en Vector[0] o Vector[3], creo yo
@Eduardo: Muchísimas gracias por tu aportación, mi duda ahora es si cambia el endian entre las máquinas que envíe y la que recibe los datos, al reconstruirlos con el memcpy creo que habría problemas. Con mi método creo que no habría problemas.
@Surgat: Si cambia el MSB, el número se transmitirá al "revés" y será incorrecto al recomponerse.
No tengo posibilidad de probarlo entre distintas arquitecturas para ver el resultado, si alguien puede aportarnos más claridad con pruebas reales, le estaría muy agradecido.
Excelente explicacion!! ahora a ver si funciona . . . sobre la HCR825 de ASK.
Saludos!!
@JulianPrestas: Debería funcionar, son instrucciones muy cercanas al ensamblador.