为什么 GCC 对错误的 printf 格式说明符显示重复的警告?
我很好奇为什么 GCC 在编译此文件时向我显示两个相同的警告:
$ cat test.c
#include <stdio.h>
int main (int argc, char const *argv[])
{
long foo = 0l;
printf("%i\n", foo);
return 0;
}
$ gcc-4.2 -Wall test.c
test.c: In function ‘main’:
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
有趣的是,Clang 还给出了两个警告:
$ clang test.c
test.c:6:14: warning: conversion specifies type 'int' but the argument has type 'long' [-Wformat]
printf("%i\n", foo);
~^ ~~~
%ld
test.c:6:14: warning: conversion specifies type 'int' but the argument has type 'long' [-Wformat]
printf("%i\n", foo);
~^ ~~~
%ld
2 warnings generated.
有什么想法吗?
有关信息:
$ gcc-4.2 -v
Using built-in specs.
Target: i686-apple-darwin11
Configured with: /private/var/tmp/gcc/gcc-5666.3~278/src/configure
--disable-checking --enable-werror --prefix=/usr --mandir=/share/man
--enable-languages=c,objc,c++,obj-c++
--program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib
--build=i686-apple-darwin11 --program-prefix=i686-apple-darwin11-
--host=x86_64-apple-darwin11 --target=i686-apple-darwin11
--with-gxx-include-dir=/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Apple Inc. build 5666) (dot 3)
$ clang -v
Apple clang version 2.1 (tags/Apple/clang-163.7.1) (based on LLVM 3.0svn)
Target: x86_64-apple-darwin11.1.0
Thread model: posix
编辑:一些人建议的“多架构”假设听起来不错,但我不确定它是否正确。如果我使用 -arch
强制使用单一架构,我会收到两个警告。如果我指定 -arch x86_64 -arch i386
,我会收到两组重复警告!
$ gcc-4.2 -Wall -arch x86_64 test.c
test.c: In function ‘main’:
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
$ gcc-4.2 -Wall -arch x86_64 -arch i386 test.c
test.c: In function ‘main’:
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
test.c: In function ‘main’:
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
编辑:我不会收到所有警告类型的欺骗。 -Wformat
是迄今为止我遇到的唯一一个。例如,如果我放入一个未使用的变量,我只会收到一个警告:
$ cat test.c
#include <stdio.h>
int main (int argc, char const *argv[])
{
long foo = 0l;
long bar;
printf("%i\n", foo);
return 0;
}
$ gcc-4.2 -Wall test.c
test.c: In function ‘main’:
test.c:7: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
test.c:7: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
test.c:6: warning: unused variable ‘bar’
I'm curious why GCC shows me two identical warnings when compiling this file:
$ cat test.c
#include <stdio.h>
int main (int argc, char const *argv[])
{
long foo = 0l;
printf("%i\n", foo);
return 0;
}
$ gcc-4.2 -Wall test.c
test.c: In function ‘main’:
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
Interestingly, Clang also gives two warnings:
$ clang test.c
test.c:6:14: warning: conversion specifies type 'int' but the argument has type 'long' [-Wformat]
printf("%i\n", foo);
~^ ~~~
%ld
test.c:6:14: warning: conversion specifies type 'int' but the argument has type 'long' [-Wformat]
printf("%i\n", foo);
~^ ~~~
%ld
2 warnings generated.
Any ideas?
For info:
$ gcc-4.2 -v
Using built-in specs.
Target: i686-apple-darwin11
Configured with: /private/var/tmp/gcc/gcc-5666.3~278/src/configure
--disable-checking --enable-werror --prefix=/usr --mandir=/share/man
--enable-languages=c,objc,c++,obj-c++
--program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib
--build=i686-apple-darwin11 --program-prefix=i686-apple-darwin11-
--host=x86_64-apple-darwin11 --target=i686-apple-darwin11
--with-gxx-include-dir=/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Apple Inc. build 5666) (dot 3)
$ clang -v
Apple clang version 2.1 (tags/Apple/clang-163.7.1) (based on LLVM 3.0svn)
Target: x86_64-apple-darwin11.1.0
Thread model: posix
EDIT: the 'multi-architecture' hypothesis a few have suggested sounded good, but I'm not sure it's right. If I force a single architecture with -arch
, I get two warnings. If I specify -arch x86_64 -arch i386
, I get two sets of duplicate warnings!
$ gcc-4.2 -Wall -arch x86_64 test.c
test.c: In function ‘main’:
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
$ gcc-4.2 -Wall -arch x86_64 -arch i386 test.c
test.c: In function ‘main’:
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
test.c: In function ‘main’:
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
test.c:6: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
EDIT: I don't get dupes for all warning types. -Wformat
is the only one I've come across so far. For example, if I throw in an unused variable I only get one warning for that:
$ cat test.c
#include <stdio.h>
int main (int argc, char const *argv[])
{
long foo = 0l;
long bar;
printf("%i\n", foo);
return 0;
}
$ gcc-4.2 -Wall test.c
test.c: In function ‘main’:
test.c:7: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
test.c:7: warning: format ‘%i’ expects type ‘int’, but argument 2 has type ‘long int’
test.c:6: warning: unused variable ‘bar’
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这是因为 Apple 的
stdio.h
标头附加了 GCCformat
属性 到其声明printf()
...(例如,参见
printf()
的声明 此处 以及__printflike()
宏 此处)...但是 GCC (还有 Clang,因为它试图与 GCC 非常兼容!)已经内置了
printf()
是一个采用printf
样式参数的函数。由于内置知识,您会收到一个警告,由于显式属性,您会收到第二个警告。您可以通过自己执行相同的操作,在其他平台(至少有多个版本的 GCC)上演示相同的行为:
This is because Apple's
stdio.h
header attaches a GCCformat
attribute to its declaration ofprintf()
...(e.g. see the declaration of
printf()
here and the declaration of the__printflike()
macro here)...but GCC (and Clang, due to it trying to be very GCC-compatible!) already has built-in knowledge that
printf()
is a function which takesprintf
-style arguments. You're getting one warning due to the built-in knowledge, and a second warning due to the explicit attribute.You can demonstrate the same behaviour on other platforms (with at least several versions of GCC) by doing the same thing yourself:
如果您的目标是两种 CPU 架构(例如,iOS 上的 ARMv6/ARMv7,或 Mac 上的 i386/x86_64),您将看到每个警告的两个副本,因为编译器为每个文件运行两次(每个架构一次)。
在 Mac 上,如果启用 PPC/PPC64 支持,则每行最多可以获得 4 个警告。 ;)
编辑:马修在接受的答案中得到了正确的答案。
If you're targetting two CPU architectures (ARMv6/ARMv7 on iOS, for instance, or i386/x86_64 on Mac), you'll see two copies of each warning because the compiler runs twice for each file (once for each architecture.)
On a Mac, you can get it up to 4 warnings per line if you enable PPC/PPC64 support. ;)
Edit: Matthew's got it spot-on in the accepted answer.
看起来您正在为 iOS 进行编译。该代码针对多种架构进行了多次编译。正在为每个架构生成警告。
It looks like you're compiling for iOS. The code is being compiled multiple times for multiple architectures. The warning is being generating for each architecture.