Jakie są prawidłowe sygnatury funkcji main () C?

Jakie są naprawdę ważne sygnatury dla funkcji głównej w C? Wiem:

int main(int argc, char *argv[])

Czy są inne ważne?

Author: Solomon Ucko, 2010-01-21

5 answers

Standard C11 wyraźnie wymienia te dwa:

int main(void);
int main(int argc, char* argv[]);

Chociaż wymienia zdanie "lub równoważne" z następującym przypisem:

Tak więc, int można zastąpić nazwą typedef zdefiniowaną jako int, lub typem argv można zapisać jako char ** argv, i tak dalej.

Ponadto przewiduje on również więcej (zdefiniowanych w implementacji) możliwości.

Odpowiedni tekst (Sekcja 5.1.2.2.1, ale ten szczególny aspekt pozostaje niezmieniony od C99) Stany:

Funkcja wywoływana przy starcie programu nosi nazwę main. Implementacja nie deklaruje prototypu dla tej funkcji. Definiuje się go za pomocą typu zwrotu int i bez parametrów:

int main(void) { /* ... */ }

Lub z dwoma parametrami (określanymi tutaj jako argc i argv, choć mogą być użyte dowolne nazwy, ponieważ są lokalne dla funkcji, w której są zadeklarowane):

int main(int argc, char *argv[]) { /* ... */ }

Lub równoważne; lub w inny sposób określony w implementacji.

Jeśli są deklarowane parametry funkcji main muszą spełniać następujące ograniczenia:

  • Wartość argc jest nonnegatywna.

  • argv[argc] jest wskaźnikiem zerowym.

  • Jeśli wartość argc jest większa od zera, elementy tablicy argv[0] do argv[argc-1] inclusive powinny zawierać wskaźniki do łańcuchów znaków, które są podane przez środowisko hosta wartości zdefiniowane przez implementację przed uruchomieniem programu. Celem jest dostarczenie do informacje o programie określone przed uruchomieniem programu z innego miejsca w środowisku hostowanym. Jeśli środowisko hosta nie jest w stanie dostarczyć ciągów znaków z wielkimi i małymi literami, implementacja zapewnia, że ciągi znaków są odbierane małymi literami.

  • Jeśli wartość argc jest większa od zera, łańcuch wskazywany przez argv[0] reprezentuje nazwę programu; argv[0][0] jest znakiem null, jeśli nazwa programu nie jest dostępna z hosta środowisko. Jeśli wartość argc jest większa niż jedna, łańcuchy wskazywane przez argv[1] przez argv[argc-1] reprezentują parametry programu.

  • Parametry argc i argv oraz ciągi znaków wskazywane przez tablicę argv mogą być modyfikowane przez program i zachowują swoje ostatnie zapisane wartości między uruchomieniem programu a zakończeniem programu.

Zauważ, że jest to środowisko hostowane, które zwykle widzisz w programach C. Wolnostojący środowisko (takie jak system wbudowany) jest znacznie mniej ograniczone, jak stwierdzono w 5.1.2.1 tego samego standardu:

W środowisku wolnostojącym (w którym wykonywanie programu C może odbywać się bez żadnych korzyści z systemu operacyjnego), nazwa i typ funkcji wywoływanej przy starcie programu są zdefiniowane jako implementacja. Wszystkie biblioteki dostępne dla wolnostojącego programu, inne niż minimalny zestaw wymagany przez klauzulę 4, są zdefiniowane w implementacji.

 77
Author: paxdiablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Standard C

Dla środowiska hostowanego (to normalne) Standard C99 mówi:]}

5.1.2.2.1 uruchamianie programu

Funkcja wywoływana przy starcie programu nosi nazwę main. Implementacja nie deklaruje prototypu dla tej funkcji. Definiuje się go za pomocą typu zwrotu int i bez parametrów:

int main(void) { /* ... */ }

Lub z dwoma parametrami (zwanymi tutaj argc i argv, choć można użyć dowolnych nazw, ponieważ są one lokalne dla funkcji w które są zadeklarowane):

int main(int argc, char *argv[]) { /* ... */ }

Lub równoważne;9) lub w inny sposób określony w implementacji.

9) Tak więc, int można zastąpić nazwą typedef zdefiniowaną jako int, lub typ argv można zapisać jako char **argv, i tak dalej.

Standardy C11 i C18 mówią zasadniczo to samo, co standard C99.

Standard C++

Standard C++98 mówi:

3.6.1 funkcja główna [basic.zaczynaj.main]

1 A program zawiera globalną funkcję o nazwie main, która jest wyznaczonym startem programu. [...]

2 implementacja nie powinna predefiniować funkcji głównej. Funkcja ta nie może być przeciążona. On ma typ zwracany typu int, ale poza tym jego typ jest zdefiniowany w implementacji. Wszystkie wdrożenia dopuszcza obie z następujących definicji main:

int main() { /* ... */ }

I

int main(int argc, char* argv[]) { /* ... */ }

Standard C++ mówi wprost: "to [główna funkcja] ma zwraca typ type int, ale poza tym jego typ jest zdefiniowany w implementacji " i wymaga tych samych dwóch podpisów co standard C. Tak więc 'void main ()' nie jest bezpośrednio dozwolone przez standard C++, chociaż nie ma nic, co mogłoby powstrzymać niestandardową zgodną implementację przed dopuszczeniem alternatyw (ani standardowa zgodna implementacja przed dopuszczeniem alternatyw jako rozszerzeń do standardu).

