2012-10-25 24 views
13

ero (rapidamente) a scrivere del codice e accidentalmente invertiti gli argomenti in scanf():argomenti invertito a scanf()

char i[] = "ABC1\t"; 
scanf(i, "%s"); 

compilazione con gcc -Werror -Wall -Wextra non lamentarsi di questo un po '. Ovviamente, questo codice non funziona, ma perché gcc non mi ha informato che ho invertito gli argomenti? Non è possibile rilevare che i non è una stringa di formato o che il secondo argomento non era un tipo di archivio?

EDIT
Grazie per tutto l'intuizione, Sembra che ho trovato la risposta, c'era una torsione sulla bandiera -Wformat che rende questo "catturabile" (pubblicato qui sotto per riferimento)

risposta

17

Ha! L'ho trovato. Colpire gcc con la bandiera -Wformat=2.

Distacco informazioni di riferimento degli altri:

Ecco il list of flags I found

-Wformat Check calls to printf and scanf, etc., to make sure that the arguments supplied have types appropriate to the format string specified...

Avevo pensato -Wall avevano -Wformat in esso, che lo fa, ma la parte veramente importante su quello che ho appena trovato:

-Wformat is included in -Wall. For more control over some aspects of format checking, the options -Wformat-y2k, -Wno-format-extra-args, -Wno-format-zero-length, -Wformat-nonliteral, -Wformat-security, and -Wformat=2 are available, but are not included in -Wall.

+0

Sì, +1 stavo anche cercando. \ – Omkant

8

Suppongo che non dovrebbe.

int scanf (const char * format, ...); 

i era normalmente convertito in un const char*, tutti i parametri di riposo sono solo "ellissi" e non possono essere controllati in fase di compilazione.

+1

Il i ders utilizzati da GCC di solito hanno il primo parametro contrassegnato come una stringa di formato e quindi possono garantire che i tipi corretti vengano passati ai parametri rimanenti, purché sia ​​fornito '-Wformat'. Credo che questo faccia parte di '-Wall'. – Will

+1

@Will Ma poi di nuovo - un non-const char * è stato passato come una stringa di formato (che è valida di per sé) e quindi il compilatore non ha forzato il controllo dei parametri. Potrebbe averlo fatto se la stringa di formato era 'const char *' o literal. – Lyth

+0

Probabilmente non controlla tra 'char * fmt' e 'const char * fmt'. Qualcuno può dirlo, se il secondo argomento ("ABC \ t") sarà char * o const char *? – anishsane

3

L'inserimento manuale per scanf (uomo scanf) dà il prototipo:

int scanf(const char *format, ...); 

Un char [] è solo un particolare tipo di char *, in modo che il primo argomento è soddisfatta. Gli argomenti secondari sono valutati in fase di esecuzione (se ricordo), quindi non vengono nemmeno presi in considerazione dal compilatore qui. Dal prospetto del compilatore, questo è un bel richiamo alla funzione dato il suo prototipo.

Inoltre, il compilatore non verifica mai se si sta tentando di scrivere in posizioni non valide. La cosa grandiosa (o terribile) di C è che ti permetterà di fare più o meno quello che vuoi, anche se ciò che vuoi è una cattiva idea.

+2

È vero che 'scanf' da solo accetta questi, ma in glibc, compilato con gcc, scanf ha' __attribute __ ((format (scanf, 1, 2))) 'che dice al compilatore di assicurarsi che i parametri siano corretti, anche se questo non è applicato dalla dichiarazione di 'scanf'. – Shahbaz