【问题标题】:getting rid of sscanf() warnings摆脱 sscanf() 警告
【发布时间】:2010-02-17 04:06:31
【问题描述】:

我正在从标准输入读取 MAC 地址(以标准十六进制表示法,例如 00:11:22:33:44:55)并将它们转换为 6 字节变量 hw_addr 作为小数:

u8 hw_addr[6];

scanf("%2x:%2x:%2x:%2x:%2x:%2x", &hw_addr[0], &hw_addr[1], &hw_addr[2], &hw_addr[3], &hw_addr[4], &hw_addr[5]);

唯一的问题是我收到了 6 个 scanf 警告:

warning: format '%2x' expects type 'unsigned int *', but argument 3 has type 'u8 *'

.....

有什么方法可以在不浪费每个字段的 int 的情况下摆脱这些警告?

【问题讨论】:

  • 为什么需要保存这些字节?
  • 使用unsigned hw_addr[6] 或@Potatoswatter 回答。

标签: c scanf


【解决方案1】:

根据我的 scanf 手册页,

 hh       Indicates that the conversion will be one of dioux or n
          and the next pointer is a pointer to a char (rather than
          int).

所以你想要"%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx"

【讨论】:

  • 您有该页面的链接吗?我在cplusplus.com/reference/clibrary/cstdio/sscanf没有看到这个@
  • @John:参见 C99 规范第 7.19.6.1.7 和 7.19.6.3.2 节
  • dreamlax:所以这只是C99?这将解释它。
  • @John:Matthew 的链接是 POSIX:2004 规范;我不知道 POSIX '04 是否包含所有 C99,但是当谈到像 scanf 这样的纯库函数时,我认为操作系统兼容性可能是库支持的独立原因。
【解决方案2】:

使用正确的类型

所以您正在使用一台拥有数十亿字节 RAM 的机器,并且您想节省其中的 6 个?

如果您要保存数百万个 mac 地址的数组,则应在读取它们后将它们转换为打包格式。但是向scanf() 提供规范的整数不会造成任何伤害。

就此而言,如果hw_addr[] 是一个局部变量,那么它实际上根本不使用空间,因为它会在您的函数返回后被其他局部变量重用。

由于您无法优化所有内容,因此将优化工作集中在真正重要的事情上很重要。

【讨论】:

  • 也许他并没有尝试优化任何东西。也许让 I/O 函数返回您想要的内容比引入本地转换更容易。
  • 我不是唯一一个将其视为节省内存的人。他确实说过“浪费一个int”。但不管意图如何,scanf() 都有一个必须使用的特定接口,使用它不会有任何危害。
【解决方案3】:

警告表明存在严重问题。您正在传递指向无符号字节的指针,但 scanf 函数将向这些指针写入 32 位。对于前 3 个值,额外的 24 位将覆盖 hw_addr 数组的部分,但对于最后 3 个值,您将覆盖堆栈上的一些 other 变量。

为了避免严重的崩溃,至少你需要过度分配 hw_addr

u8 hw_addr[6+3];

至少可以防止您的代码破坏堆栈。但实际上,您应该只使用正确大小的 scanf 值,然后将整数转换回无符号字节。

【讨论】:

    【解决方案4】:

    您正在将 unsigned int 读入 char 地址,这可能不是很便携或安全。只需使用 int 数组作为缓冲区读取然后复制到字节数组

    【讨论】:

    • @Matthew 大端机器将覆盖以前扫描的字节。无论架构如何,最后一个字节总是会溢出。 Int 有帮助,因为那时您正在将 n 个字节读入 n 个字节而不是一个字节
    猜你喜欢
    • 2016-01-15
    • 1970-01-01
    • 2016-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-16
    • 2017-01-25
    相关资源
    最近更新 更多