"Int main (vuoto)"? Come funziona?


135

Di recente ho dovuto digitare un piccolo programma di test C e, nel processo, ho commesso un errore di ortografia nella funzione principale utilizzando accidentalmente vooidanzichévoid .

Eppure ha ancora funzionato.

Riducendolo alla sua versione completa più piccola, ho finito con:

int main (vooid) {
    return 42;
}

Questo effettivamente compila (gcc -Wall -o myprog myprog.c ) e, quando eseguito, restituisce 42.

Come è esattamente questo codice valido?


Ecco una trascrizione tagliata e incollata dalla mia bashshell per mostrare cosa sto facendo:

pax$ cat qq.c
int main (vooid) {
    return 42;
}

pax$ rm qq ; gcc -Wall -o qq qq.c ; ./qq

pax$ echo $?
42

Definendo main con un singolo intparametro, si richiama il comportamento indefinito . Tutto può succedere :)
pmg

9
In realtà, non sono sicuro dell'UB, @pmg. L'ISO prevede specificamente altre possibilità mainrispetto alle due standard canoniche standard. Per la portabilità, dovresti usare uno di quei due ma non credo che UB si applichi qui.
paxdiablo,

Hmm: in un ambiente ospitato maindeve avere una delle 2 forme canoniche (2.1.2.2). Ma hai ragione @pax, in un ambiente indipendente, l'identificatore non mainè affatto speciale: se usato come funzione può essere di qualsiasi tipo e avere un numero qualsiasi di parametri di qualsiasi tipo.
pm

2
In C99, il freestanding è totalmente definito dall'implementazione. Per quanto riguarda l'hosting, la sezione 5.1.2.2.1 afferma alla fine "o in qualche altro modo definito dall'implementazione", quindi richiede almeno le due forme canoniche ma può avere anche altre (ciò consentirebbe a UNIXy int main (int argc, char *argv[], char *envp[]);di essere conforme ).
paxdiablo,

Risposte:


220

Sta semplicemente usando la sintassi della dichiarazione di funzione "vecchio stile"; stai dichiarando implicitamente un intparametro chiamato vooid.


2
Questo sembra essere il caso. Se aggiungi "vooid = 42; return vooid;" alla principale, ottieni anche un valore di ritorno di 42.
Jeff Ames,

43
Aargghh, hai ragione. Se aggiungo -std=c99, ottengo qq.c:1: warning: type of 'vooid' defaults to 'int'.
paxdiablo,

70

È un codice valido, perché myprog.c contiene:

int main (vooid) // vooid is of type int, allowed, and an alias for argc
{     
  return 42; // The answer to the Ultimate Question
} 

vooidcontiene uno più il numero di argomenti passati (ovvero, argc). Così, in effetti tutto quello che hai fatto è per rinominare argca vooid.


11
Se si "restituisce il vuoto;" invece, dà effettivamente 1 + num. di args.
Jeff Ames,

6
@Jeff, il nome del programma è contato come argomento, quindi il + 1
Martin Beckett

23

In C, il tipo predefinito per un argomento di funzione è int. Quindi, il tuo programma sta trattando la parola vooidcome int main(int vooid), che è un codice perfettamente valido.


20

È solo gcc -std=c89 -Wall -o qq qq.ce gcc -std=gnu89 -Wall -o qq qq.cnon emettere un avviso. Tutti gli altri standard emettono un avvertimento sul tipo implicito intper vooid.

int main(chart)si comporta allo stesso modo int main (vooid).

return vooid; restituisce il numero di argomenti della riga di comando.

Ho provato con gcc 4.4.5 sul sistema di test Debian.

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.