Standard C - Ambiente ospitato
Per un ambiente ospitato (quello normale), lo standard C11 (ISO / IEC 9899: 2011) dice:
5.1.2.2.1 Avvio del programma
La funzione chiamata all'avvio del programma è denominata main
. L'implementazione non dichiara alcun prototipo per questa funzione. Deve essere definito con un tipo di ritorno int
e senza parametri:
int main(void) { /* ... */ }
o con due parametri (indicati qui come argc
e argv
, sebbene sia possibile utilizzare qualsiasi nome, poiché sono locali alla funzione in cui sono dichiarati):
int main(int argc, char *argv[]) { /* ... */ }
o equivalente; 10) o in qualche altro modo definito dall'implementazione.
Se sono dichiarati, i parametri della funzione principale devono rispettare i seguenti vincoli:
- Il valore di
argc
non è negativo.
argv[argc]
deve essere un puntatore nullo.
- Se il valore di
argc
è maggiore di zero, i membri dell'array argv[0]
tramite
argv[argc-1]
inclusivo devono contenere puntatori alle stringhe, che ricevono valori definiti dall'implementazione dall'ambiente host prima dell'avvio del programma. L'intento è fornire al programma le informazioni determinate prima dell'avvio del programma altrove nell'ambiente ospitato. Se l'ambiente host non è in grado di fornire stringhe con lettere sia maiuscole che minuscole, l'implementazione deve garantire che le stringhe siano ricevute in minuscolo.
- Se il valore di
argc
è maggiore di zero, la stringa indicata da argv[0]
rappresenta il nome del programma; argv[0][0]
deve essere il carattere null se il nome del programma non è disponibile dall'ambiente host. Se il valore di argc
è maggiore di uno, le stringhe indicate da argv[1]
attraverso argv[argc-1]
rappresentano i parametri del programma.
- I parametri
argc
e argv
le stringhe a cui punta l' argv
array devono essere modificabili dal programma e conservare i loro ultimi valori memorizzati tra l'avvio e la fine del programma.
10) Pertanto, int
può essere sostituito da un nome typedef definito come int
, oppure il tipo di argv
può essere scritto come
char **argv
e così via.
Terminazione del programma in C99 o C11
Il valore restituito da main()
viene trasmesso all '"ambiente" in modo definito dall'implementazione.
5.1.2.2.3 Terminazione del programma
1 Se il tipo restituito della main
funzione è compatibile con un tipo int
, un ritorno dalla chiamata iniziale alla main
funzione equivale a chiamare la exit
funzione con il valore restituito dalla main
funzione come argomento; 11) il raggiungimento di quello }
che termina la
main
funzione restituisce un valore di 0. Se il tipo restituito non è compatibile int
, lo stato di terminazione restituito all'ambiente host non è specificato.
11) In conformità al punto 6.2.4, la durata di vita degli oggetti con durata di conservazione automatica dichiarata main
sarà terminata nel primo caso, anche se non nel secondo.
Si noti che 0
è obbligatorio come "successo". Puoi usare EXIT_FAILURE
e EXIT_SUCCESS
da <stdlib.h>
se preferisci, ma 0 è ben definito, e lo è anche 1. Vedi anche Codici di uscita superiori a 255 - possibili? .
In C89 (e quindi in Microsoft C), non ci sono istruzioni su cosa succede se la main()
funzione ritorna ma non specifica un valore di ritorno; porta quindi a comportamenti indefiniti.
7.22.4.4 La exit
funzione
¶5 Infine, il controllo viene restituito all'ambiente host. Se il valore di status
è zero o EXIT_SUCCESS
, viene restituita una forma definita dall'implementazione della terminazione riuscita dello stato . Se il valore di status
è EXIT_FAILURE
, viene restituita una forma definita dall'implementazione della terminazione non riuscita dello stato . Altrimenti lo stato restituito è definito dall'implementazione.
Standard C ++ - Ambiente ospitato
Lo standard C ++ 11 (ISO / IEC 14882: 2011) afferma:
3.6.1 Funzione principale [basic.start.main]
¶1 Un programma deve contenere una funzione globale chiamata main, che è l'inizio designato del programma. [...]
¶2 Un'attuazione non deve predefinire la funzione principale. Questa funzione non deve essere sovraccaricata. Deve avere un tipo restituito di tipo int, ma per il resto il suo tipo è definito dall'implementazione. Tutte le implementazioni devono consentire entrambe le seguenti definizioni di main:
int main() { /* ... */ }
e
int main(int argc, char* argv[]) { /* ... */ }
In quest'ultima forma argc
deve essere indicato il numero di argomenti passati al programma dall'ambiente in cui viene eseguito il programma. Se argc
è diverso da zero questi argomenti vengono forniti in argv[0]
attraverso argv[argc-1]
come puntatori ai caratteri iniziali di stringhe multibyte null-terminate (NTMBSs) (17.5.2.1.4.2) e argv[0]
sono il puntatore al carattere iniziale di un NTMBS che rappresenta il nome utilizzato per invocare il programma o ""
. Il valore di argc
deve essere non negativo. Il valore di argv[argc]
deve essere 0. [Nota: si consiglia di aggiungere ulteriori parametri (facoltativi) dopo argv
. —Endola nota]
¶3 La funzione main
non deve essere utilizzata all'interno di un programma. Il collegamento (3.5) di main
è definito dall'implementazione. [...]
¶5 Un'istruzione return in main ha l'effetto di lasciare la funzione principale (distruggere qualsiasi oggetto con durata di memorizzazione automatica) e chiamare std::exit
con l'argomento il valore restituito. Se il controllo raggiunge la fine di main senza incontrare un'istruzione return, l'effetto è quello dell'esecuzione
return 0;
Lo standard C ++ dice esplicitamente "Essa [la funzione principale] deve avere un tipo restituito di tipo int
, ma altrimenti il suo tipo è definito dall'implementazione" e richiede che le stesse due firme dello standard C siano supportate come opzioni. Quindi un 'void main ()' non è direttamente consentito dallo standard C ++, anche se non c'è nulla che possa fare per fermare un'implementazione non standard che consente alternative. Si noti che C ++ proibisce all'utente di chiamare main
(ma lo standard C no).
C'è un paragrafo di §18.5 Inizio e fine nello standard C ++ 11 che è identico al paragrafo di §7.22.4.4 La exit
funzione nello standard C11 (citato sopra), a parte una nota a piè di pagina (che documenta semplicemente EXIT_SUCCESS
e che EXIT_FAILURE
sono definiti in <cstdlib>
).
Standard C - Estensione comune
Classicamente, i sistemi Unix supportano una terza variante:
int main(int argc, char **argv, char **envp) { ... }
Il terzo argomento è un elenco di puntatori alle stringhe con terminazione null, ognuno dei quali è una variabile di ambiente che ha un nome, un segno di uguale e un valore (possibilmente vuoto). Se non lo usi, puoi comunque accedere all'ambiente tramite ' extern char **environ;
'. Questa variabile globale è unica tra quelle in POSIX in quanto non ha un'intestazione che la dichiara.
Ciò è riconosciuto dalla norma C come estensione comune, documentata nell'allegato J:
J.5.1 Argomenti ambientali
¶1 In un ambiente ospitato, la funzione principale riceve un terzo argomento, char *envp[]
che punta a una matrice di puntatori con terminazione nulla char
, ciascuno dei quali punta a una stringa che fornisce informazioni sull'ambiente per questa esecuzione del programma (5.1. 2.2.1).
Microsoft C
Il compilatore Microsoft VS 2010 è interessante. Il sito web dice:
La sintassi della dichiarazione per main è
int main();
o, facoltativamente,
int main(int argc, char *argv[], char *envp[]);
In alternativa, le funzioni main
e wmain
possono essere dichiarate come void
return (nessun valore di ritorno). Se si dichiara main
o si wmain
annulla la restituzione, non è possibile restituire un codice di uscita al processo padre o al sistema operativo utilizzando un'istruzione return. Per restituire un codice di uscita quando main
o wmain
viene dichiarato come void
, è necessario utilizzare la exit
funzione.
Non mi è chiaro cosa succede (quale codice di uscita viene restituito al genitore o al sistema operativo) quando un programma con void main()
esce, e anche il sito Web MS è silenzioso.
È interessante notare che MS non prescrive la versione a due argomenti main()
richiesta dagli standard C e C ++. Prescrive solo una forma a tre argomenti in cui si trova il terzo argomento char **envp
, un puntatore a un elenco di variabili di ambiente.
La pagina Microsoft elenca anche alcune altre alternative, wmain()
che richiedono ampie stringhe di caratteri e altre ancora.
La versione di Microsoft Visual Studio 2005 di questa pagina non è elencata void main()
come alternativa. Le versioni da Microsoft Visual Studio 2008 in poi lo fanno.
Standard C - Ambiente indipendente
Come notato in precedenza, i requisiti di cui sopra si applicano agli ambienti ospitati. Se lavori con un ambiente indipendente (che è l'alternativa a un ambiente ospitato), lo standard ha molto meno da dire. Per un ambiente indipendente, non è necessario chiamare la funzione chiamata all'avvio del programma main
e non vi sono vincoli sul tipo di ritorno. Lo standard dice:
5.1.2 Ambienti di esecuzione
Sono definiti due ambienti di esecuzione: indipendenti e ospitati. In entrambi i casi, l'avvio del programma si verifica quando una funzione C designata viene chiamata dall'ambiente di esecuzione. Tutti gli oggetti con durata di memorizzazione statica devono essere inizializzati (impostati sui valori iniziali) prima dell'avvio del programma. Le modalità e i tempi di tale inizializzazione sono altrimenti non specificati. La terminazione del programma restituisce il controllo all'ambiente di esecuzione.
5.1.2.1 Ambiente indipendente
In un ambiente indipendente (in cui l'esecuzione del programma C può avvenire senza alcun vantaggio di un sistema operativo), il nome e il tipo della funzione chiamata all'avvio del programma sono definiti dall'implementazione. Qualsiasi struttura di libreria disponibile per un programma indipendente, ad eccezione dell'insieme minimo richiesto dalla clausola 4, è definita dall'implementazione.
L'effetto della conclusione del programma in un ambiente indipendente è definito dall'implementazione.
Il riferimento incrociato alla clausola 4 Conformità si riferisce a questo:
¶5 Un programma strettamente conforme deve utilizzare solo le caratteristiche della lingua e della biblioteca specificate nella presente norma internazionale. 3) Non deve produrre output dipendenti da comportamenti non specificati, non definiti o definiti dall'implementazione e non deve superare alcun limite minimo di implementazione.
¶6 Le due forme di implementazione conforme sono ospitate e indipendenti . Un conforme implementazione ospitata accetta qualsiasi programma rigorosamente conforme. Un conforme implementazione indipendente accetta qualsiasi programma rigorosamente conforme in cui l'uso delle caratteristiche specificate nella clausola libreria (clausola 7) si limita al contenuto delle intestazioni standard <float.h>
, <iso646.h>
, <limits.h>
, <stdalign.h>
,
<stdarg.h>
, <stdbool.h>
, <stddef.h>
, <stdint.h>
, e
<stdnoreturn.h>
. Un'implementazione conforme può avere estensioni (incluse funzioni di libreria aggiuntive), a condizione che non alterino il comportamento di alcun programma strettamente conforme. 4)
¶7 Un programma conforme è accettabile per un'implementazione conforme. 5)
3) Un programma rigorosamente conforme può utilizzare le funzioni condizionali (vedere 6.10.8.3) a condizione che l'uso sia tutelato da un'adeguata direttiva di preelaborazione dell'inclusione condizionale utilizzando la relativa macro. Per esempio:
#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */
/* ... */
fesetround(FE_UPWARD);
/* ... */
#endif
4) Ciò implica che un'implementazione conforme non riserva identificatori diversi da quelli esplicitamente riservati nella presente norma internazionale.
5) I programmi rigorosamente conformi devono essere massimamente trasportabili tra le implementazioni conformi. I programmi conformi possono dipendere da funzionalità non portatili di un'implementazione conforme.
È evidente che l'unica intestazione richiesta per un ambiente indipendente che definisce effettivamente qualsiasi funzione è <stdarg.h>
(e anche quelle possono essere - e spesso lo sono - solo macro).
Standard C ++ - Ambiente indipendente
Proprio come lo standard C riconosce sia l'ambiente ospitato che quello indipendente, così anche lo standard C ++. (Citazioni da ISO / IEC 14882: 2011.)
1.4 Conformità all'implementazione [intro.compliance]
¶7 Sono definiti due tipi di implementazioni: un'implementazione ospitata e un'implementazione indipendente . Per un'implementazione ospitata, questo standard internazionale definisce l'insieme delle librerie disponibili. Un'implementazione indipendente è quella in cui l'esecuzione può avvenire senza il beneficio di un sistema operativo e ha un set di librerie definito dall'implementazione che include determinate librerie di supporto linguistico (17.6.1.3).
¶8 Un'implementazione conforme può avere estensioni (incluse funzioni di libreria aggiuntive), a condizione che non alterino il comportamento di alcun programma ben formato. Le implementazioni sono necessarie per diagnosticare i programmi che utilizzano tali estensioni mal formate secondo questo standard internazionale. Fatto ciò, tuttavia, possono compilare ed eseguire tali programmi.
¶9 Ciascuna implementazione deve includere la documentazione che identifica tutti i costrutti supportati condizionalmente che non supporta e definisce tutte le caratteristiche specifiche della locale. 3
3) Questa documentazione definisce anche il comportamento definito dall'implementazione; vedi 1.9.
17.6.1.3 Implementazioni indipendenti [conformità]
Sono definiti due tipi di implementazioni: ospitato e indipendente (1.4). Per un'implementazione ospitata, questo standard internazionale descrive l'insieme di intestazioni disponibili.
Un'implementazione indipendente ha un set di intestazioni definito dall'implementazione. Questo set comprende almeno le intestazioni indicate nella tabella 16.
La versione fornita dell'intestazione <cstdlib>
dichiara almeno le funzioni abort
, atexit
, at_quick_exit
, exit
, e quick_exit
(18.5). Le altre intestazioni elencate in questa tabella devono soddisfare gli stessi requisiti previsti per un'implementazione ospitata.
Tabella 16 - Intestazioni C ++ per implementazioni indipendenti
Subclause Header(s)
<ciso646>
18.2 Types <cstddef>
18.3 Implementation properties <cfloat> <limits> <climits>
18.4 Integer types <cstdint>
18.5 Start and termination <cstdlib>
18.6 Dynamic memory management <new>
18.7 Type identification <typeinfo>
18.8 Exception handling <exception>
18.9 Initializer lists <initializer_list>
18.10 Other runtime support <cstdalign> <cstdarg> <cstdbool>
20.9 Type traits <type_traits>
29 Atomics <atomic>
Che ne dici di usare int main()
in C?
Lo standard §5.1.2.2.1 dello standard C11 mostra la notazione preferita - int main(void)
- ma ci sono anche due esempi nello standard che mostrano int main()
: §6.5.3.4 ¶8 e §6.7.6.3 ¶20 . Ora, è importante notare che gli esempi non sono "normativi"; sono solo illustrativi. Se negli esempi ci sono dei bug, questi non influenzano direttamente il testo principale dello standard. Detto questo, sono fortemente indicativi del comportamento previsto, quindi se la norma include int main()
in un esempio, suggerisce che int main()
non è vietato, anche se non è la notazione preferita.
6.5.3.4 Operatori sizeof
e_Alignof
...
¶8 ESEMPIO 3 In questo esempio, la dimensione di un array di lunghezza variabile viene calcolata e restituita da una funzione:
#include <stddef.h>
size_t fsize3(int n)
{
char b[n+3]; // variable length array
return sizeof b; // execution time sizeof
}
int main()
{
size_t size;
size = fsize3(10); // fsize3 returns 13
return 0;
}