【问题标题】:sscanf 1 byte hex data without overflowsscanf 1 字节十六进制数据,无溢出
【发布时间】:2014-12-31 03:29:27
【问题描述】:

我需要扫描 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]);

这不会溢出,但是因为我是小端结构,所以顺序是混乱的......

【问题讨论】:

  • 是否需要用大端结构表示?你的意思是订单搞砸了?
  • 你试过无符号字符吗? - 又名 %c
  • 代码正在加载到一个 6 字节的缓冲区中。建议使用 '%c' 而不是 '%02x' 加载。
  • 并非所有嵌入式系统都受到严重的资源限制,因此一个不跟随另一个;你应该更具体地量化你的约束。从表面上看,如果你真的受到资源限制,你不会在一开始就使用 sscanf()。

标签: c embedded overflow scanf


【解决方案1】:

请注意,我在嵌入式系统中,所以每个字节都很重要。

如果是这样,那么 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 ;
}

【讨论】:

  • 关于该主题的完美答案。我不明白 [b * 1]。谁能解释一下?
  • @Noel ;这是一个错误或类型。只花了将近 4 年的时间让任何人发现它!修好了。
  • 这是真的,我检查了 2 个“嵌入式”实现,它们分别使用了 100 和 500 字节的堆栈......
  • 令我惊讶的是,hh 在我的案例中也确实不受支持 (gnu-arm-none-eabi 7.3.1) ... 有什么特别的原因吗?
  • @AyberkÖzgür :因为独立的 GCC 实现不使用依赖于 POSIX 的 gnu libc C 库,而您可能正在使用 Newlib 或其他 C 库。也就是说,它是关于 C 库,而不是编译器。
【解决方案2】:

您想在一个无符号字符数组上使用%02hhX。 (所以uint8_t 很好)

【讨论】:

  • 它被埋没了,可能取决于您拥有的手册页集。在linux.die.net/man/3/printf,查看标题为“长度修饰符”部分下的第一位。这是一个很大的手册页,printf 格式的字符串很复杂。
  • 如果他的资源严重受限,他不太可能使用 Linux,因此手册页参考可能不相关。 hh 格式修饰符是在 ISO C99 中引入的,许多嵌入式库在任何情况下都使用“缩减”的 stdio 实现,因此它可能不可用。 @moquette31,您应该查阅特定工具链的库文档。
  • Win32/64平台在%02hhx的情况下不会写入单个字节:github.com/exploitagency/vanitygen-plus/pull/97/files
猜你喜欢
  • 2019-09-19
  • 2015-08-08
  • 1970-01-01
  • 2015-08-08
  • 2017-09-13
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多