2011-01-11 12 views
5

poniżej podanego programu działa bez włączania <stdio.h>? Dlaczego to działa?bez uwzględnienia <stdio.h>

int main() 
{ 
    printf("integra"); 
    return 0; 
} 
+1

"Dlaczego to działa?" nie jest poprawnym pytaniem, gdy napisałeś kod z niezdefiniowanym zachowaniem. –

+0

@R ..: może to powód, by zakładać, że venkat sam nie wymyślił tego pytania, ale jego nauczyciel? – Bart

+0

Możliwy duplikat [Dlaczego #include jest \ * not \ * wymagany do użycia printf()?] (Http: // stackoverflow.com/questions/336814/why-include-stdio-h-is-not-required-to-use-printf) – vaxquis

Odpowiedz

1

Niektóre (stare?) Kompilatory nie wymagają prototypów przed wywołaniem funkcji.

+0

Często dopuszczalne jest używanie niezadeklarowanych funkcji w C (ale nie sądzę w tym przypadku), ale niezalecane . – Philipp

7

w starszym standardzie, funkcja nieoznakowana przyjmuje argument int i zwraca wartość. Twój char* ma ten sam rozmiar (32-bitowy) co int, więc wszystko działa.

Po prostu tego nie rób.

+0

Witam, działa również main() { if (isalnum (';')) printf ("znak; nie jest alfanumeryczny"); if (isalnum ("A")) printf ("znak A jest alfanumeryczny"); return 0; } – venkat

+0

daj mi jasne wyjaśnienie – venkat

+1

sprawdź swoją stronę podręcznika. 'isalpha()' to 'int isalpha (int)'. ten mecz, co powiedziałem. –

5

printf() jest zdefiniowana tylko w libc.so

dynamiczny linker rozwiąże printf symbol() w libc, ponieważ nie obejmowały go

libc jest domyślny w gcc dla każdego programu

+0

Dynamiczny linker rozwiąże symbol printf **, nawet jeśli posiadasz deklarację **. (Pomyśl o tym!) – user562374

1

Gdy używasz funkcji, która nie została zadeklarowana, kompilator przyjmie, że ta funkcja zwraca wartość int i przyjmuje nieokreśloną, ale ustaloną liczbę argumentów.

Jeśli to przyporządkowanie pasuje do definicji funkcji, a podane argumenty również pasują (modulo domyślne promocje argumentów) do parametrów oczekiwanych przez funkcję, to wszystko jest w porządku.
Jeśli założenie jest niepoprawne (np. Dla printf, która jest funkcją variadic) lub gdy argumenty nie są zgodne, wyniki są niezdefiniowane. Jedną z nieprzyjemnych rzeczy o nieokreślonym zachowaniu jest to, że może działać zgodnie z oczekiwaniami.

3

Jak zauważył Abi, twój kod buduje się pomyślnie bez włączania stdio.h, ponieważ linker domyślnie stosuje systemową bibliotekę std dla niezdefiniowanego symbolu (printf). GCC zwykle ostrzega Cię o takich przypadkach.

Let test.c być: test.c

1: int main() 
2: { 
3: printf("test\n"); 
4: return 0; 
5: } 

Budynek z GCC 4.2.1 na Mac OSX:

$ gcc test.c 
test.c: In function ‘main’: 
test.c:3: warning: incompatible implicit declaration of built-in function ‘printf’ 
$ ./a.out 
test 

Można wyłączyć tę domyślną łączenie poprzez określenie opcji linkera GCC -nostdlib (lub -nodefaultlibs) wraz z -lgcc (jak instrukcja GCC zaleca)

$ gcc -nostdlib -lgcc test.c 
test.c: In function ‘main’: 
test.c:3: warning: incompatible implicit declaration of built-in function ‘printf’ 
Undefined symbols: 
    "_puts", referenced from: 
     _main in cc3bvzuM.o 
ld: symbol(s) not found 
collect2: ld returned 1 exit status 
$ 
8

Definicja printf() znajduje się w libc.so, a dynamiczny linker zajmie się tym, nawet jeśli nie uwzględnisz pliku nagłówkowego. Podczas kompilacji, printf() będzie niezdefiniowanym symbolem i zakłada, że ​​może znaleźć definicję później w bibliotece libc. Plik nagłówkowy po prostu nadaje typ proto i tłumi kompilator (ostrzeżenia), stwierdzając, że definicja prototypu jest obecna w glibc. Zasadniczo pliki nagłówkowe są uwzględniane tylko po to, aby upewnić się, że definicje są dostępne w naszych bibliotekach, aby pomóc programistom.

Powiązane problemy