2012-10-25 15 views
13

byłem (szybko) pisanie kodu i przypadkowo odwrócony argumenty w scanf():Odwrócony argumenty scanf()

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

Kompilacja z gcc -Werror -Wall -Wextra nie narzekać na ten jeden bit. Oczywiście ten kod nie działa, ale dlaczego gcc nie poinformował mnie, że odwróciłem argumenty? Czy nie może wykryć, że i nie jest łańcuchem formatu lub, że drugi argument nie był typem składowania?

EDIT
Dzięki za wglądu wszystkich, Wygląda na to, znalazłem odpowiedź, nie było niespodzianką na fladze -Wformat że czyni to „połów” (pisał go poniżej dla porównania)

Odpowiedz

17

Ha! Znalazłem to. Udało się trafić w gcc z flagą -Wformat=2.

zamieszczaniu info dla odniesienia innymi:

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

Przypuszczałem -Wall miał -Wformat w to, co robi, ale bardzo ważną częścią tego, co właśnie Znaleziono:

-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

Tak, +1 też tego szukałem. \ – Omkant

8

Przypuszczam, że nie powinien.

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

i się zwykle przekształca się w const char* wszystkie parametry reszta jest po prostu „elipsa” i nie może być sprawdzane w czasie kompilacji.

+1

Hej ders używane przez GCC zwykle mają pierwszy parametr oznaczony jako ciąg formatu, a następnie mogą zapewnić, że poprawne typy są przekazywane do pozostałych parametrów, pod warunkiem, że podano '-Wformat'. Wierzę, że jest to część '-Wall'. – Will

+1

@Will Ale potem jeszcze raz - nie const char * został przekazany jako ciąg formatu (który jest ważny sam), więc kompilator nie wymusił sprawdzenia parametrów. Mogłoby tak być, gdyby ciąg formatu był "const char *" lub literał. – Lyth

+0

Prawdopodobnie nie sprawdza pomiędzy "char * fmt" i "const char * fmt". Czy każdy może powiedzieć, czy drugi argument ("ABC \ t") będzie char * lub const char *? – anishsane

3

Instrukcja wejście do scanf (mężczyzna scanf) daje prototype:

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

char [] jest właśnie specjalny typ char *, więc pierwszy argument jest spełniony. Wtórne argumenty są oceniane w czasie wykonywania (jeśli sobie przypomnę), więc nie są nawet brane pod uwagę przez kompilator tutaj. Z punktu widzenia kompilatora jest to znakomite wezwanie do funkcji ze względu na jego prototyp.

Ponadto kompilator nigdy nie sprawdza, czy próbujesz pisać do nieprawidłowych lokalizacji. Wspaniałą (lub straszną) rzeczą w C jest to, że pozwoli ci robić mniej więcej to, czego chcesz, nawet jeśli to, co chcesz, jest złym pomysłem.

+2

Prawdą jest, że 'scanf' sam je akceptuje, ale w glibc skompilowanym z gcc, scanf ma' __attribute __ ((format (scanf, 1, 2))), co mówi kompilatorowi, aby upewnić się, że parametry są poprawne, nawet jeśli nie jest to wymuszone przez deklarację 'scanf'. – Shahbaz