2010-09-16 10 views
15

Ho scritto un programma che stampa un tavolo. Non ho incluso la sintassi di ritorno nella funzione principale, ma ancora ogni volta che digito echo $? visualizza 12.Perché una funzione principale senza un'istruzione return restituisce il valore 12?

mio codice sorgente:

#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); 
    } 
} 

non ho scritto di ritorno 12, ma ancora restituisce 12 ogni volta che eseguire il programma.

Grazie.

+1

+1 buona domanda. :) – Pavitar

+0

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

risposta

19

Come dice Swegi, è un comportamento non definito. Come Steve Jessop et al dicono, il suo comportamento non specificato prima di C99, e specificato in C99 (il comportamento osservato non è conforme a C99)

Cosa succede in realtà nella maggior parte degli ambienti è che il valore di ritorno dall'ultimo printf è lasciato nel registro utilizzato per i valori di ritorno.

Così sarà 11 per n == 0, 12 se n è una cifra, 14 per due cifre n, 16 per tre cifre n, ecc

+5

In realtà è un comportamento non specificato. –

+0

+1: bella risposta neutra alla piattaforma (chi ha una macchina reale basata su stack?;)) – snemarch

+1

(-1, beh, vediamo) perché non è un comportamento non definito, ma in C89 è specifico dell'implementazione e in C99 il comportamento osservato è chiaramente non conforme. (+1 per una bella spiegazione di cosa sta succedendo, beh siete fortunati) –

1

comportamento indefinito

+2

Da 5.1.2.2.3 Fine del programma: "Se il tipo di ritorno della funzione principale è un tipo compatibile con int ... raggiungendo il} che termina la funzione principale restituisce un valore di 0 ". Ma quella specifica sembra essere nuova in 'c99' (non in' ansi'). –

+1

@jleedev: il testo 'C89' è simile: "Se viene raggiunto il} che termina la funzione principale, lo stato della terminazione restituito all'ambiente host non è specificato." (src: http://www.vmunix.com/~gabor/c/draft.html) – pmg

+1

@ pmg: Non lo trovo molto simile. Uno di loro richiede un comportamento specifico di implementazione, le altre forze restituiscono '0'. –

1

Se siete a tutti familiarità con il linguaggio assembly, si può ricordare che il "valore di ritorno" di una funzione viene fatta passare attraverso il registro EAX.

In questo caso, il valore di ritorno viene letto da EAX. Che, in questo caso, sembra essere 12.

Tuttavia, non si sta impostando esplicitamente questo valore, è semplicemente un artefatto dal resto del codice (o forse solo caso).

Come è stato detto, questo è sicuramente undefined behavior. Se sei semplicemente curioso del perché di questi risultati, ti preghiamo di prendere in considerazione questa spiegazione.

Ma non tentare, in nessuna circostanza, di utilizzare intenzionalmente questo valore come qualcosa di significativo.

+6

Questo è limitato alle architetture x86. Possono essere i più comuni, ma dichiararlo come fatto universale è sicuramente scorretto. –

+5

No questo non è un comportamento non definito. Per C89 è specifico di implementazione e per C99 '0' deve essere restituito. –

+0

Bene su ARM non lo stesso si può dire per R0 – doron

0

Il vostro programma sta causando un comportamento indefinito non restituendo qualsiasi cosa quando dovrebbe, in tal modo il chiamante in genere catturerà quanto mai il valore del registro eax (su x86, rax su x64) è al momento del ritorno della procedura, che è generalmente spazzatura dall'ultimo uso di eax (per funzioni che ritornano valori o semplicemente registro basato su vars), in questo caso è probabilmente la quantità di caratteri che printf ha scritto sul buffer stdout

18

Risposta perché tutte le risposte esistenti dicono che è un comportamento indefinito, che non è vero, quindi non ho nulla circuito integrato un upvote.

In C89 (grazie al PMG per il riferimento a un draft standard), 5.1.2.2.3:

Un ritorno dalla chiamata iniziale alla funzione principale è equivale a chiamare la funzione di uscita con il valore restituito dalla funzione principale come argomento. Se viene raggiunto il} che termina la funzione principale, lo stato di terminazione restituito all'ambiente host è non specificato.

In C99, citazione da n1256, 5.1.2.2.3:

Se il tipo di ritorno della funzione principale è un tipo compatibile con int, un ritorno dalla chiamata iniziale la funzione principale è equivalente alla chiamare la funzione di uscita con il valore restituito da la funzione principale è il suo argomento; arrivando al} che termina la funzione principale restituisce un valore pari a 0. Se il tipo restituito non è compatibile con int, lo stato di terminazione restituito all'ambiente host non è specificato.

Quindi, non è "un comportamento indefinito": si comporta come se le main funzione ritorna, ma in C89 il valore restituito non è specificato dalla norma. Per il tuo programma di esempio, sulla tua implementazione, il valore restituito sembra essere 12, presumibilmente per il motivo che dice Ben Voigt. Dato che sei su Linux, probabilmente non è una grossa modifica compilare il tuo codice come C99 (o comunque, compilarlo usando la modalità C99 quasi-compatibile di gcc).

Per qualsiasi funzione che restituisce un valore, diverso da main, si è comportamento indefinito, a meno che il chiamante non utilizza il valore di ritorno (n1256, 6.9.1/12):

Se il} che termina una funzione è raggiunto, e il valore della chiamata della funzione viene utilizzato dal chiamante, il comportamento dello non è definito.

non sono sicuro se la chiamata iniziale main dovrebbe essere menzionato come escluso da questa regola generale. Non ha bisogno di essere: dal POV dello standard, quella chiamata non ha un chiamante, quindi penso che il valore della chiamata di funzione non sia "usato dal chiamante", anche se diventa lo stato di terminazione per il programma.

+2

L'attuale standard ISO C 1990 (e presumibilmente lo standard ANSI del 1989) afferma che "lo stato di terminazione restituito all'ambiente ospite non è definito". Apparentemente la parola è stata cambiata da "non specificato" a "indefinito" tra la bozza e la pubblicazione dello standard. Per inciso, [quel collegamento sembra essere morto] (http://www.vmunix.com/~gabor/c/draft.html). –

Problemi correlati