Newsgroup: it.comp.lang.c
Titolo: Dubbi su "return" ed "exit()" riguardo al "main()"

Ciao a tutti,
ho un dubbio che mi arrovella un po'...
dichiarando la funzione "main()" come
	int main(int argc, char *argv[])
	{
		...
	}
si presume che essa debba ritornare un intero, ovvero presentare almeno
un'istruzione "return <int>" in qualche punto del codice, altrimenti essa
non restituisce un valore di ritorno (che in questo caso viene ricevuto
dalla shell, ma non solo).
Da quel che ne so io, la funzione standard "exit()" dovrebbe fare lo
stesso, anzi, non proprio (la pagina di man dice: "exit - cause normal
program termination"), in quanto la "exit()" *termina* un programma,
mentre l'istruzione "return" ritorna un valore interrompendo l'esecuzione
nel punto in cui si trova.
Ecco, il mio vero problema è questo:
sempre nell'esercizio per l'Università che sto per ultimare, in tutti i
programmi che contengono un "main()" i punti di uscita sono costituiti da
funzioni "exit()" con i rispettivi valori di errore (quindi non compare
mai la "return" come istruzione per terminare un programma, bensì solo
"exit()").
Il fatto è che, usando come flags di compilazione:
	-O2 -ansi -std=c89 -Wall -Werror -pedantic
su GNU/Linux (con GCC v3.4.5) tutto funziona a meraviglia senza neanche il
più piccolo warning, mentre su Sun Solaris (con GCC v3.4.1, architettura
SPARC), per ogni file sorgente contenente un "main()", ottengo un unico
errore (in realtà è un warning):
	control reaches end of non-void function
la cui riga segnalata corrisponde sempre con la parentesi graffa che
chiude il blocco di codice della dichiarazione del "main()" (in sostanza,
l'ultimo carattere di ogni sorgente :-).
In realtà, io ho badato bene a non lasciare nessuna condizione irrisolta
(rischiando quindi di non fornire una possibilità di terminazione in uno
o più casi), fornendo quindi sempre un punto in cui uscire, ma l'unica
cosa che mi viene in mente è che ci voglia proprio l'istruzione "return"
(infatti, mettendone una di prova subito prima dell'ultima graffa, il
problema non si presenta più).
Qualcuno potrebbe gentilmente chiarirmi un attimino le idee? Sicuramente
mi manca qualche nozione, ma non riesco a capire l'importanza così
fondamentale di una "return" nel caso del "main()" (tra l'altro richiesta
solo su Solaris...).
Grazie mille!
Un saluto :-)
-- 
      ______________
(*)--[::::::::::::::]--(*)
(*)--[>::d1s4st3r::<]--(*)
(*)--[::::::::::::::]--(*)
(*)--[::wonder'ing::]--(*)
(*)--[::what's::::::]--(*)
(*)--[::^happening::]--(*)
(*)--[::|^::::::::::]--(*)
(*)--[__||__________]--(*)
 |......................|
http://xoomer.virgilio.it/
 +------> mental_insomnia/
(*) <-------------------+

 l'ultimo carattere di ogni sorgente :-).
E` un'errore della flow analysis del compilatore, anche se e` strano che
il gcc dia comportamente diversi (non ho sparc sotto mano, ma su ARM
funge). Il gcc sa che la funzion exit() non e` una funzione normale (nel
senso che non ritorna mai).
Al limite metti un return <qualcosa> al posto della ultima exit per
farlo contento, oppure cerca nel bugzilla del gcc per vedere se e` un
problema noto.
Luca
-- 
Home: 
http://kronoz.cjb.net
La differenza fra l'intelligenza e la stupidita`?
All'intelligenza c'e` un limite.

 Giovanni
Wow, figo! Ma quante ne sai?!?
Dici quindi che dovrei usare solo le "return" (visto che comunque il
parametro passato a "exit()" e' proprio il loro valore di ritorno)?
In pratica, se ho ben capito:
	"return 666"   equivale a   "exit(666)"
Ho provato a passare a GCC il C99 come standard, ma i risultati che
ottengo sono sempre gli stessi (ovvero su GNU/Linux nessun warning, invece
su Solaris il solito warning "control reaches end of non-void function").
Grazie ancora per avermi risposto! :-)))


Giò
-Tutto ciò che può esistere, esiste.
          (Tullio Regge)

 su Solaris il solito warning "control reaches end of non-void function").
Sembra che il gcc interpreti la chiamata a exit() in modo corretto come 
equivalente a return.



Ciao,
mi permetto di aggiungere alcune informazioni a ciò che ti è già stato 
detto. Innanzi tutto mi vien da pensare che chi ha scritto il gcc abbia 
voluto essere un po' più di manica larga trattando la exit alla stregua del 
return; infatti in molti dei compilatori che mi è capitato di utilizzare, 
quando ho avuto la necessità di utilizzare la exit nella main, per evitare i 
warning ho dovuto modificare il prototipo da
int main(int argc, char *argv[])
a
void main(int argc, char *argv[])
In quest'ultimo caso ho avuto occasione di notare che se la funzione main 
termina senza la chiamata alla exit, questa viene invocata automaticamente 
con 0 (zero) come parametro. Comunque, la differenza fondamentale è che la 
funzione exit, che non è rientrante, prima di terminare esegue il flush di 
tutti i buffer (compreso stdout ed stderr) e chiude tutti i file aperti dal 
programma ad eccezione di quelli standard ma prima di tutto ciò, se 
esistono, chiama in ordine LIFO tutte le funzioni di chiusura passategli 
dalla chiamata alla funzione atexit. Infine, così come con il return, il 
parametro passato alla exit diverrà il valore ERRORLEVEL del sistema ospite.
Spero di esserti stato utile.
Un saluto.