[C con Clase] hexdump

Salvador Pozo salvador en conclase.net
Jue Sep 24 16:39:00 CEST 2009


El pasado 2009-09-24 10:51:24, David escribió:

Hola:

D> esta función tan conocida que pasa datos de binario a hexadecimal no logro
D> entender como lo hace:

Vamos a ver...

D> const char *
D> mrtd_hexdump(const void *data, unsigned int len)
D> {
D>     static char string[1024];
D>     unsigned char *d = (unsigned char *) data;
D>     unsigned int i, left;
D>     memset(string, 0, sizeof(string));//inicializa a 0.
D>     left = sizeof(string); //left no se usa , no entiendo para que lo
D> declara

Lo puedes quitar, efectivamente, la variable "left" no se usa, y por lo tanto, no es necesario declararla ni inicializarla. Probablemente ha dejado de ser necesaria después de alguna modificación (seguramente cunado se sustituyó sprintf por su versión "segura": _snprintf).

D>     for (i = 0; len--; i += 3){  //no entiendo el control de este bucle,
D> ¿cuando acaba?

Acaba cuando el valor de 'len' llega a cero. En cada iteración del bucle, el valor de i se incrementa en tres. Eso corresponde a dos dígitos hexadecimales y el espacio separador. Al mismo tiempo,para cada iteración también disminuye en una unidad el valor de len, que es un parámetro que indica el número de bytes que tenemos que convertir a hexadecimal.

En definitiva, en cada iteración, un byte de los datos apuntados por "data" se convierte a dos caracteres hexadecimales más un espacio.

D>         if (i >= sizeof(string) -4)

Aquí nos aseguramos de que tenemos espacio en "string" para otro valor hexadecimal, compuesto, como dije antes, por dos caracteres hexadecimales, un espacio y un cero terminador, en total, cuatro caracteres.

Creo que esto es un error, o al menos que se puede optimizar, ya que en la anterior iteración (salvo que sea la primera), ya añadimos un caracter nulo, que se sobrescribirá en la iteración actual, pero bueno.

D>             break;
D>         _snprintf(string+i, 4, " %02x", *d++);  ¿ por que tiene d un *? la
D> cadena de formato "%02x" no la entiendo

_snprintf es una de las llamadas "versiones seguras" de las funciones para imprimir en cadenas. La seguridad consiste en que se añade un parámetro, el segundo, que indica el número máximo de caracteres a añadir. 

En este caso es redundante, puesto que ya verificamos que hay espacio en el "if" anterior.

El formato "%02x" indica varias cosas:
 - la 'x', que se espera un entero que se expresará en hexadecimal.
 - el '2', que se usarán dos caracteres.
 - el '0', que si se necesitan menos caracteres de los indicados, se rellenarán los sobrantes al inicio con ceros.

Y la variable "d" lleva un asterisco porque se trata de un puntero a unsigned char (unsigned char *), y el formato espera un entero, por lo tanto, necesitamos desreferenciar el valor apuntado por "d".

D>     }
D>     return string;
D> }
D> a ver si conseguis explicarmelo porque llevo una hora y a pesar de que
D> intuyo que el proceso de conversión será el que seguimos normalmente para
D> pasar de hexadecimal a binario, en el código no lo entiendo.

No, no tiene nada que ver. En este caso nos aprovechamos de la función sprintf, o más concretamente de su versión "segura". La conversión real larealiza esa función. Todo lo demás se añade para almacenar la salida en una cadena.

He de añadir que (y esto es una opinión personal), no me gustan las versiones "seguras" de las funciones con acceso a memoria, en el mejor de los casos (como este) son redundantes, y en el peor, deposita el control que deberíamos hacer nosotros en el compilador o en las librerías. Pero esto es una opición. :-)

-- 
Salvador Pozo (Administrador)
mailto:salvador en conclase.net


Más información sobre la lista de distribución Cconclase