2009-10-25 5 views
24

Lo standard afferma esplicitamente che main ha due firme valide (vale a dire garantite per funzionare); vale a dire:Gli argomenti della firma di main in C++ hanno i qualificatori unsiged e const?

int main(); 
int main(int, char*[]); 

La mia domanda è semplice, sarebbe qualcosa di simile al seguente essere legale?

int main(const unsigned int, const char* const* argv); 

miei test dicono 'sì', ma io sono sicuro della risposta, perché sono io che non sovraccaricare main cambiando int a unsigned int così come il non alto livello const -ness di argv? Se lo sono, allora è chiaramente proibito.

Quindi, queste modifiche sono garantite per funzionare su un compilatore conforme agli standard?

+7

perché vorresti fare qualcosa del genere? Basta scrivere il codice conforme allo standard – Glen

+10

Glen, io _want_ per scrivere un codice conforme. Ecco perché ho fatto questa domanda in primo luogo. – bh9042

+9

Quindi dichiara 'int main (int, char **)' e sii sulla buona strada. –

risposta

33

Lo standard C++ 98 dice nel paragrafo 3.6.1 comma 2

Un'implementazione non deve predefinire la funzione principale. Questa funzione non deve essere sovraccaricata. Deve avere un tipo di ritorno di tipo int, ma in caso contrario 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[])

Quindi non è obbligatorio per lo standard che l'ENV accettare main è accettabile, ma è lecito.


Perché questo è indicato spesso, qui è il paragrafo precedente che esenta gli ambienti freestanding dal nulla, ma documentare il loro comportamento:

Un programma deve contenere una funzione globale chiamato principale, che è l'inizio designato del programma. È l'implementazione definita se è necessario un programma in un ambiente indipendente per definire una funzione principale .[Nota: in un ambiente indipendente, l'avvio e la terminazione sono definiti dall'implementazione; startup contiene l'esecuzione di costruttori per oggetti di ambito namespace con durata di memorizzazione statica; terminazione contiene l'esecuzione di distruttori per oggetti con durata di memorizzazione statica. ]

+0

Ah, ho perso la parte "tipo" quando l'ho letto. – bh9042

1

Per quanto mi risulta dalla lettura dello standard, si sta rispettando gli standard. Ma non riesco a immaginare un compilatore che non ti permetta di farlo. Come in questo, ci vorrebbe più lavoro dal compilatore per vietare specificamente un caso limite che è per lo più innocuo e molto oscuro.

+0

Amen. il tuo codice potrebbe avere problemi di compilazione su un ipotetico compilatore che 100% segue lo standard. Ma la maggior parte dei compilatori no, e questo caso limite è probabilmente uno di quelli in cui consentono ciò che è tecnicamente un comportamento illegale. – DVK

2

I puntatori argv non devono essere const char* const perché al programma è consentito modificare i buffer.

+0

** Solo ** le stringhe, non i puntatori alle stringhe. –

+3

Questo è il punto. Non voglio cambiare nulla! – bh9042

+2

Quindi non modificare nulla. –

0

Potrebbe essere illegale secondo lo standard, ma la maggior parte dei runtime non interessa davvero. Inseriranno semplicemente un numero intero per argc e un puntatore per argv, chiameranno il numero main e spero che li analizzi correttamente. Quindi, a vostro parere, "garantito di funzionare" è discutibile in quanto il caricatore non si preoccupa davvero di ciò che avete dichiarato come argomenti.

Se viene generato, verrà chiamato il numero main. Come si analizzano gli argomenti dipende da voi. Dovrei chiarire che questo è altamente specifico per la piattaforma, così come quasi l'intera domanda.

Detto questo, perché?

+1

1. argc è garantito non negativo, voglio vedere un unsigned da qualche parte in là ...;) 2. Voglio la rete di sicurezza extra che const fornisce contro gli errori stupidi. Come ho risposto a jeffamaphone, anche se ho il permesso di cambiare argv, non voglio o non ne ho bisogno. – bh9042

+1

'main' precede C++ e anche il tempo di' unsigned'. Indipendentemente da ciò che desideri, 'main' è stato dichiarato in questo modo per molto, molto tempo. Hai davvero bisogno del compilatore per proteggerti dalla modifica di 'argv'? Se non hai quel 'const', dovrai sostituire per errore tutti i '-' con '/' nelle tue stringhe' argv'? Non mi stai vendendo perché è necessario. –

+1

Penso che sia un punto valido che permette ai programmatori di specificare assunzioni e vincoli attraverso modificatori come 'unsigned' e' const' dovrebbero essere permessi ovunque. Se è buono per le funzioni definite dall'utente, non vedo perché non andrebbe bene anche per 'main(). –

19

È necessario utilizzare una delle firme conformi allo standard per essere conformi allo standard.

Capisco perfettamente perché vuoi farlo a modo tuo. Il modo migliore è scrivere la propria funzione myMain() o qualsiasi altra cosa con la firma desiderata e chiamarla da main(), inclusi i cast richiesti.

+5

+1 per fornire una risposta utile invece di quella di tutti gli altri "Non vedo perché lo faresti". –

1

Questo potrebbe non funzionare se il compilatore utilizza il nome mangling per main. È una funzione C++ dopo tutto. Quindi, il linker cercherà due "manglings" particolari. La tua definizione avrebbe un altro nome mutilato.

Si noti che main è speciale (non sovraccarico, non chiamabile) e potrebbe non richiedere affatto il nome di manomissione.

0

ISO/IEC 9899: TC3

Sezione 5.1.2.2.1 all'avvio del programma

La funzione chiamata all'avvio del programma prende il nome principale. L'implementazione non dichiara il prototipo per questa funzione. Essa è definita con un tipo di ritorno di int e senza parametri:

int main(void) { /* ... */ } 

o con due parametri (qui indicati come argc e argv, se eventuali nomi possono essere utilizzati, in quanto sono locale alla funzione in cui sono dichiarati):

int main(int argc, char *argv[]) { /* ... */ } 

o equivalente; 9) o in qualche altro modo definito dall'implementazione.