"Int main (vooid)"? Wie funktioniert das?

135

Ich musste kürzlich ein kleines C-Testprogramm eingeben und habe dabei einen Rechtschreibfehler in der Hauptfunktion gemacht, indem ich versehentlich vooidanstelle von verwendet habe void.

Und trotzdem hat es funktioniert.

Als ich es auf die kleinste vollständige Version reduzierte, endete ich mit:

int main (vooid) {
    return 42;
}

Dies kompiliert tatsächlich ( gcc -Wall -o myprog myprog.c) und gibt beim Ausführen 42 zurück.

Wie genau ist dieser gültige Code?


Hier ist ein Transkript, das aus meiner bashShell ausgeschnitten und eingefügt wurde, um zu zeigen, was ich tue:

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

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

pax$ echo $?
42
paxdiablo
quelle
Indem Sie main mit einem einzelnen intParameter definieren, rufen Sie Undefined Behavior auf . Alles kann passieren :)
pmg
9
Eigentlich bin ich mir nicht sicher über die UB, @pmg. ISO erlaubt speziell andere Möglichkeiten mainvon den Standard zwei kanonischen. Für die Portabilität sollten Sie eine dieser beiden verwenden, aber ich denke nicht, dass UB hier gilt.
Paxdiablo
Hmm: In einer gehosteten Umgebung mainmuss eine der beiden kanonischen Formen vorliegen (2.1.2.2). Aber Sie haben Recht @pax, in einer freistehenden Umgebung ist der Bezeichner mainin keiner Weise speziell: Wenn er als Funktion verwendet wird, kann er von einem beliebigen Typ sein und eine beliebige Anzahl von Parametern eines beliebigen Typs haben.
PMG
2
In C99 ist freistehend vollständig implementierungsdefiniert. Für gehostete, Abschnitt 5.1.2.2.1 Staaten am Ende „oder in einer anderen Implementierung definiert Art und Weise“ , so dass es, auf ein Minimum erfordert, die beiden kanonischen Formen können aber auch andere haben (dies ist der Unixy erlauben würde , int main (int argc, char *argv[], char *envp[]);konform zu sein ).
Paxdiablo

Antworten:

220

Es wird einfach die Syntax der Funktionsdeklaration im "alten Stil" verwendet. Sie deklarieren implizit einen intParameter namens vooid.

Oliver Charlesworth
quelle
2
Dies scheint der Fall zu sein. Wenn Sie "vooid = 42; return vooid;" zu main erhalten Sie auch einen Rückgabewert von 42.
Jeff Ames
43
Aargghh, du hast recht. Wenn ich hinzufüge -std=c99, bekomme ich qq.c:1: warning: type of 'vooid' defaults to 'int'.
Paxdiablo
70

Es ist ein gültiger Code, da myprog.c Folgendes enthält:

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

vooidenthält eins plus die Anzahl der übergebenen Argumente (dh argc). Also in der Tat alles , was Sie getan haben , ist zu umbenennen argczu vooid.

Michael Goldshteyn
quelle
11
Wenn Sie "void zurückgeben"; stattdessen gibt es tatsächlich 1 + num. von args.
Jeff Ames
6
@ Jeff, der Name des Programms wird als Argument gezählt, daher die + 1
Martin Beckett
23

In C ist der Standardtyp für ein Funktionsargument int. Ihr Programm behandelt das Wort also vooidals einen int main(int vooid)vollkommen gültigen Code.

Chinmay Kanchi
quelle
20

Es ist nur gcc -std=c89 -Wall -o qq qq.cund gcc -std=gnu89 -Wall -o qq qq.ckeine Warnung ausgeben. Alle anderen Standards geben eine Warnung über den impliziten Typ intfür aus vooid.

int main(chart)verhält sich genauso wie int main (vooid).

return vooid; Gibt die Anzahl der Befehlszeilenargumente zurück.

Ich habe mit gcc 4.4.5 auf dem Debian-Testsystem getestet.

vpit3833
quelle