Perché `main` non può restituire un doppio o una stringa piuttosto che int o void?


38

In molti linguaggi come C, C ++ e Java, il mainmetodo / funzione ha un tipo di ritorno di voido int, ma non di doubleo String. Quali potrebbero essere i motivi alla base di ciò?

So un po 'che non possiamo farlo perché mainviene chiamato dalla libreria di runtime e si aspetta una sintassi simile int main()o int main(int,char**)così dobbiamo attenerci a questo.

Quindi la mia domanda è: perché mainha la firma del tipo che ha e non una diversa?


19
Cosa sarebbe un valore doppio di ritorno significa ? Cosa sarebbe un valore di ritorno di stringa significa ?

1
ki capisco che non significa nulla, ma altri motivi e convenzioni?
JAVA,

1
penso che non significhi nulla, semplicemente perché universalmente è stato scelto quello 0 per l'uscita normale e uno zero per un anormale. Un int è stato scelto come il tipo di dati più semplice con ampia compatibilità linguistica. @ delnan
JAVA

@sunny Da quello che sono stato in grado di raccogliere dalla mia esperienza con sistemi operativi simili a Unix, 0 viene utilizzato come "uscita normale" (0 errori) perché non è ambiguo rispetto ad altri valori interi. Poiché la maggior parte (non tutti) i linguaggi moderni sono progettati per essere simili a (se non progettati sul retro) di C, e poiché C è stato usato per scrivere Unix, direi che è stata una decisione storica di KnR.
Jamie Taylor,

3
La "compatibilità con più lingue" non è stata un problema. C e UNIX sono stati scritti in tandem. La ragione per cui molte altre lingue restituiscono ints è perché sono state progettate per funzionare in ambienti tipo UNIX o UNIX.

Risposte:


88

Il valore di ritorno di maindeve essere passato al sistema operativo ( qualsiasi sistema operativo) in un unico modo coerente. Le informazioni che il sistema operativo deve sapere sono "il programma è stato chiuso correttamente o si è verificato un errore?"

Se questa è una stringa, la risposta diventa difficile in diverse lingue. Gli interni di una stringa Pascal (il primo byte è lunghezza) e una stringa FORTRAN (fissa, riempita con un certo valore) e una stringa C (terminata con null) sono tutte diverse. Ciò renderebbe difficile restituire un valore coerente al sistema operativo. Supponendo che ciò sia stato risolto, cosa faresti per rispondere alla domanda che il sistema operativo aveva del programma? I confronti tra stringhe sono pieni di errori ("successo" vs "Successo") e, sebbene l'errore possa essere più utile per un essere umano, è più difficile che il sistema operativo o un altro programma (shell) si occupino. Ci sono state anche differenze significative anche nelle stringhe stesse - EBCDIC (con tutte le sue pagine di codice) rispetto a ASCII.

I float e i doppi non forniscono alcun valore aggiuntivo rispetto all'intero per la comunicazione dei dati di ritorno al sistema operativo (e alla shell). Per la maggior parte, nessuna di queste parti del computer ha a che fare con numeri in virgola mobile. Anche i doppi non sono enumerabili, rendendo difficili i confronti. Non essendo enumerabili, fanno la segnalazione dell'errore (supponendo che tu abbia scelto un valore particolare per il successo). Ancora una volta, i punti mobili non sono coerenti - un float su una macchina a 8 bit era diverso dal float su una macchina a 16 bit e 32 bit (e quelli erano solo quelli "normali" - anche all'interno di IBM, il virgola mobile non era standardizzato tra macchine dello stesso produttore fino agli anni '80). E poi hai i computer decimali vs binari. I valori in virgola mobile non sono coerenti e non forniscono dati significativi.

Questo ci lascia davvero con il byte e il numero intero come opzioni. La convenzione stabilita era "0" fu un successo e qualsiasi altra cosa fu un errore. Un numero intero dà più spazio di un byte per la segnalazione dell'errore. Può essere elencato (ritorno di 1 significa XYZ, ritorno di 2 significa ABC, ritorno di 3, DEF, ecc.) O usato come flag ( 0x0001significa che questo ha fallito, 0x0002significa che ha fallito, 0x0003significa sia questo che fallito). Limitare questo a un solo byte potrebbe facilmente esaurire i flag (solo 8), quindi probabilmente si è deciso di utilizzare un numero intero.


2
Penso che main sia chiamato dalla libreria di runtime c / c ++ prima che l'OS lo chiami, che è anche un pezzo di codice caricato insieme al nostro codice e chiamato dall'os @ MichaelT
JAVA il

5
main()viene invocato in modi diversi su diversi sistemi operativi. In C, come viene inizialmente chiamato il metodo main ()? entra in questo.

