2010-06-22 17 views
30

Czytam z książki o wstępną defination żeO Wstępna definicja

A tentative definition is any external data declaration that has no storage class specifier and no initializer. A tentative definition becomes a full definition if the end of the translation unit is reached and no definition has appeared with an initializer for the identifier

Proszę wyjaśnić, co oznacza, że ​​powyższe stwierdzenie. Różnica między deklaracją a definicją? Z tego powodu się pomyliłem. :( A dlaczego nie ten program daje błąd:

#include<stdio.h> 
int a;  //Tentative definition 
int a;  //similarly this declaration too. 
int main() //not getting any error with this code why its so? 
{ 
    printf("hi"); 
} 

Ponadto, co jest nie tak z tym kodem:

#include<stdio.h> 
printf("Hi"); 
int main(void){ 
    return 0; 
} 
+1

W której książce przeczytasz o wstępnej definicji? – Destructor

Odpowiedz

55

Zmienna deklaracja mówi: "w programie jest zmienna o następującej nazwie i typie".

Definicja zmiennej mówi: "Drogi Panie Kompilatorze, proszę przydzielić pamięć dla zmiennej o następującej nazwie i typie."

Tak więc może istnieć wiele deklaracji dla tej samej zmiennej, ale powinna istnieć tylko jedna definicja.

W języku C czyste deklaracje (które nie są również definicjami) poprzedza się słowem kluczowym extern. Tak więc, ponieważ nie masz tego słowa kluczowego w pierwszym przykładzie, masz dwie definicje. Na pierwszy rzut oka wydaje się, że jest to problem (i w rzeczywistości jest to błąd w C++), ale C ma specjalną "wstępną definicję", która pozwala na wiele definicji dla tej samej zmiennej, o ile wszystkie pasują do siebie i najwyżej jeden ma inicjator. Kompilator C, za kulisami, łączy wszystkie wstępne definicje w jedną definicję.

Gdybyś próbował zainicjować obie definicje, tak:

int a = 1; 
int a = 2; 

Wtedy musiałby błąd.

Twoje drugie pytanie jest bardziej proste. W języku C po prostu nie można mieć instrukcji wykonywalnych poza ciałem funkcji. Po prostu nie jest dozwolone. Pomyśl o tym: kiedy możesz oczekiwać, że będzie działał, jeśli pozwolono na to?

+0

@TylerMcHenry: Jest to nielegalne zarówno w C jak i C++, ale kompilatory C implementują to jako typowe rozszerzenie. Zobacz [tę odpowiedź] (http://stackoverflow.com/a/6371156/183120). – legends2k

+4

@ legends2k Nie, to nie jest nielegalne w C ... w pytaniu, które łączysz (a także z pytaniem, że odpowiedź, z którą łączysz się z linkami), dotyczy wielu plików. Wiele (zgodnych) próbnych definicji w tym samym pliku nie stanowi naruszenia. Naruszenie w tym pytaniu pojawia się, ponieważ na końcu jednostki tłumaczeniowej, jeśli istnieją wstępne definicje bez pełnej definicji, zakłada się pełną definicję.To plus wiele plików prowadzi do wielu definicji w czasie łączenia (z wyjątkiem wspólnego rozszerzenia wstępnych reguł definicji do rozpiętości wielu plików). –

+0

Dlaczego jest on poprawny tylko w przypadku zmiennych globalnych, a nie zmiennych lokalnych? W przypadku zmiennych lokalnych pojawia się błąd redeclaracji? –

8

Pierwsze prace, ponieważ oba wasze definicje a są niepewne, co Na końcu jednostki tłumaczeniowej nie widziano żadnej nieprecyzyjnej definicji, więc to, co określiłeś dla atrybutów, jest połączone z wartościami domyślnymi, aby dać ostateczną definicję a, więc " Będą mieć zewnętrzne powiązania, stały czas przechowywania i być zainicjowane na 0.

Problem z drugim nie ma nic wspólnego z wstępnymi definicjami. Twoja printf("Hi"); musi znajdować się wewnątrz funkcji do pracy - nie jest deklaracją ani definicją (próbną lub inną); to nie jest dozwolone.