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

38

In molti linguaggi come C, C ++ e Java, il metodo / funzione main ha un tipo di ritorno di void o int , ma non double o String . Quali potrebbero essere le ragioni dietro a questo?

So un po 'che non possiamo farlo perché main è chiamato dalla libreria di runtime e si aspetta una certa sintassi come int main() o int main(int,char**) , quindi dobbiamo attenerci a quello.

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

    
posta JAVA 28.06.2013 - 22:37
fonte

3 risposte

83

Il valore di ritorno di main deve 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 terminato correttamente o c'era un errore?"

Se si tratta di una stringa, la risposta diventa difficile in diverse lingue. Gli interni di una stringa Pascal (il primo byte è la lunghezza) e una stringa FORTRAN (fissa, riempita con un certo valore) e una stringa C (terminata con null) sono tutti diversi. Ciò renderebbe difficile restituire un valore coerente al sistema operativo. Supponendo che questo è 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 mentre l'errore può essere più utile per un essere umano, è più difficile per il sistema operativo o un altro programma (shell) da gestire. C'erano anche differenze significative anche nelle stringhe stesse - EBCDIC (con tutte le sue code page) vs. ASCII.

Le virgolette e le doppie non forniscono alcun valore addizionale 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, rendono conto dell'errore (presumendo che tu abbia scelto un valore particolare per il successo). Anche in questo caso, 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 a 32 bit (e quelli sono solo quelli "normali" - anche all'interno di IBM, il punto mobile non era standardizzato tra macchine dello stesso produttore fino agli anni '80). E poi hai computer decimali vs binari. I valori in virgola mobile non sono coerenti e non restituiscono dati significativi.

Questo ci lascia davvero con il byte e il numero intero come opzioni. La convenzione stabilita era "0" era successo, e qualsiasi altra cosa era un errore. Un numero intero offre più spazio di un byte per la segnalazione dell'errore. Può essere enumerato (return of 1 significa XYZ, return of 2 significa ABC, return of 3, significa DEF, ecc.) O usato come flags ( 0x0001 significa che non è riuscito, 0x0002 significa che non è riuscito, 0x0003 significa sia questo sia quello fallito). Limitare questo a un solo byte potrebbe facilmente esaurire i flag (solo 8), quindi la decisione era probabilmente quella di usare un intero.

    
risposta data 28.06.2013 - 23:00
fonte
27

Bene, potrebbe .

Ad esempio, nel dialetto di C usato nel Piano 9 il sistema operativo main è normalmente dichiarato come una funzione void , ma lo stato di uscita viene restituito all'ambiente chiamante passando un puntatore a stringa alla funzione exits() . La stringa vuota denota il successo, e qualsiasi stringa non vuota denota qualche tipo di errore. Questo potrebbe essere stato implementato avendo main restituito un risultato char* .

E sarebbe certamente possibile implementare un sistema con uno stato di uscita float o double .

Quindi perché int ? È solo una questione di convenzioni - e c'è un tremendo valore nell'avere sistemi operativi e programmi che funzionano sotto di loro obbediscono a una convenzione comune.

La convenzione Unix consiste nell'utilizzare un codice di stato intero, con 0 che denota il successo e il non-zero che denota il fallimento (perché in genere c'è solo un modo per avere successo, ma più modi per fallire). Non so se quella convenzione sia nata con Unix; Sospetto che provenga da precedenti sistemi operativi.

Il virgola mobile sarebbe una convenzione più difficile, perché (a) il supporto a virgola mobile non è universale, (b) è più difficile definire una mappatura tra valori a virgola mobile e condizioni di errore, (c) utilizzo di sistemi diversi diverse rappresentazioni a virgola mobile e (d) immagina solo il divertimento di rintracciare un errore di arrotondamento nello stato di uscita del tuo programma. Gli interi, d'altra parte, si prestano molto bene a enumerare i codici di errore.

Il piano 9, come ho detto, usa le stringhe, ma questo impone una certa complessità per la gestione della memoria, la codifica dei caratteri, ecc. Era, per quanto ne so, una nuova idea quando Plan 9 lo implementava, e non sostituire la convenzione diffusa esistente.

(Incidentalmente, in C ++ main può solo restituire int , e in C void main è permesso solo se il compilatore lo supporta in modo specifico.Molti compilatori non si lamentano molto strong se scrivi void main , ma è solo una leggera esagerazione affermare che è sbagliato .)

    
risposta data 29.06.2013 - 03:23
fonte
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. Il ritorno di un 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 c'è GC).

    
risposta data 28.06.2013 - 23:02
fonte

Leggi altre domande sui tag