2011-09-11 6 views
7

tengo curiosidad por qué me muestra GCC dos advertencias idénticas al compilar este archivo:¿Por qué GCC muestra advertencias duplicadas para el especificador de formato bad printf?

$ 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’ 

Curiosamente, Clang también da dos advertencias:

$ 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. 

alguna idea?


Para información:

$ 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: la hipótesis de 'multi-arquitectura' unos pocos han sugerido sonaba bien, pero no estoy seguro de que es correcta. Si fuerzo una sola arquitectura con -arch, recibo dos advertencias. Si especifico -arch x86_64 -arch i386, ¡recibo dos juegos de advertencias duplicadas!

$ 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: No entiendo engañados para todo tipo de advertencia. -Wformat es el único con el que me he encontrado hasta ahora. Por ejemplo, si tiro una variable no utilizada, solo aparece una advertencia al respecto:

$ 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’ 
+2

Fwiw, solo me dan un mensaje de error cuando se utiliza GCC 4.1.2 . ¿Estás seguro de que esto no es un artefacto de tu sistema de compilación, que de alguna manera invoca a GCC dos veces? –

+0

Gracias Oli. No estoy seguro del todo, probablemente lo sea.: -/ –

+0

No veo la advertencia duplicada. Pero entonces, es una advertencia que deberías arreglar de todos modos, así que ... –

Respuesta

8

Esto se debe a la cabecera de Apple stdio.h adjunta un GCC format attribute a su declaración de printf() ...

(por ejemplo, véase la declaración de printf()here y la declaración de la __printflike() macro here)

... pero ¡GCC (y Clang, debido a que intenta ser muy compatible con GCC!) Ya tiene conocimiento incorporado de que printf() es una función que toma printf-argumentos de estilo. Recibirá una advertencia debido al conocimiento incorporado y una segunda advertencia debido al atributo explícito.

Puede demostrar el mismo comportamiento en otras plataformas (con al menos varias versiones de GCC) por hacer lo mismo a ti mismo:

extern int printf(const char *, ...) __attribute__((__format__ (__printf__, 1, 2))); 

int main (int argc, char const *argv[]) 
{ 
    long foo = 0l; 
    printf("%i\n", foo); 

    return 0; 
} 
+0

Brillante! Problema resuelto. (También puede demostrar que esta es la respuesta correcta eliminando el '__DARWIN_LDBL_COMPAT (printf) __printflike (1, 2)' de la definición de 'printf' en'/usr/include/stdio.h' y luego volviendo a compilar). –

2

Parece que está compilando para iOS. El código se está compilando varias veces para múltiples arquitecturas. La advertencia se está generando para cada arquitectura.

+1

La explicación de multi-arquitectura tiene sentido, pero no estoy seguro de que sea el caso aquí. Si agrego, p. '-arch x86_64' a mis banderas gcc o clang, todavía recibo advertencias duplicadas. Si agrego '-arch x86_64 -arch i386', recibo cuatro advertencias. :) –

+1

-1: evidentemente él no está compilando para iOS, ni está haciendo compilación multi-arcos. La invocación del compilador se especifica en la pregunta. –

3

Si está orientando dos arquitecturas de CPU (ARMv6/ARMv7 en iOS, por ejemplo, o i386/x86_64 en Mac), verá dos copias de cada advertencia porque el compilador se ejecuta dos veces para cada archivo (una vez cada arquitectura.)

En una Mac, puede obtener hasta 4 advertencias por línea si habilita la compatibilidad con PPC/PPC64. ;)

Editar: Matthew lo tiene perfecto en la respuesta aceptada.

Cuestiones relacionadas