«Int main (vooid)»? Comment ça marche?

135

J'ai récemment dû taper un petit programme de test C et, dans le processus, j'ai commis une faute d'orthographe dans la fonction principale en utilisant accidentellement vooidau lieu de void.

Et pourtant, cela fonctionnait toujours.

En le réduisant à sa plus petite version complète, je me suis retrouvé avec:

int main (vooid) {
    return 42;
}

Cela compile effectivement ( gcc -Wall -o myprog myprog.c) et, lorsqu'il est exécuté, il renvoie 42.

Comment est exactement ce code valide?


Voici une transcription coupée et collée de mon bashshell pour montrer ce que je fais:

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

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

pax$ echo $?
42
paxdiablo
la source
En définissant main avec un seul intparamètre, vous appelez le comportement indéfini . Tout peut arriver :)
pmg
9
En fait, je ne suis pas sûr de l'UB, @pmg. ISO permet spécifiquement d'autres possibilités mainparmi les deux standard canoniques. Pour la portabilité, vous devriez utiliser l'un de ces deux mais je ne pense pas que UB s'applique ici.
paxdiablo
Hmm: dans un environnement hébergé maindoit avoir l'une des 2 formes canoniques (2.1.2.2). Mais vous avez raison @pax, dans un environnement autonome, l'identifiant mainn'est en aucun cas spécial: s'il est utilisé comme une fonction, il peut être de n'importe quel type et avoir n'importe quel nombre de paramètres de n'importe quel type.
pmg
2
Dans C99, l'autonomie est totalement définie par l'implémentation. Pour hébergé, la section 5.1.2.2.1 indique à la fin "ou d'une autre manière définie par l'implémentation" donc elle nécessite, au minimum, les deux formes canoniques mais peut en avoir d'autres aussi (cela permettrait à UNIXy int main (int argc, char *argv[], char *envp[]);d'être conforme ).
paxdiablo

Réponses:

220

Il utilise simplement la syntaxe de déclaration de fonction «à l'ancienne»; vous déclarez implicitement un intparamètre appelé vooid.

Oliver Charlesworth
la source
2
Cela semble être le cas. Si vous ajoutez "vooid = 42; return vooid;" à main, vous obtenez également une valeur de retour de 42.
Jeff Ames
43
Aargghh, tu as raison. Si j'ajoute -std=c99, je reçois qq.c:1: warning: type of 'vooid' defaults to 'int'.
paxdiablo
70

C'est un code valide, car myprog.c contient:

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

vooidcontient un plus le nombre d'arguments passés (c'est-à-dire argc). Donc, tout ce que vous avez fait en effet est de renommer argcà vooid.

Michael Goldshteyn
la source
11
Si vous faites "return vooid;" au lieu de cela, il donne en effet 1 + num. d'arguments.
Jeff Ames
6
@Jeff, le nom du programme est compté comme un argument, d'où le + 1
Martin Beckett
23

En C, le type par défaut d'un argument de fonction est int. Donc, votre programme traite le mot vooidcomme int main(int vooid)un code parfaitement valide.

Chinmay Kanchi
la source
20

C'est seulement gcc -std=c89 -Wall -o qq qq.cet gcc -std=gnu89 -Wall -o qq qq.cn'émet pas d'avertissement. Toutes les autres normes émettent un avertissement sur le type implicite intpour vooid.

int main(chart)se comporte de la même manière que int main (vooid).

return vooid; renvoie le nombre d'arguments de ligne de commande.

J'ai testé avec gcc 4.4.5 sur le système de test Debian.

vpit3833
la source