Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sscanf 1 byte hex data without overflow

I need to scan a hex representation of 6 bytes data and store it in a 6 byte array.

Please note I am in an embedded system so every byte count.

Using sscanf this way :

uint8_t buf[6];
char hex[13] = "123456789ABC";
sscanf(hex, "%02X%02X%02X%02X%02X%02X", &buf[0], &buf[1], &buf[2], &buf[3], &buf[4], &buf[5]);

is overflowing because each %02X specifier load in a uint32_t.

  • %02lX will load in a uint32_t
  • %02hX will load in a uint16_t

Is there a specifier that load in a uint8_t ? (I don't find it anywhere)

Is there another way of doing this ?

I tried to do :

sscanf(hex, "%08lX%04hX", &buf[0], &buf[4]);

this does not overflow, but as I am on little endian structure, the order is mixed up...

like image 571
GPTechinno Avatar asked Dec 31 '14 03:12

GPTechinno


2 Answers

Please note I am in an embedded system so every byte count.

If that is the case then sscanf is probably ill-advised; its stack usage and code space will dwarf any saving you might perceive in using the smallest possible data type. Consider:

uint8_t hexdigit( char hex )
{
    return (hex <= '9') ? hex - '0' : 
                          toupper(hex) - 'A' + 10 ;
}

uint8_t hexbyte( const char* hex )
{
    return (hexdigit(*hex) << 4) | hexdigit(*(hex+1)) ;
}

Then your code becomes:

char hex[13] = "123456789ABC";

for( int b = 0; b < 6; b++ )
{
    buf[b] = hexbyte( &hex[b * 2] ) ;
}

If you must use sscanf() but your library does not support the hh format specifier qualifier (as many embedded or older C libraries may not), then you can use an intermediate integer:

char hex[13] = "123456789ABC";

for( int b = 0; b < 6; b++ )
{
    unsigned byte ;

    sscanf( &hex[b * 2], "%02X", &byte ) ;
    buf[b] = (unit8_t)byte ;
}
like image 198
Clifford Avatar answered Nov 06 '22 22:11

Clifford


You want to use %02hhX on an array of unsigned char. (So uint8_t is fine)

like image 26
dho Avatar answered Nov 06 '22 23:11

dho