Odpowiedz

10

Tak powołując printf() bez odpowiedniego prototypu (ze standardowego nagłówka <stdio.h> lub z prawidłowo pisemnej deklaracji a) powołuje niezdefiniowanej zachowanie.

Jak udokumentowano w C11 załączniku J (informacyjny tylko)

J2 zachowanie niezdefiniowane

  • Dla wywołania funkcji bez prototypu funkcji w zakresie, w którym funkcja jest określona w funkcji prototyp, prototyp kończy się wielokropkiem lub typy argumentów po promocji nie są zgodne z typami parametrów (6.5.2.2).

Ten załącznik nie jest normatywny, ale wyraźnie dokumentuje powyższy kod jako przykład niezdefiniowanego zachowania.

W bardziej praktyczne słowy, w przypadku braku prototypu printf kompilator generuje sekwencję dzwonienia jak printf zdefiniowanego jako int printf(const char*, int), które mogą być bardzo różne i niezgodne z aktualną wykonania printf w standardowym biblioteki zdefiniowane jako int printf(const char restrict *format, ...).

Starożytne ABI były na tyle regularne, że nie stanowiłoby to problemu, ale nowoczesne (np. 64-bitowe) ABI używają bardziej wydajnych sekwencji wywołujących, które czynią powyższy kod zdecydowanie niepoprawnym.

W konsekwencji, ten słynny klasyczny program C zawiedzie też bez #include <stdio.h> lub przynajmniej właściwy prototyp printf:

int main(void) { 
    printf("Hello world\n"); // undefined behavior 
    return 0; 
} 
+0

drobne zastrzeżenie: Wywoływanie 'printf()' bez odpowiedniej prototyp wywołuje niezdefiniowany zachowanie. Nieważne, czy pochodzi z ''. Program może alternatywnie dostarczyć swoją własną prototypową deklarację 'printf'. – hvd

+0

@hvd: zgodził się, będę przeredagować odpowiedź. Prototyp może pochodzić z innego źródła, ale musi być zgodny z rzeczywistą definicją 'printf' w bibliotece C. – chqrlie

+4

Cóż, ściśle mówiąc, odpowiedź na twoje pytanie (patrz tytuł) brzmi * nie *. Jak sam to zauważyłeś, plik nagłówkowy [zamiast "" może być zastąpiony przez * poprawnie napisaną deklarację *. – Matsmath