Standardy C++03, C++11, C++14 i C++17 mówią zasadniczo to samo co C++98

Rozszerzenie Wspólne

Klasycznie Systemy Unix wspierają trzeci wariant:

int main(int argc, char **argv, char **envp) { ... }

Trzeci argument jest zakończoną znakiem null listą wskaźników do łańcuchów znaków, z których każdy jest zmienną środowiskową, która ma nazwę, znak równości i wartość (być może pustą). Jeśli nie użyjesz tego, nadal możesz dostać się do środowiska przez " extern char **environ;". Ta zmienna nie jest (nadal) zadeklarowana w żadnym nagłówku POSIX (niezależnie od poprzednich wersji tej odpowiedzi).

To jest uznane przez standard C jako wspólne rozszerzenie, udokumentowane w załączniku J:

###J. 5.1 argumenty środowiska

¶1 w środowisku hostowanym, główna funkcja otrzymuje trzeci argument, char *envp[], wskazuje na zakończoną znakiem NUL tablicę wskaźników do char, z których każdy wskazuje na łańcuch znaków który dostarcza informacji o środowisku dla tego wykonania programu (5.1.2.2.1).

Microsoft C

Microsoft VS 2010 kompilator jest interesujące. Strona mówi:

Składnia deklaracji dla main to

 int main();

Lub, opcjonalnie,

int main(int argc, char *argv[], char *envp[]);

Alternatywnie, funkcje main i wmain mogą być zadeklarowane jako zwracające void (bez wartości zwracanej). Jeśli zadeklarujesz main lub wmain jako zwracający void, nie możesz zwrócić kodu zakończenia procesowi nadrzędnemu lub systemowi operacyjnemu za pomocą instrukcji return. Aby zwrócić kod wyjścia, gdy main lub wmain jest zadeklarowane jako void, musisz użyć exit funkcja.

Nie jest dla mnie jasne, co się dzieje (jaki kod zakończenia jest zwracany do rodzica lub o/S), gdy program z void main() kończy pracę - a strona MS też milczy.

Co ciekawe, MS nie przepisuje dwuargumentowej wersji main(), której wymagają standardy C i C++. Przepisuje on tylko formę trzech argumentów, gdzie trzecim argumentem jest char **envp, wskaźnik do listy zmiennych środowiskowych.

Strona Microsoft zawiera również inne alternatywy - wmain() który pobiera ciągi szerokich znaków i kilka innych.

Wersja Microsoft VS 2005 ta strona nie wymienia void main() jako alternatywy. Wersje od Microsoft VS 2008 dalej zrobić.

Czy int main() to to samo co int main(void)?

Aby uzyskać szczegółową analizę, zobacz koniec mojej odpowiedzi na co powinno main() zwrócić w C i C++. (Wydaje mi się, że kiedyś uznałem, że to pytanie odnosi się do C++, mimo że nie i nigdy tak. W C++ nie ma różnicy między int main() a int main(void) i int main() jest idiomatycznym C++.)

W C Istnieje różnica między tymi dwoma notacjami, ale zauważasz to tylko w ezoterycznych przypadkach. W szczególności, jest różnica, jeśli wywołujesz funkcję main() z własnego kodu, co możesz robić w C, a nie w C++.

Notacja int main() nie dostarcza prototypu dla main(), ale ma to znaczenie tylko wtedy, gdy nazwiemy ją rekurencyjnie. Z int main(), ty może później (w tej samej funkcji, lub w innej funkcji) napisać int rc = main("absolute", "twaddle", 2): i formalnie kompilator nie powinien narzekać do tego stopnia, że odmawia kompilacji kodu, chociaż może słusznie narzekać (ostrzegać) o tym (a użycie {[44] } Z GCC przekonwertowałoby ostrzeżenie na błąd). Jeśli użyjesz int main(void), kolejne wywołanie {[29] } powinno wygenerować błąd - powiedziałeś, że funkcja nie pobiera argumentów, ale próbowała podać trzy. Oczywiście, nie możesz legalnie zadzwonić main() zanim Zadeklarowana lub zdefiniowana (chyba że nadal używasz semantyki C90) - a implementacja nie deklaruje prototypu dla main(). Uwaga: standard C11 ilustruje zarówno int main(), jak i int main(void) w różnych przykładach - oba są ważne w C, mimo że istnieje między nimi subtelna różnica.

 19
Author: Jonathan Leffler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-16 20:24:54

POSIX obsługuje execve(), który z kolei obsługuje

int main(int argc, char *argv[], char *envp[])

Dodanym argumentem jest środowisko, tzn. tablica łańcuchów postaci nazwa = wartość.

 8
Author: unwind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-21 09:53:43

Http://en.wikipedia.org/wiki/Main_function_ (programowanie)#C_and_C.2B.2B

Oprócz zwykłego int main(int argc, char *argv[]) i POSIX int main(int argc, char **argv, char **envp), Na Mac OS X obsługuje również

int main(int argc, char* argv[], char* envp[], char* apple[]);
Oczywiście, że tylko Mac.

Na Windows jest

int wmain(int argc, wchar_t* argv[], wchar_t* envp[]);

Jako wariant Unicode (właściwie szerokoznakowy). Oczywiście, że jest też WinMain.

 8
Author: kennytm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-21 10:06:45
int main(void)

W niektórych systemach operacyjnych (na przykład Windows) również takie jest ważne:

int main(int argc, char **argv, char **envp)

Gdzie envp daje środowisko, w przeciwnym razie dostępne przez getenv()

 3
Author: flashnik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-21 09:52:24