2010-09-16 14 views
15

Napisałem program, który drukuje tabelę. Nie zawarłem składni powrotu w funkcji głównej, ale nadal za każdym razem, gdy wpisuję echo $? wyświetla 12.Dlaczego główna funkcja bez instrukcji return zwraca wartość 12?

mojego kodu źródłowego:

#include <stdio.h> 


int main(void) 
{ 
    int ans,i,n; 
    printf("enter the no. : "); 
    scanf("%d",&n); 

    for(i=1;i<=10;i++) 
    { 
     ans = n*i; 
     printf("%d * %d = %d\n",n,i,ans); 
    } 
} 

nie pisałem powrotny 12, ale wciąż powraca 12 za każdym razem jak wykonać program.

Dzięki.

+1

+1 dobre pytanie. :) – Pavitar

+0

http://stackoverflow.com/questions/204476/what-should-main-return-in-and-c –

Odpowiedz

19

Jak mówi swegi, jest to niezdefiniowane zachowanie. Jak Steve Jessop wsp powiedzieć, że to nieokreślone zachowanie przed C99, oraz określone w C99 (obserwowane zachowanie jest non-conformant do C99)

Co właściwie dzieje się w większości środowisk jest to, że wartość zwracana z ostatniego printf pozostało w rejestrze używanym do zwracania wartości.

Więc to będzie 11 dla n == 0, 12 jeśli n jest jedna cyfra, 14 dla dwóch cyfr n 16 za trzy cyfry n itd

+5

To nieokreślone zachowanie. –

+0

+1: niezła odpowiedź neutralna dla platformy (kto ma maszynę opartą na stosie?;)) – snemarch

+1

(-1, zobaczmy), ponieważ nie jest niezdefiniowanym zachowaniem, ale w C89 jest to implementacja specyficzna, aw C99 zachowanie, które jest obserwowane, wyraźnie nie jest zgodne. (+1 za miłe wyjaśnienie, co się dzieje, cóż, masz szczęście) –

1

niezdefiniowane zachowanie

+2

Od 5.1.2.2.3 Zakończenie programu: "Jeśli typ powrotu funkcji głównej jest typ zgodny z int ... osiągając}, który kończy główną funkcję, zwraca wartość 0 ". Ale ta specyfikacja wydaje się być nowa w 'c99' (nie w' ansi'). –

+1

@jleedev: Tekst 'C89' jest podobny: "Jeśli zostanie osiągnięty koniec funkcji głównej, stan zakończenia zwracany do środowiska hosta jest nieokreślony." (src: http://www.vmunix.com/~gabor/c/draft.html) – pmg

+1

@pmg: Nie uważam tego za bardzo podobne. Jeden z nich przypisuje zachowanie specyficzne dla implementacji, pozostałe siły to powrót '0'. –

1

Jeśli w ogóle zna asemblerze, można przypomnieć, że „wartość zwracana” z funkcji jest przekazywana poprzez rejestr EAX.

W tym przypadku wartość zwracana jest odczytywana z EAX. Który w tym przypadku przypadkiem jest 12.

Jednak nie określasz wyraźnie tej wartości, jest to po prostu artefakt od reszty kodu (lub może po prostu przypadek).

Jak już powiedziano, jest to zdecydowanie undefined behavior. Jeśli jesteś po prostu ciekawy, dlaczego tak się dzieje, rozważ to wyjaśnienie.

Ale pod żadnym pozorem nie wolno próbować używać tej wartości jako znaczącej.

+6

To jest ograniczone do architektur x86. Mogą być najczęstsze, ale stwierdzenie tego jako faktu uniwersalnego jest zdecydowanie nieprawidłowe. –

+5

Nie jest to niezdefiniowane zachowanie. Dla C89 jest to implementacja specyficzna, a dla C99 '0' musi zostać zwrócona. –

+0

Cóż, na ARM można to samo powiedzieć o r0 – doron

0

Twój program jest przyczyną niezdefiniowanej zachowanie przez nie wraca cokolwiek, kiedy powinno, w związku z tym osoba wywołująca generalnie będzie chwytała to, co kiedykolwiek wartość rejestru eax (na x86, rax na x64) jest w momencie powrotu procedury, co jest ogólnie bzdurą od ostatniego użycia eax (przez funkcje zwracające wartości lub tylko rejestry oparte na vars), w tym przypadku prawdopodobnie ilość znaków char, które printf zapisał na stdoutowym buforze

18

Odpowiedzi, ponieważ wszystkie istniejące odpowiedzi mówią, że jest to niezdefiniowane zachowanie, co nie jest prawdą, więc nie mam nic C uprowadzenie.

w C89 (dzięki PMG w odniesieniu do draft standard) 5.1.2.2.3:

Powrót z pierwszego połączenia do głównych funkcji jest równoważne wywołaniu funkcji wyjścia z wartość zwrócona przez funkcję główną jako jej argument. Jeśli zostanie osiągnięte} , które kończy działanie głównej funkcji, stan zakończenia powracający do środowiska hosta to nieokreślony.

W C99, cytując za pomocą n1256, 5.1.2.2.3:

Jeśli zwracany typ głównego funkcji jest typ zgodny z int, powrót z początkowego wywołania główną funkcją jest równoważna wywołując funkcję wyjścia z wartością zwróconej przez główna funkcja jako jego argument; docierając do}, że kończy się, funkcja główna zwraca wartość 0. Jeśli typ powrotu nie jest kompatybilny z int, stan zakończenia zwrócono do środowiska hosta środowisko nie jest określone.

Tak, to nie jest „niezdefiniowane zachowanie”: zachowuje się jak gdyby main zwrotów funkcyjnych, ale w C89 zwrócona wartość nie jest określona przez standard. W przypadku twojego przykładowego programu, na twojej implementacji, zwracana wartość wydaje się konsekwentnie wynosić 12, prawdopodobnie z powodu, dla którego mówi Ben Voigt. Skoro jesteś na Linuksie, prawdopodobnie nie jest to duża zmiana, aby skompilować twój kod jako C99 (lub zresztą skompilować go przy użyciu prawie zgodnego z GCC trybu C99).

dowolną funkcję, która zwraca wartość, inne niż main to jest niezdefiniowane zachowanie chyba rozmówca nie wykorzystuje wartość powrotną (n1256, 6.9.1/12):

Jeśli}, który kończy działanie, osiąga wartość , a wywołanie funkcji wywołuje funkcję , zachowanie jest niezdefiniowane.

Nie jestem pewien, czy początkowe połączenie z numerem main należy wymienić jako wyłączone z tej ogólnej zasady. Nie musi to być: z POV standardu, że wywołanie nie ma wywołującego, więc myślę, że wartość wywołania funkcji nie jest "używana przez wywołującego", mimo że staje się stanem zakończenia dla programu.

+2

Faktyczny standard ISO C z 1990 r. (I prawdopodobnie standard ANSI z 1989 r.) Mówi, że "stan zakończenia zwracany do środowiska hosta jest niezdefiniowany". Najwyraźniej słowo zostało zmienione z "nieokreślony" na "nieokreślony" między wersją roboczą a publikacją standardu. Nawiasem mówiąc, [link wydaje się być martwy] (http://www.vmunix.com/~gabor/c/draft.html). –

Powiązane problemy