Para completar, también puede hacerlo fácilmente sin llamar a ninguna función de biblioteca pesada (sin snprintf, sin strcat, ni siquiera memcpy). Puede ser útil, digamos, si está programando algún microcontrolador o kernel del sistema operativo donde libc no está disponible.
No hay nada realmente elegante, puedes encontrar un código similar si lo buscas en Google. Realmente no es mucho más complicado que llamar a snprintf y mucho más rápido.
#include <stdio.h>
int main(){
unsigned char buf[] = {0, 1, 10, 11};
char str[12];
unsigned char * pin = buf;
const char * hex = "0123456789ABCDEF";
char * pout = str;
int i = 0;
for(; i < sizeof(buf)-1; ++i){
*pout++ = hex[(*pin>>4)&0xF];
*pout++ = hex[(*pin++)&0xF];
*pout++ = ':';
}
*pout++ = hex[(*pin>>4)&0xF];
*pout++ = hex[(*pin)&0xF];
*pout = 0;
printf("%s\n", str);
}
Aquí hay otra versión un poco más corta. Simplemente evita la variable de índice intermedio iy la duplicación del último código de caso (pero el carácter de terminación se escribe dos veces).
#include <stdio.h>
int main(){
unsigned char buf[] = {0, 1, 10, 11};
char str[12];
unsigned char * pin = buf;
const char * hex = "0123456789ABCDEF";
char * pout = str;
for(; pin < buf+sizeof(buf); pout+=3, pin++){
pout[0] = hex[(*pin>>4) & 0xF];
pout[1] = hex[ *pin & 0xF];
pout[2] = ':';
}
pout[-1] = 0;
printf("%s\n", str);
}
A continuación se muestra otra versión para responder a un comentario que dice que utilicé un "truco" para saber el tamaño del búfer de entrada. En realidad, no es un truco, sino un conocimiento de entrada necesario (necesita saber el tamaño de los datos que está convirtiendo). Hice esto más claro extrayendo el código de conversión a una función separada. También agregué un código de verificación de límites para el búfer de destino, que no es realmente necesario si sabemos lo que estamos haciendo.
#include <stdio.h>
void tohex(unsigned char * in, size_t insz, char * out, size_t outsz)
{
unsigned char * pin = in;
const char * hex = "0123456789ABCDEF";
char * pout = out;
for(; pin < in+insz; pout +=3, pin++){
pout[0] = hex[(*pin>>4) & 0xF];
pout[1] = hex[ *pin & 0xF];
pout[2] = ':';
if (pout + 3 - out > outsz){
break;
}
}
pout[-1] = 0;
}
int main(){
enum {insz = 4, outsz = 3*insz};
unsigned char buf[] = {0, 1, 10, 11};
char str[outsz];
tohex(buf, insz, str, outsz);
printf("%s\n", str);
}
buf[i]
debe ser fundido aunsigned char
, o se desborde sibuf[i] > 127
, es decir:buf_ptr += sprintf(buf_ptr, "%02X", (unsigned char)buf[i]);