我经常尝试使用最近的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。
尽管有警告,它仍会建立,但我更愿意知道如何防止它,
因此结果更有效,数据损坏的可能性更小。
拜托,我错过了什么,需要改变?
提前谢谢。
答案 0 :(得分:6)
这是undefined behavior,这意味着任何事情都可能发生,包括看似正常工作,然后在路上休息。
查看来源,我们可以看到count
和bpi
无符号长:
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
转化说明符1
和2
都是%d
,这意味着printf
会希望接下来的两个参数属于int
类型,但它们确实是类型为unsigned long
。
如果我们查看draft C99 standard部分7.19.6.1
fprintf函数,其中也包含printf格式说明符,请说:
如果转换规范无效,则行为未定义。 248)如果任何参数不是相应转换规范的正确类型,则行为未定义。
因此您需要修复不正确的格式说明符,并且您的警告将消失,您将回到明确定义的行为领域。
答案 1 :(得分:5)
使用格式说明符%lu
代替%d
,您的编译器应该停止抱怨。
printf("Approximately %lu.%lu' of tape used\n", count/bpi/12, (count*10/bpi/12)%10);
答案 2 :(得分:2)
使用%lu
代替%d
。 %d
用于int
,[{1}}用于%lu
。