„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

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.


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.


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.


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.