2012-09-01 21 views
50

Cosa fa la seguente media:Differenza tra int main() e int main (void)?

int main(void) {...} 

VS

int main() {...} 

?

ritengo che int main() {...} significa che principale non riceve alcun parametro (da linea di comando), tuttavia:

int main(int argc, char *argv[]) 

fa.

Ma cosa significa int main(void) {...}? cosa significa il vuoto?

Ho cercato here ma è in qualche modo una domanda diversa.

+0

C99 e C11 non menzionano più 'int main()'. Basta usare 'int main (void)'. Vedere 5.1.2.2.1 "Avvio del programma" dello standard: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf – superlukas

risposta

47

In C++, non c'è differenza.


In C, la differenza è discutibile. Alcuni amano sostenere che quest'ultima versione (quella senza void) è tecnicamente solo un'estensione di implementazione comune e non è garantita per funzionare dallo standard a causa della dicitura nello standard. Tuttavia, lo standard afferma chiaramente che in una definizione di funzione un insieme vuoto di parametri ha un comportamento ben definito: che la funzione non prende alcun parametro. Quindi una definizione di questo tipo corrisponde alla seguente descrizione nello standard:

La [principale] deve essere definita con un tipo di ritorno di int e senza parametri.

V'è, tuttavia, una notevole differenza tra i due: vale a dire, la versione senza void non riesce a fornire una corretta prototipo per la funzione:

// this is OK. 
int main() 
{ 
    if (0) main(42); 
} 

// this requires a diagnostic to be shown during compiling 
int main(void) 
{ 
    if (0) main(42); 
} 

Oh, e solo per essere completo: la void ha il seguente significato in tutti dichiaratori funzione:

(6.7.6.3p10) il caso particolare di un parametro senza nome di tipo void come unico elemento nell'elenco specifica che la funzione ha para metri.

+2

Nel tuo primo esempio, cosa significa 'main (42); 'mean (dove hai scritto' // questo è okay')? – ron

+1

È una chiamata di funzione (di 'main' con un singolo argomento int di' 42'). –

+7

Sì, ma cosa fa? questa è la prima volta che vedo un invoke di main() da main(). – ron

1

In C++, non vi è alcuna differenza tra i due e int main() è una firma legale e un tipo di reso per main.

0

Il prototipo di funzione con Type foo(void) è assolutamente uguale a Type foo(), non vi è alcuna differenza tra i due. L'ex può essere utilizzato per la leggibilità.

Come con main - prendendo argomenti o no, il programma può ancora accedere alle informazioni della riga di comando attraverso altri mezzi come __argv, __argc, GetCommandLine, o altri simboli specifici della piattaforma/compilatore.

+4

Corretto per C++, errato per C. In C , data una definizione 'void foo() {}', la chiamata 'foo (42)' ha un comportamento indefinito; data una definizione 'void foo (void) {}', la chiamata 'foo (42)' è una violazione del vincolo. –

+0

Non ho detto nulla contro questo! – Ajay

+3

Sì, l'hai fatto. Hai detto che sono assolutamente uguali. Loro non sono. –

6

In C, in un prototipo (non in C++ però) una lista di argomenti vuoto indica che la funzione potrebbe assumere qualsiasi argomenti (nella definizione di una funzione, significa argomenti). In C++, una lista di parametri vuota significa nessun argomento. In C, per non avere argomenti, devi usare void. Vedi la domanda this per una spiegazione migliore.

+0

Questo si applica solo quando il dichiaratore non fa parte della definizione della funzione. –

+0

@ eq-: Scusa, ma ciò significa che si applica solo quando è separato dall'implementazione? Quindi si applica a 'int foo (void); int foo (void) {} ​​'ma non per' int foo (void) {} ​​'? – Linuxios

+1

In C, 'int foo();' non specifica nulla sui parametri della funzione, mentre 'int foo() {}' specifica che 'foo' non accetta alcun parametro. –

4

In C++ con una funzione e foo() è la stessa cosa. Tuttavia, in C è diverso: foo(void) è una funzione che non ha argomenti, mentre foo() è una funzione con argomenti non specificati.

+1

Hai perso il punto (per C). In una definizione 'int foo() {}' dichiara una funzione senza argomenti. –

+1

@JensGustedt in C, in una definizione, 'int foo() {}' in realtà * definisce * una funzione senza argomenti, tuttavia * dichiara * una funzione che accetta un numero non specificato di argomenti. – RastaJedi

3

In C++, non esistono differenze, entrambi sono uguali.

Entrambe le definizioni lavorano in C anche, ma la seconda definizione con vuoto è considerato tecnicamente meglio come specifica chiaramente che principale può essere chiamato solo senza alcun parametro. In C, se la firma di funzione non specifica alcun argomento, significa che la funzione può essere chiamata con qualsiasi numero di parametri o senza parametri. Ad esempio, prova a compilare ed eseguire i seguenti due programmi C (ricorda di salvare i tuoi file come .c).

2

Prima di tutto, c'è una differenza tra ciò che è consentito per i sistemi hosted e i sistemi indipendenti, come shown here.

Per i sistemi ospitati, 5.1.2.2.1 all'avvio del programma si applica:

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) 

... (segue altro testo per quanto riguarda argv/argc ecc stili).

La parte interessante è "senza parametri". int main() e int main (void) sono attualmente equivalenti, poiché sono entrambi dichiaratori di funzioni e non hanno parametri. Si applica quanto segue (6.7.6.3):

10 Il caso speciale di un parametro senza nome di tipo void come unica voce nell'elenco specifica che la funzione non ha parametri.

/-/

