„Int main (vooid)”? Jak to działa?

135

Niedawno musiałem wpisać mały program testowy w języku C i podczas tego procesu popełniłem błąd w pisowni w funkcji głównej, przypadkowo używając vooidzamiast void.

A jednak nadal działało.

Sprowadzając go do najmniejszej pełnej wersji, otrzymałem:

int main (vooid) {
    return 42;
}

To rzeczywiście kompiluje ( gcc -Wall -o myprog myprog.c) i po uruchomieniu zwraca 42.

Jak dokładnie jest ten prawidłowy kod?


Oto transkrypcja wycięta i wklejona z mojej bashpowłoki, aby pokazać, co robię:

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

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

pax$ echo $?
42
paxdiablo
źródło
Definiując main za pomocą jednego intparametru, wywołujesz niezdefiniowane zachowanie . Wszystko może się zdarzyć :)
pmg
9
Właściwie nie jestem pewien co do UB, @pmg. W szczególności ISO dopuszcza inne możliwości mainspośród standardowych dwóch kanonicznych. Aby zapewnić przenośność, powinieneś użyć jednego z tych dwóch, ale nie sądzę, aby UB miało tutaj zastosowanie.
paxdiablo,
Hmm: w środowisku hostowanym mainmusi mieć jedną z 2 form kanonicznych (2.1.2.2). Ale masz rację @pax, w wolnostojącym środowisku identyfikator nie mainjest w żaden sposób specjalny: jeśli jest używany jako funkcja, może być dowolnego typu i mieć dowolną liczbę parametrów dowolnego typu.
pmg
2
W C99 wolnostojące jest całkowicie zdefiniowane jako implementacja. W przypadku hostingu sekcja 5.1.2.2.1 stwierdza na końcu „lub w inny sposób zdefiniowany w implementacji”, więc wymaga co najmniej dwóch form kanonicznych, ale może mieć również inne (pozwoliłoby to UNIXy int main (int argc, char *argv[], char *envp[]);na zgodność ).
paxdiablo

Odpowiedzi:

220

Po prostu używa "starego stylu" składni deklaracji funkcji; niejawnie deklarujesz intparametr o nazwie vooid.

Oliver Charlesworth
źródło
2
Wydaje się, że tak jest. Jeśli dodasz „vooid = 42; return vooid;” do main, otrzymasz również wartość zwracaną 42.
Jeff Ames,
43
Aargghh, masz rację. Jeśli dodam -std=c99, dostanę qq.c:1: warning: type of 'vooid' defaults to 'int'.
paxdiablo
70

To prawidłowy kod, ponieważ myprog.c zawiera:

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

vooidzawiera jeden plus liczbę przekazanych argumentów (tj argc.). W efekcie wszystko, co zrobiłeś, to zmiana nazwy argcna vooid.

Michael Goldshteyn
źródło
11
Jeśli wykonasz „powrót puste”; zamiast tego rzeczywiście daje 1 + num. argumentów.
Jeff Ames,
6
@Jeff, nazwa programu jest liczona jako argument, stąd +1
Martin Beckett,
23

W języku C domyślnym typem argumentu funkcji jest int. Zatem twój program traktuje słowo vooidjako int main(int vooid), co jest całkowicie poprawnym kodem.

Chinmay Kanchi
źródło
20

To tylko gcc -std=c89 -Wall -o qq qq.ci gcc -std=gnu89 -Wall -o qq qq.cnie wysyłaj ostrzeżenia. Wszystkie inne standardy wysyłają ostrzeżenie o niejawnym typie intdla vooid.

int main(chart)zachowuje się tak samo jak robi int main (vooid).

return vooid; zwraca liczbę argumentów wiersza poleceń.

Testowałem z gcc 4.4.5 w systemie testowym Debiana.

vpit3833
źródło