2014-12-08 14 views
19

Ho installato con successo MinGW su una macchina Windows 7 a 32 bit e ho provato a compilare un semplice programma utilizzando la riga di comando o la console MinGW.MinGW non produce avvisi

il codice è un errore intenzionale in una dichiarazione printf:

#include <stdio.h> 
#include <stdlib.h> 
int main(void) 
{ 
    printf("%d\n" , 3.14) ; 
return 0 ; 
} 

Il comando gcc -Wall hello.c dà una corretta avvertimento: hello.c: 7: 2: avvertimento: formato '% d' aspetta argomento di tipo 'int' ...

Ma il comando gcc -std=c99 -Wall hello.c non fornisce alcun avviso.

Entrambi creano un file eseguibile a.exe (che viene eseguito e restituisce lo stesso risultato).

(È interessante notare che un comando gcc -std=gnu99 -Wall hello.c dà l'allarme.)

Non so se questo è un bug, o ha fatto l'installazione andare male in qualche modo, ma sembra sia improbabile poiché le opere del compilatore e con successo compilato una più grande progetto (ma lo stesso avvertimento ovviamente omesso quando si utilizza -std = c99).

Mi mancano alcune informazioni.

(ps: se qualcuno ha un nuovo MinGW installare, si prega di verificare questa.)

versione di gcc 4.8.1 (GCC)

Update 1:

Definizione _GNU_SOURCE prima di includere stdio.h rimuove l'avviso anche con gcc -Wall hello.c.

Aggiornamento 2 (potrebbe essere meno rilevante):

Compilazione

printf("%lf\n" , 3.14) ; 

-std=c99 uscite bandiera: 0.000000

-std=gnu99 uscite: 3,140000

e la compilazione:

01.235.164,106 mila
printf("%f\n" , 3.14) ; 

-std=gnu99 e -std=c99 uscita: 3,140000

Update 3:

funzioni che sembrano essere colpiti sono: printf, fprintf, snprintf, sprintf.

+0

Quale versione? 'gcc --version' – ooga

+2

Ottengo lo stesso risultato (anche 4.8.1). Qualcuno dovrebbe dirlo agli sviluppatori perché questo mi sembra un bug. – ooga

+0

Cosa succede se si utilizza -formato in modo esplicito? –

risposta

15

Il problema con la mancanza di avviso quando si utilizza l'opzione std=c99 sembra che sia perché MinGW 4.8.1 preprocessa stdio.h un po 'diverso per la printf() famiglia di funzioni quando -std=c99 viene utilizzato rispetto a quando viene utilizzato -std=gnu99.

Nota: sto guardando MinGW 4.8.1 da TDM - Penso che altre distribuzioni potrebbero differire in questi dettagli.

MinGW ha avuto alcuni problemi di compatibilità con la formattazione valori in virgola mobile a causa della sua dipendenza storico sulla msvcrt.dll per il runtime C e il fatto che MSVC utilizza una rappresentazione a 64 bit per long double mentre gcc usa un 96-bit (o 128 bit su x64) rappresentazione. Vedi gcc: printf and long double leads to wrong output. [C - Type conversion messes up] per alcuni dettagli. Versioni più recenti di MinGW hanno fornito la loro implementazione della famiglia di funzioni printf() (con un prefisso __mingw_ sul nome) in libmingwex.a per risolvere questi problemi.

I file di intestazione _mingw.h e stdio.h configurare se non saranno utilizzati i libmingwex.a implementazioni o le msvcrt.dll implementazioni.

Sembra che se viene richiesta la conformità ANSI, MinGW utilizzerà le implementazioni libmingwex.a (ci sono molti altri modi per ottenere questa configurazione anche - guarda le intestazioni per i dettagli). Il collegamento di una chiamata utente a printf() all'implementazione __mingw_printf() in libmingwex.a viene effettuato da stdio.h definendo un'implementazione statica in linea di printf() ovvero un involucro sottile attorno a una chiamata a __mingw_vfprintf(). Apparentemente lo -Wformat non viene applicato alle versioni delle funzioni familiari printf() che il compilatore non crede di far parte della libreria (un presupposto ragionevole: il compilatore non sa nulla di queste funzioni). Questo problema può essere risolto applicando l'attributo di funzione appropriato (ad esempio: __attribute__ ((format (printf, 1, 2)))) alle funzioni di wrapper inline statiche.

L'altro problema che hai trovato, dove printf("%lf\n", 3.14) stampe 0.000000 quando si utilizza std=c99, sembra essere un bug nella libmingwex.a realizzazione di __mingw_vfprintf(). Sembra che __mingw_vfprintf() interpreti erroneamente "%lf" in modo che l'argomento sia long double. Non ne sono troppo sorpreso - devo sempre cercare se %lf significa double o long double.

+0

Molto bene. Citerò dallo standard C, dal momento che vedo che ci sei abituato. ["f, FA double argument che rappresenta un numero in virgola mobile ..."] (http://www.iso-9899.info/n1570.html#7.21.6.1p8) – Sebivor

+0

Non è davvero possibile passare un 'float 'a' printf() 'perché un argomento di quel tipo è promosso a' double'. Suppongo che '"% lf "' e '"% f "' siano equivalenti in modo che le stringhe di formato con esse possano 'echo' il loro uso in 'scanf()'. Ma non sono sicuro di cosa siano questi recenti commenti - la risposta dice che sembra che '__mingw_vfprintf()' possa erroneamente considerare '"% lf "' come usando un argomento 'long double' dato che apparentemente produce output differente per 'Specifiche"% lf "' e '"% f "'. Non dice che '"% lf "' dovrebbe essere usato con un tipo 'long double'. –

+0

Il 'l' in'% lf' viene esplicitamente ignorato - '% f' da solo copre l'uso di' double' e 'float' (quest'ultimo viene convertito in down). È lì per dare conforto a coloro che pensano che sia richiesto come 'l' è in'% ld' per lunghi int. –