Para completude, você também pode fazer isso facilmente sem chamar qualquer função de biblioteca pesada (sem snprintf, sem strcat, nem mesmo memcpy). Pode ser útil, digamos, se você estiver programando algum microcontrolador ou kernel do sistema operacional onde libc não está disponível.
Nada realmente sofisticado que você possa encontrar código semelhante por aí se você procurar por ele no Google. Na verdade, não é muito mais complicado do que chamar snprintf e muito mais 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);
}
Aqui está outra versão um pouco mais curta. Ele simplesmente evita a variável de índice intermediária i e a duplicação do último código de caso (mas o caractere de terminação é escrito duas vezes).
#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);
}
Abaixo está outra versão para responder a um comentário dizendo que usei um "truque" para saber o tamanho do buffer de entrada. Na verdade, não é um truque, mas um conhecimento de entrada necessário (você precisa saber o tamanho dos dados que está convertendo). Deixei isso mais claro extraindo o código de conversão para uma função separada. Também adicionei o código de verificação de limite para o buffer de destino, o que não é realmente necessário se sabemos o que estamos fazendo.
#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]
deve ser lançado paraunsigned char
, ou irá transbordar sebuf[i] > 127
, isto é:buf_ptr += sprintf(buf_ptr, "%02X", (unsigned char)buf[i]);