【问题标题】:sscanf with struct member char array具有结构成员字符数组的 sscanf
【发布时间】:2018-10-30 12:11:38
【问题描述】:

我在为 Arduino 编写代码时发现了这种意外行为,并且我能够在 MSVC15 中复制同样的东西:

struct IDCount
{
    uint16_t count;
    char ID[20];
};
void test06b()
{
    IDCount item;
    char str[] = "0411010103, 8";
    char str1[20];

    // writing to struct member char array
    int res1 = sscanf(str, "%[^,], %d", item.ID, &item.count);
    printf("[%d] id: [%s]\tcount: [%d]\n", res1, item.ID, &item.count);

    // writing to a char array
    int res2 = sscanf(str, "%[^,], %d", str1, &item.count);
    printf("[%d] id: [%s]\tcount: [%d]\n", res2, str1, &item.count);
}

结果:

[2] id: []    count: [8]
[2] id: [0411010103]  count: [8]    

在我缩小到 struct char 数组的问题之前,我花了很多时间检查格式说明符。为什么结构中的 char 数组 不起作用?有什么想法吗?

提前致谢。

更新 从 uint16_t 更改为 int 有效。

【问题讨论】:

  • 您使用的是 %d 而不是 %hu stackoverflow.com/questions/8699812/…
  • @VictorPadureanu %hu 代表unsigned short,不一定与uint16_t 相同。
  • @ach 是对的,我刚刚在 MSVS15 上进行了测试,在那种情况下 %hu 没问题。感谢您指出这一点。
  • @VictorPadureanu C/C++ 是非常脆弱的语言,有很多方法可以进入未定义行为的领域,仅仅在一个编译器上进行测试是不够的。实际上,在几乎所有存在uint16_t 的现代平台上,它都被定义为unsigned short 的同义词。然而理论上,unsigned short 不需要正好有 16 位,可能有更多。在这种情况下,uint16_tunsigned short 将是不同的类型。这就是标准库中提供SCNu16 等宏的原因。

标签: c++ scanf


【解决方案1】:

您使用了错误的格式说明符来读取item.count。对于uint16_t,您必须使用"%"SCNd16"%"SCNu16 而不是"%d"

由于大多数现代平台上的int 长度为32 位,写入item.count 的数据会溢出到item.ID。在 little-endian 架构上,值适合 uint16_t,溢出的字节将为零,有效地终止缓冲区中位置 0 处的字符串。

您可以尝试在源字符串中为 item.count 提供一个负值,然后看到 item.ID 的前两个字节被 0xFFs 覆盖。

【讨论】:

  • 谢谢,我确信这是格式说明符错误,以至于我忽略了由于相邻内存写入溢出而导致的内存损坏。 .
猜你喜欢
  • 2020-02-09
  • 2020-04-13
  • 1970-01-01
  • 2017-02-16
  • 2012-11-22
  • 2020-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多