25
Penso che il punto chiave da capire sia che main- diversamente da altre funzioni di qualsiasi programma - non fa parte di un protocollo definito dal programmatore, ma il protocollo utilizzato per interfacciarsi con l'host (SO). Non puoi sceglierlo perché non è mai stato tuo. A un livello più pragmatico, UNIX si aspetta che un int venga restituito da un processo, quindi il protocollo da C a UNIX fa esattamente questo. È possibile formulare un argomento analogo per il passaggio degli argomenti: se C fosse stato inventato per un sistema operativo / host che passava solo numeri come argomenti (ad es. Nessuna riga di comando), gli argomenti sarebbero ints anziché in stringhe.
Euro Micelli,

2
IBM ha portato il concetto di codepage da EBCDIC ai propri PC. Ci perseguitano ancora oggi, proseguendo 35 anni dopo l'introduzione dell'IBM 5150. ASCII a 7 bit è senza codice, ma i codici di caratteri a 8 bit possono essere interpretati in molti modi diversi anche su un singolo computer, a seconda delle impostazioni - - per non parlare delle codepage che codificano per le codifiche multi-byte. Quindi in realtà è anche peggio di ciò a cui alludi nell'ultima frase del secondo paragrafo.
un CVn

@EuroMicelli è davvero una bella notizia grazie per quello :)
JAVA

29

Beh, potrebbe .

Ad esempio, nel dialetto di C utilizzato nel sistema operativo Plan 9main viene normalmente dichiarato una voidfunzione, ma lo stato di uscita viene restituito all'ambiente chiamante passando un puntatore di stringa alla exits()funzione. La stringa vuota indica il successo e qualsiasi stringa non vuota indica un tipo di errore. Questo avrebbe potuto essere implementato avendo mainrestituito achar* risultato.

E sarebbe certamente possibile implementare un sistema con un floatodouble uscita.

Allora perchè int? È solo una questione di convenzioni - e c'è una cosa tremenda valore nel fatto che i sistemi operativi e i programmi eseguiti sotto di loro obbediscano a una convenzione comune.

La convenzione Unix prevede l'uso di un codice di stato intero, con 0 che indica il successo e diverso da zero che indica il fallimento (perché in genere esiste un solo modo per avere successo, ma più modi per fallire). Non so se quella convenzione sia nata con Unix; Sospetto che provenisse da precedenti sistemi operativi.

Il virgola mobile sarebbe una convenzione più difficile, perché (a) il supporto in virgola mobile non è universale, (b) è più difficile definire una mappatura tra valori in virgola mobile e condizioni di errore, (c) sistemi diversi usano differenti virgola mobile- rappresentazioni punto e (d) immagina solo il divertimento di rintracciare un errore di arrotondamento nello stato di uscita del tuo programma. I numeri interi, d'altra parte, si prestano molto bene all'enumerazione dei codici di errore.

Plan 9, come ho già detto, usa stringhe, ma ciò impone una certa complessità per la gestione della memoria, la codifica dei caratteri, ecc. Fu, per quanto ne so, una nuova idea quando Plan 9 lo implementò e non sostituì quello esistente convenzione diffusa.

(Per inciso, in C ++ mainpuò solo tornare int, e in C void mainè consentito solo se il compilatore lo supporta specificamente. Molti compilatori non si lamentano molto ad alta voce se scrivi void main, ma è solo una leggera esagerazione dire che è sbagliato .)


9

Il valore restituito dal metodo principale è un "codice di uscita". Viene utilizzato dall'applicazione chiamante (normalmente bash) per verificare se il programma è terminato come previsto. Restituire un numero intero è il modo più semplice per farlo a livello di sistema operativo. Double non ha senso per il codice di errore e una stringa è difficile da mantenere a livello di sistema operativo (non esiste un GC).


3
Perché una stringa deve essere garbage collection mentre un intero no?
Brad,

4
@Brad, le stringhe hanno una lunghezza variabile e sarebbero essenzialmente le stesse del passaggio di un array che potrebbe essere un carattere o potrebbe essere migliaia. La memoria dinamica sarebbe un dolore mentre un int ha una dimensione piuttosto fissa che non è così difficile da gestire.
JB King,

-4

main dovrebbe restituire lo stato del programma che viene eseguito, sia che venga eseguito correttamente (return 0 che sia EXIT_SUCCESS) oppure no (return 1 significa EXIT_FAILURE) qualsiasi numero diverso da zero trasmette lo stesso significato ma zero indica nessun errore o esecuzione riuscita.


1
questo non sembra offrire nulla di sostanziale rispetto ai punti espressi (e molto meglio spiegati) nelle risposte precedenti che erano state pubblicate diversi anni fa
moscerino del
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.