2010-08-11 12 views
5

Recentemente ho scritto un post:
Weird Error in C++ Program: Removing Printout Breaks ProgramIn che modo i prog ++ C++ ottengono il loro valore di ritorno, quando non viene specificato un ritorno nella funzione?

... in cui stavo cercando di risolvere un problema apparentemente sconcertante, in cui la rimozione di un comunicato cout avrebbe rotto il mio programma.

Come si è scoperto, il mio problema era che mi sono dimenticato di restituire il mio flag true/false success che stavo usando in seguito per la logica.

Ma apparentemente QUALCOSA è stato restituito e che qualcosa era sempre vero se lasciavo quel cout in, ma sembrerebbe "magicamente" diventare falso quando l'ho tirato fuori.

La mia domanda per voi è:
Che cosa determina cosa restituisce una funzione C++ quando non viene eseguito alcun comando di ritorno all'interno della funzione? C'è qualche logica?

Ovviamente dimenticare che il tipo di reso è una cattiva idea. In questo caso, tuttavia, è stato in gran parte dovuto alla natura del mio programma: un lavoro rapido di hacking. In seguito ho deciso che non valeva la pena di includere l'implementazione di un algoritmo per determinare il successo/l'insuccesso della chiamata alla funzione, ma che inavvertitamente ha lasciato il codice dipendente dal rendimento.

modo sconcertante g ++ mi ha dato nessun avviso o errori durante la compilazione del file eseguibile in questo modo:

g++ main.cc -g -o it_util 

La mia versione è: g ++ (GCC) 4.1.2 20.080.704 (Red Hat 4.1.2-44)

Ancora una volta, per salvare altre frustrazioni future nel caso in cui commettano lo stesso stupido errore e si incontrino con lo stesso comportamento apparentemente erratico, qualcuno può illuminare dove una funzione senza un ritorno ottiene il suo valore di ritorno?

Grazie !!

+2

Cosa succede se si compila con il flag '-Wall'? –

+4

Da qualunque cosa si trovi su 'eax', suppongo? –

+0

Il valore restituito è specifico per macchina/architettura. Se fai un fischio su quale sistema operativo/computer/compiler combo lavori (32 bit/64 bit) e di quale tipo è il valore di ritorno previsto (int, struttura, puntatore, virgola mobile), qualcuno potrebbe aiutarti qui. Saluti rbo –

risposta

5

Sulle convenzioni di chiamata x86, il valore di ritorno per numeri interi e puntatori si trova nel registro EAX. Il seguente è un esempio di tale:

int func() { 
    if(0) return 5; // otherwise error C4716: 'func' : must return a value 
} 
int main() { 
    int a; 
    a = func(); 
} 

compilazione con cl.exe /Zi, MSVC++ 10:

push ebp 
mov  ebp, esp 
push ecx 
call [email protected]@YAHXZ ; func(void) 
mov  [ebp+a], eax ; assumes eax contains the return value 
xor  eax, eax 
mov  esp, ebp 
pop  ebp 
retn 

Naturalmente, questo è un comportamento indefinito.

5

Non c'è alcuna logica e la maggior parte dei compilatori C++ dovrebbe contrassegnarlo con un avviso. Ha permesso di scorrere all'indietro compatibilità C.

In K & R C, non c'era tipo void, e quando un tipo sia specificato, IT predefinito int. Così,

myfunc() {....} 

Era techincally una funzione che restituisce un int, ma la maggior parte dei programmatori utilizzato questa forma di routine non restituire un valore.

Il compilatore doveva dare un senso a questo. Quindi, la convenzione è diventata, il return avrebbe messo qualcosa in un registro. E l'assegnazione nella routine chiamante toglierebbe il valore dal registro. Ora, se il destinatario non ha mai emesso un reso, niente specifico verrà inserito in tale registro. Ma avrebbe ancora del valore (casuale) in esso, che verrebbe assegnato ciecamente al chiamante.

1

Dipende dalla convenzione di chiamata. Ad esempio, per un ritorno di numeri interi a 32 bit su una piattaforma Intel, si ottiene ciò che si trova nel registro eax.

4

Dalla sezione standard C++ 6.6.3 L'istruzione return

scorre l'estremità di una funzione è equivalente ad un rendimento senza valore; questo comporta un comportamento non definito in una funzione di ritorno valore.

C'è un'eccezione (come da 3.6.1/5):

Se il controllo raggiunge la fine principale senza incontrare un'istruzione return , l'effetto è quello di esecuzione return 0;

Il motivo di questo è sintatticamente consentito è messo bene per James Curran. Ma con l'opzione -Wall (come commentato da Neil) dovresti essere avvisato di questo comportamento; qualcosa come "Non tutti i percorsi di controllo restituiscono valore in una funzione di ritorno valore ...".

+0

C'è ogni caso in cui questo è un comportamento auspicabile nel moderno C++? Perché non c'è un avviso di default (ad esempio perché devi attivare -Wall in g ++ per vedere l'errore?)? –

+0

@Jason: immagina di avere una maschera modello 'modello T func() {return; } template <> int func() {return 1; } modello T func1() {return func (); } int main() {func (); func (); ritorno 0; } ' Ora il compilatore non può protestare basandosi solo sulla parola chiave' return', può? – Abhay

+0

@ Jason: g ++ non fornisce avvisi per impostazione predefinita. È così e basta. –

0

Con un compilatore moderno probabilmente otterrete un avviso utilizzando -Wall

Ma se non restituisce un valore, di solito si otterrà spazzatura.

0

"Che cosa determina cosa restituisce una funzione C++ quando non viene eseguito alcun comando di ritorno all'interno della funzione? C'è qualche logica?"

Il tipo all'inizio della funzione.

Esempio:

int mucca() { int temperatura; temp di ritorno; }

Se non si restituisce il tipo corretto o non si restituisce nulla, il compilatore dovrebbe lamentarsi. Modifica: Oh merda, ho appena letto le tue bandiere. Devi attivare più flag man, -W -Wall -pedantic. Leggi il manuale di g ++.

A meno che non si disponga di una funzione di annullamento. Quindi non devi restituire nulla o puoi avere un puntatore per giocare.

void somefunction (int * ptr_int) { int temp = * ptr_int; temp + = 1000; this-> ptr_int = temp; }

Credo che il codice precedente funzioni, è passato un po 'di tempo da quando ho codificato in C++.

Problemi correlati