sscanf 1字节十六进制数据,没有溢出

时间:2014-12-31 03:29:27

标签: c embedded overflow scanf

我需要扫描6字节数据的十六进制表示,并将其存储在一个6字节的数组中。

请注意我在嵌入式系统中,因此每个字节都有。

以这种方式使用sscanf:

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]);

溢出,因为每个%02X说明符都在uint32_t中加载。

  • %02lX将加载到uint32_t
  • %02hX将加载uint16_t

是否有一个在uint8_t中加载的说明符? (我在任何地方都找不到它)

还有另一种方法吗?

我试着这样做:

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

这不会溢出,但由于我处于小端结构上,订单混淆了......

2 个答案:

答案 0 :(得分:8)

您希望在unsigned char数组上使用%02hhX。 (所以uint8_t很好)

答案 1 :(得分:8)

  

请注意我在嵌入式系统中,因此每个字节都有。

如果是这种情况,那么sscanf可能是不明智的;它的堆栈使用和代码空间将使您在使用尽可能小的数据类型时可能感知到的任何保存相形见绌。考虑:

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)) ;
}

然后您的代码变为:

char hex[13] = "123456789ABC";

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

如果必须使用sscanf(),但是您的库不支持hh格式说明符限定符(因为许多嵌入式或旧的C库可能不支持),那么您可以使用中间整数:

char hex[13] = "123456789ABC";

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

    sscanf( &hex[b * 2], "%02X", byte ) ;
    buf[b] = (unit8_t)byte ;
}