【问题标题】:Re Legacy code : format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘long unsigned int’ [-Wformat]重新遗留代码:格式“%d”需要“int”类型的参数,但参数 3 的类型为“long unsigned int”[-Wformat]
【发布时间】:2014-01-02 15:46:45
【问题描述】:

我经常尝试使用最近的 GCC 构建许多旧的模拟器以及磁盘和磁带存档工具。有些错误很容易修复,但我不是一个很好的程序员。

我明白了:

itstar.c:在函数“addfiles”中:
itstar.c:194:4:警告:格式“%d”需要“int”类型的参数,但参数 2 的类型为“long unsigned int”[-Wformat]
itstar.c:194:4:警告:格式“%d”需要“int”类型的参数,但参数 3 的类型为“long unsigned int”[-Wformat]

来自此代码片段:

/* add files to a DUMP tape */
/* output buffer must have been initialized with resetbuf() */
static void addfiles(int argc,char **argv)
{
    int c=argc;
    char **v=argv;

    while(c--) {
        addfile(argc,argv,*v++);
    }
    if(verify)
        printf("Approximately %d.%d' of tape used\n",count/bpi/12,
            (count*10/bpi/12)%10);
}

第 194 行是倒数第三行,从 printf 开始。

文件是itstar.c,来自tapetools,代码here

尽管有警告,但我更愿意知道如何防止它,
所以结果更有效,数据损坏的可能性更小。

请问,我错过了什么,需要改变吗?

提前谢谢你。

【问题讨论】:

  • 现在我真的不明白这个。我再次运行 make,它没有错误地构建。
  • 它来自什么平台?检查 printf 参数是编译器的最新功能,intlong 在许多平台上具有相同的大小,尤其是在 Win32 上。
  • 我需要查找它编写的原始平台。我正在 Ubuntu 13.04 上构建。感谢您这么快回复。
  • @Kuze:Make 可能第二次没有重新编译文件。
  • @Kuze 也有相关的目标文件?

标签: c unix gcc printf undefined-behavior


【解决方案1】:

使用格式说明符%lu 而不是%d,您的编译器应该停止抱怨。

printf("Approximately %lu.%lu' of tape used\n", count/bpi/12, (count*10/bpi/12)%10);

【讨论】:

    【解决方案2】:

    使用%lu 代替%d%d 用于int 类型,%lu 用于unsigned long

    【讨论】:

      【解决方案3】:

      这里是undefined behavior,这意味着任何事情都可能发生,包括看起来正常工作,然后在路上出现故障。

      查看源代码我们可以看到countbpi 都是unsigned long

      extern unsigned long bpi; /* tape density in bits per inch */
      extern unsigned long count; /* count of tape frames written */ 
      

      这些的正确格式说明符是%lu

      printf 的第一个参数指定要打印的字符串,该字符串可以包含以 % 开头的转换说明符,通常指定后续参数的类型,因此在您的示例中:

      "Approximately %d.%d' of tape used\n"
                     ^^ ^^
                     1  2
      

      转换说明符12 都是%d,这意味着printf 将期望接下来的两个参数是int 类型,但它们实际上是unsigned long 类型。

      如果我们查看 draft C99 standard 部分 7.19.6.1 fprintf 函数,它还涵盖了格式说明符的 printf,说:

      如果转换规范无效,则行为未定义。248) 如果任何参数不是相应转换规范的正确类型,则行为未定义。

      因此您需要修复不正确的格式说明符,您的警告将消失,您将回到明确定义的行为领域。

      【讨论】:

      • 考虑添加一个关于 printf 工作原理的简要说明,op 显然不明白错误是什么。
      猜你喜欢
      • 2014-02-03
      • 1970-01-01
      • 2015-02-27
      • 1970-01-01
      • 2021-05-12
      • 2021-06-22
      • 2012-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多