W trybie ścisłej zgodności (to znaczy "w teorii") wywołujesz niezdefiniowane zachowanie (które jest złe), gdy wywołujesz funkcję, która pobiera zmienną liczbę argumentów bez prototypowej deklaracji funkcji w zakresie. Oznacza to, że kompilator może robić wszystko, co mu się podoba, używając programu, który używa printf()
bez prototypu z #include <stdio.h>
lub deklaracji równoważnej. "Wszystko, co lubi" obejmuje prawidłowe działanie jako jedna z opcji; to wydaje się być opcją wybraną przez twój przykład.
W praktyce kod będzie działał poprawnie z większością praktycznych kompilatorów, nawet bez formalnej deklaracji funkcji printf()
.
Jak wskazał qrdl, funkcja została znaleziona, ponieważ kompilator C łączy się z biblioteką C.
Należy zauważyć, że komentarz Chrisa Younga na temat C99 i "implicit int" jest dokładny, ale reguła dotycząca "funkcji zmiennych argumentów musi mieć prototyp w zakresie" dotyczy zarówno C89, jak i C99. Większość kompilatorów nie pracuje domyślnie w trybie ścisłej kompatybilności C99, ponieważ jest zbyt wiele kodu, który by się nie skompilował.
Chris Młoda komentuje:
Aby wyjaśnić, mój komentarz był na C99 usuwania ukrytych deklaracji. Mówiąc "implicit int", myślę, że odnosisz się do funkcji C89 zezwalania na deklaracje takie jak foo (void); to znaczy int foo (void) ;, coś C99 również zostało usunięte.
Chris jest, oczywiście, poprawny. Z normy C99 usunięto dwie cechy "ukrytej deklaracji".Przedmowa do normy wymienia je jako:
- usunąć niejawny
int
- usunąć niejawny deklarację funkcji
nie myślałem (i stąd nie pisania) wystarczająco jasno. Niemniej jednak zarówno C89, jak i C99 wymagają prototypu w zakresie funkcji, które pobierają zmienną liczbę argumentów.
Dla ilustracji
extern int pqr();
int main(void)
{
int i = pqr(1, 3);
return i;
}
bez pierwszej linii, to jest fragment o właściwej C89 z domniemanym zgłoszenia funkcji pqr()
jako funkcję, która zwraca całkowitą (z nieokreślonymi argumentów). Jeśli pierwszy wiersz zostanie zastąpiony przez extern pqr();
, jest to poprawny fragment C89 z jawną deklaracją pqr()
jako funkcją zwracającą liczbę całkowitą (z nieokreślonymi argumentami), ale typem powrotu jest "niejawny int
". Jak napisano, funkcja jest jawnie zadeklarowana i ma wyraźny typ zwracany int
- ale wciąż ma nieokreślone argumenty. Uważam, że jest to ważne C99 - choć nie jest to całkowicie pożądane. Oczywiście, GCC (3.4.4) akceptuje to z opcjami "-std=c99 -pedantic
". Idealnie, deklaracja funkcji powinna zawierać pełny prototyp. (I gdyby pqr()
zostały zdefiniowane z elipsą, prototyp ten byłby wymagany w teorii!)
Należy zauważyć, że w C89/C90 należy podać wartość zwracaną z 'main()' .C99 pozwala pominąć 'return 0;' lub odpowiednik od końca 'main()'. –