14 Un elenco identificativo dichiara solo gli identificatori dei parametri della funzione. Un elenco vuoto in un dichiaratore di funzione che fa parte di una definizione di tale funzione specifica che la funzione non ha parametri. L'elenco vuoto in un dichiaratore di funzione che non fa parte di una definizione di di quella funzione specifica che non sono fornite informazioni sul numero o sui tipi dei parametri .145)

Enfasi minime, il testo in grassetto è quello che si applica a int main(). V'è anche nota 145) alla fine del testo, che dice "Ci vediamo '' direzioni future lingua '' (6.11.6)":

6.11.6 Funzione Dichiaratori

L'uso della funzione i dichiaratori con parentesi vuote (non dichiaratori del tipo di parametro in formato prototipo) sono una caratteristica obsoleta.

Ed ecco la differenza. Essendo un dichiaratore di funzione, int main() è in cattivo stato a causa di quanto sopra, poiché non è garantito il funzionamento nella prossima versione dello standard C. È contrassegnato come una caratteristica obsoleta in C11.

Si consiglia pertanto di utilizzare sempre int main (void) su un sistema ospitato e mai int main(), anche se i due moduli sono, per ora, equivalenti.


In C++ entrambe le forme sono del tutto equivalenti, ma c'è int main() è lo stile preferito per soggettivi, ragioni estetiche (Bjarne Stroustrup dice così ... che è probabilmente piuttosto una cattiva logica per spiegare perché si fa qualcosa in un un modo particolare).

+0

"' int main() 'è lo stile preferito per ragioni soggettive, estetiche" - forse soggettivo, ok, ma IMO è ancora giusto. '()' è chiaramente una tupla vuota. '(void)' sembra che sia un singolo argomento di tipo 'void', e quindi ti aspetteresti di poter scrivere cose come' main (f()) ', se' f' è una funzione che "restituisce nulla" ”. È una buona idea fare una distinzione tra insiemi vuoti (/ liste/matrici/tuple) e insiemi di un elemento il cui membro sembra essere vacuo. (A parte questo, se oggettivamente non importa se scrivi "void" o no, allora segui il rasoio di caldaia di Occam ... – leftaroundabout

0

So che il thread è vecchio, ma questa domanda mi ha infastidito per un po 'di anni fa, quindi ho voluto inserire il mio mezzo centesimo (se quello).

Trovo sempre che C funzioni come se avessero una quantità fissa di argomenti indipendentemente dal contesto, a meno che non utilizzino va_args. Cioè, ho fiducia principale di avere sempre il prototipo:

int main(int argc, char **argv). 

anche se sono passati senza argomenti, la funzione ha questi argomenti sullo stack perché la funzione principale non ha funzione di sovraccarico.

C ha la capacità di avere un sovraccarico primitivo semplicemente facendo finta che l'argomento non sia presente. In tal caso, l'argomento è ancora passato ed è in pila ma non lo si accede mai, quindi riduce semplicemente la dimensione del codice sorgente.

Dicendo int main() significa semplicemente che so che la funzione potrebbe avere parametri, ma non li sto utilizzando, quindi scrivo int main().

Dire int main (void) dice che principale ha certamente nessun argomento, e implica che ci sono due diversi prototipi di funzione:

int main(void); 
int main(int argc, char **argv); 

Dato che C non ha alcuna funzione sovraccarico, questo è un po 'fuorviante per me, e Diffido del codice che ha il principale (vuoto) in esso. Non lo farei se main non avesse MAI preso alcun parametro, nel qual caso main (void) sarebbe completamente OK.

NOTA: In alcune implementazioni, ci sono più parametri in main che argc e argv, come env, ma questo non mi infastidisce perché so che non dico esplicitamente che quelli sono gli unici due parametri, ma quelli sono i parametri minimi e va bene avere di più, ma non di meno. Questo è in contrasto con il vero detto int main (void) che mi urla come QUESTA FUNZIONE NON HA PARAMETRI, il che non è vero, dal momento che lo fa, vengono semplicemente omessi.

Ecco il mio codice base:

/* sample.c - build into sample. */ 
#include <stdio.h> 

int main(void) 
{ 
    int _argc = *((int *)2686800); 
    char ***_pargv = (char ***)2686804; 
    int i; 

    for (i = 1; i < _argc; ++i) { 
     printf("%s ", (*_pargv)[i]); 
    } 

    return 0; 
} 

./sample ho chiaramente argomenti

La funzione ha chiaramente argomenti passati ad esso, nonostante andando fuori del modo di dire esplicitamente che doesn' t digitando void nel prototipo della funzione.

Come Eq- dice sopra:

(6.7.6.3p10) Il caso particolare di un parametro senza nome di tipo vuoto come unico elemento nell'elenco specifica che la funzione ha parametri.

Così dicendo che la funzione è vuota come argomento ma in realtà avere argomenti in pila è una contraddizione.

Il mio punto è che gli argomenti sono ancora lì, quindi affermare esplicitamente che il principale è privo di argomenti è disonesto. Il modo onesto sarebbe quello di dire int main(), che non pretende nulla su quanti parametri ha, solo su quanti parametri ti interessa.

NOTA 2: Il _argc, _pargv dipendono dal sistema, per trovare il vostro valori li si deve scoprire eseguendo questo programma:

/* findargs.c */ 
#include <stdio.h> 

int main(int argc, char **argv) 
{ 
    printf("address of argc is %u.\n", &argc); 
    printf("address of argv is %u.\n", &argv); 

    return 0; 
} 

Questi valori dovrebbero rimanere corretto per il sistema specifico.

Problemi correlati