Standard C - środowisko hostowane
W przypadku hostowanego środowiska (to jest normalne) standard C11 (ISO / IEC 9899: 2011) mówi:
5.1.2.2.1 Uruchomienie programu
Nazwana jest funkcja wywoływana podczas uruchamiania programu main
. Implementacja deklaruje brak prototypu dla tej funkcji. Należy go zdefiniować za pomocą typu zwrotu int
i bez parametrów:
int main(void) { /* ... */ }
lub z dwoma parametrami (określanymi tutaj jako argc
i argv
chociaż można używać dowolnych nazw, ponieważ są one lokalne dla funkcji, w której zostały zadeklarowane):
int main(int argc, char *argv[]) { /* ... */ }
lub odpowiednik; 10) lub w inny określony sposób.
Jeżeli zostaną zadeklarowane, parametry funkcji głównej muszą spełniać następujące ograniczenia:
- Wartość
argc
musi być nieujemna.
argv[argc]
będzie wskaźnikiem zerowym.
- Jeśli wartość
argc
jest większa od zera, elementy tablicy argv[0]
poprzez
argv[argc-1]
włącznie zawierają wskaźniki do łańcuchów, którym środowisko hosta otrzymuje wartości zdefiniowane w implementacji przed uruchomieniem programu. Celem jest dostarczenie do informacji o programie określonych przed uruchomieniem programu z innego miejsca w hostowanym środowisku. Jeśli środowisko hosta nie jest w stanie dostarczyć ciągów liter zarówno wielkimi, jak i małymi, wdrożenie zapewnia, że ciągi są odbierane małymi literami.
- Jeśli wartość
argc
jest większa od zera, ciąg wskazany przez argv[0]
oznacza nazwę programu; argv[0][0]
będzie znakiem pustym, jeśli nazwa programu nie jest dostępna w środowisku hosta. Jeśli wartość argc
jest większa niż jeden, ciągi wskazywane przez argv[1]
przez argv[argc-1]
reprezentują parametry programu.
- Parametry
argc
i argv
ciągi wskazane przez argv
tablicę mogą być modyfikowane przez program i zachowują swoje ostatnio zapisane wartości między uruchomieniem programu a zakończeniem programu.
10) Tak więc int
można go zastąpić nazwą typu zdefiniowanego jako int
lub typ argv
można zapisać jako
char **argv
i tak dalej.
Zakończenie programu w C99 lub C11
Zwrócona wartość main()
jest przekazywana do „środowiska” w sposób zdefiniowany w implementacji.
5.1.2.2.3 Zakończenie programu
1 Jeśli typ zwracany przez main
funkcję jest typem zgodnym int
, powrót z początkowego wywołania main
funkcji jest równoważny wywołaniu exit
funkcji z wartością zwróconą przez main
funkcję jako argument; 11) osiągnięcie wartości }
kończącej
main
funkcję powoduje zwrócenie wartości 0. Jeśli typ zwracany jest niezgodny int
, status zakończenia zwracany do środowiska hosta jest nieokreślony.
11) Zgodnie z 6.2.4, czasy życia obiektów z zadeklarowanym automatycznym czasem przechowywania main
zostaną zakończone w pierwszym przypadku, nawet jeśli nie miałyby miejsca w drugim przypadku.
Pamiętaj, że 0
jest to obowiązkowe jako „sukces”. Możesz używać EXIT_FAILURE
i EXIT_SUCCESS
od<stdlib.h>
jeśli wolisz, ale 0 jest dobrze rozwinięta, a więc jest 1. Patrz także zjazdu kody większa niż 255 - możliwe? .
W C89 (i stąd w Microsoft C) nie ma informacji o tym, co się stanie, jeśli main()
funkcja zwróci, ale nie określi wartości zwracanej; prowadzi to zatem do nieokreślonego zachowania.
7.22.4.4 exit
Funkcja
5 Wreszcie kontrola jest zwracana do środowiska hosta. Jeśli wartość status
wynosi zero lub EXIT_SUCCESS
, zwracana jest zdefiniowana w implementacji forma pomyślnego zakończenia statusu . Jeśli wartością status
jest EXIT_FAILURE
, zdefiniowana w implementacji forma statusu nieudanego zakończenia . W przeciwnym razie zwracany status jest zdefiniowany w implementacji.
Standard C ++ - środowisko hostowane
Norma C ++ 11 (ISO / IEC 14882: 2011) mówi:
3.6.1 Główna funkcja [basic.start.main]
1 Program powinien zawierać funkcję globalną o nazwie main, która jest wyznaczonym początkiem programu. [...]
2 Implementacja nie powinna predefiniować głównej funkcji. Ta funkcja nie może być przeciążona. Powinien mieć typ zwracany typu int, ale w przeciwnym razie jego typ jest zdefiniowany jako implementacja. Wszystkie implementacje powinny umożliwiać obie następujące definicje głównej:
int main() { /* ... */ }
i
int main(int argc, char* argv[]) { /* ... */ }
W tej ostatniej formie argc
powinna być liczba argumentów przekazanych do programu ze środowiska, w którym program jest uruchomiony. Jeśli argc
jest niezerowe argumenty te powinny być dostarczane w argv[0]
przez argv[argc-1]
jako wskaźniki do początkowych znaków NUL ciągów wielobajtowych (NTMBSs) (17.5.2.1.4.2) i argv[0]
powinien być wskaźnik do pierwotnego charakteru a NTMBS który reprezentuje nazwę używaną do wywołać program lub ""
. Wartość argc
musi być nieujemna. Wartość argv[argc]
powinna wynosić 0. [Uwaga: Zaleca się późniejsze dodanie (opcjonalnych) parametrów argv
. —Wskazówka]
¶3 Funkcji main
nie należy używać w programie. Połączenie (3.5) main
jest zdefiniowane w implementacji. [...]
5 Polecenie return w main powoduje pozostawienie funkcji main (zniszczenie dowolnych obiektów z automatycznym czasem przechowywania) i wywołanie std::exit
z wartością zwracaną jako argumentem. Jeśli kontrola osiągnie koniec Main bez napotkania instrukcji return, efektem jest wykonanie
return 0;
Standard C ++ wyraźnie mówi: „To [główna funkcja] powinna mieć typ zwracany typu int
, ale poza tym jego typ jest zdefiniowany w implementacji”, i wymaga tych samych dwóch sygnatur co standard C, aby był obsługiwany jako opcje. Zatem „void main ()” nie jest bezpośrednio dozwolone przez standard C ++, chociaż nic nie może zrobić, aby zatrzymać niestandardową implementację dopuszczającą alternatywy. Zauważ, że C ++ zabrania użytkownikowi dzwonienia main
(ale standard C nie).
W standardzie C ++ 11 znajduje się akapit §18.5 Rozpoczęcie i zakończenie, który jest identyczny z akapitem z § 7.22.4.4 . exit
Funkcja w standardzie C11 (cytowana powyżej), oprócz przypisu (który po prostu dokumentuje to EXIT_SUCCESS
i EXIT_FAILURE
jest zdefiniowana w <cstdlib>
).
Standard C - Wspólne rozszerzenie
Klasycznie systemy Unix obsługują trzeci wariant:
int main(int argc, char **argv, char **envp) { ... }
Trzeci argument to zakończona zerem lista wskaźników do ciągó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 tego nie użyjesz, nadal możesz dostać się do środowiska poprzez ' extern char **environ;
'. Ta zmienna globalna jest unikalna wśród tych w POSIX, ponieważ nie ma nagłówka, który ją deklaruje.
Jest to uznawane przez normę C za wspólne rozszerzenie, udokumentowane w załączniku J:
J.5.1 Argumenty środowiskowe
¶1 W środowisku hostowanym funkcja główna otrzymuje trzeci argument char *envp[]
wskazujący na zakończoną zerem tablicę wskaźników char
, z których każdy wskazuje na ciąg znaków informujący o środowisku dla wykonania programu (5.1. 2.2.1).
Microsoft C.
Microsoft VS 2010 kompilator jest interesująca. Strona internetowa 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
można zadeklarować jako zwracane void
(bez wartości zwracanej). Jeśli zadeklarujesz main
lub wmain
anulujesz, nie możesz zwrócić kodu wyjścia do procesu nadrzędnego lub systemu operacyjnego za pomocą instrukcji return. Aby zwrócić kod wyjścia, gdy main
lub wmain
jest zadeklarowany jako void
, musisz użyć exit
funkcji.
Nie jest dla mnie jasne, co się dzieje (jaki kod wyjścia jest zwracany do rodzica lub systemu operacyjnego), gdy program ma void main()
robi wyjście - a strona MS również milczy.
Co ciekawe, MS nie zaleca dwuargumentowej wersji main()
wymaganej przez standardy C i C ++. Określa tylko trzyargumentową formę, w której znajduje się trzeci argumentchar **envp
wskaźnikiem do listy zmiennych środowiskowych.
Strona Microsoft wymienia także kilka innych alternatyw - wmain()
które wymagają szerokich ciągów znaków i kilka innych.
Wersja tej strony programu Microsoft Visual Studio 2005 nie jest wymieniona jako alternatywa. W wersjach z Microsoft Visual Studio 2008 r robić.void main()
Standard C - środowisko wolnostojące
Jak wspomniano wcześniej, powyższe wymagania dotyczą środowisk hostowanych. Jeśli pracujesz w środowisku wolnostojącym (które jest alternatywą dla środowiska hostowanego), standard ma znacznie mniej do powiedzenia. W środowisku wolnostojącym funkcja wywoływana podczas uruchamiania programu nie musi być wywoływana main
i nie ma żadnych ograniczeń co do typu jej powrotu. Standard mówi:
5.1.2 Środowiska wykonawcze
Zdefiniowano dwa środowiska wykonawcze: wolnostojące i hostowane. W obu przypadkach uruchomienie programu następuje, gdy środowisko wykonawcze wywołuje wyznaczoną funkcję C. Wszystkie obiekty ze statycznym czasem przechowywania powinny zostać zainicjowane (ustawione na wartości początkowe) przed uruchomieniem programu. Sposób i czas takiej inicjalizacji są poza tym nieokreślone. Zakończenie programu zwraca kontrolę do środowiska wykonawczego.
5.1.2.1 Środowisko wolnostojące
W środowisku wolnostojącym (w którym wykonywanie programu C może odbywać się bez jakiejkolwiek korzyści systemu operacyjnego), nazwa i typ funkcji wywoływanej podczas uruchamiania programu są zdefiniowane pod względem implementacji. Wszelkie funkcje biblioteczne dostępne dla programu wolnostojącego, inne niż minimalny zestaw wymagany przez klauzulę 4, są zdefiniowane w implementacji.
Efekt zakończenia programu w środowisku wolnostojącym jest definiowany pod względem implementacji.
Odniesienie do klauzuli 4 Zgodność odnosi się do tego:
5 Program ściśle zgodny powinien używać tylko tych funkcji języka i biblioteki określonych w niniejszej Normie Międzynarodowej. 3) Nie będzie generować wyników zależnych od jakiegokolwiek nieokreślonego, niezdefiniowanego lub określonego dla implementacji zachowania i nie przekroczy żadnego minimalnego limitu implementacji.
¶6 Dwie formy implementacji zgodnej są hostowane i wolnostojące . Zgodne gospodarzem realizacja powinna przyjąć dowolny program ściśle zgodny. Wykonanie zgodne wolnostojące przyjmuje dowolny program ściśle zgodny, w których korzystanie z funkcji określonych w klauzuli biblioteki (klauzula 7) ogranicza się do zawartości standardowych nagłówków <float.h>
, <iso646.h>
, <limits.h>
, <stdalign.h>
,
<stdarg.h>
, <stdbool.h>
, <stddef.h>
, <stdint.h>
, i
<stdnoreturn.h>
. Implementacja zgodna może mieć rozszerzenia (w tym dodatkowe funkcje biblioteczne), pod warunkiem, że nie zmieniają zachowania żadnego ściśle zgodnego programu. 4)
7 Program zgodny jest programem akceptowanym przez implementację zgodną. 5)
3) Program ściśle zgodny może korzystać z funkcji warunkowych (patrz 6.10.8.3), pod warunkiem, że użycie jest chronione przez odpowiednią dyrektywę wstępnego przetwarzania warunkowego włączenia z wykorzystaniem powiązanego makra. Na przykład:
#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */
/* ... */
fesetround(FE_UPWARD);
/* ... */
#endif
4) Oznacza to, że zgodne wdrożenie nie zastrzega żadnych identyfikatorów innych niż te wyraźnie zastrzeżone w niniejszej Normie Międzynarodowej.
5) Programy ściśle zgodne mają być maksymalnie przenośne wśród zgodnych implementacji. Zgodne programy mogą zależeć od nieprzenośnych funkcji zgodnej implementacji.
Można zauważyć, że jedynym wymaganym nagłówkiem wolnostojącego środowiska, które faktycznie definiuje dowolne funkcje, jest <stdarg.h>
(a nawet te mogą - i często są - tylko makra).
Standard C ++ - środowisko wolnostojące
Podobnie jak standard C rozpoznaje zarówno środowisko hostowane, jak i wolnostojące, podobnie standard C ++. (Cytaty z ISO / IEC 14882: 2011.)
1.4 Zgodność z implementacją [wstęp. Zgodność]
¶7 Zdefiniowano dwa rodzaje implementacji: implementację hostowaną i implementację wolnostojącą . W przypadku hostowanej implementacji ten standard międzynarodowy określa zestaw dostępnych bibliotek. Wolnostojąca implementacja to taka, w której wykonanie może odbywać się bez korzyści systemu operacyjnego, i zawiera zdefiniowany przez implementację zestaw bibliotek, który zawiera pewne biblioteki obsługujące język (17.6.1.3).
8 Implementacja zgodna może mieć rozszerzenia (w tym dodatkowe funkcje biblioteczne), pod warunkiem, że nie zmieniają zachowania żadnego poprawnie sformułowanego programu. W celu zdiagnozowania programów korzystających z takich rozszerzeń, które są źle sformułowane zgodnie z niniejszym standardem międzynarodowym, wymagane są implementacje. Po wykonaniu tych czynności mogą jednak kompilować i uruchamiać takie programy.
9 Każda implementacja powinna zawierać dokumentację, która identyfikuje wszystkie konstrukcje wspierane warunkowo, których nie obsługuje i definiuje wszystkie cechy charakterystyczne dla ustawień regionalnych. 3)
3) Ta dokumentacja określa również zachowanie zdefiniowane w ramach implementacji; patrz 1.9.
17.6.1.3 Wdrożenia wolnostojące [zgodność]
Zdefiniowano dwa rodzaje implementacji: hostowany i wolnostojący (1.4). W przypadku hostowanej implementacji ten Międzynarodowy Standard opisuje zestaw dostępnych nagłówków.
Wolnostojąca implementacja ma zdefiniowany zestaw implementacji nagłówków. Zestaw ten zawiera co najmniej nagłówki przedstawione w tabeli 16.
Dostarczone wersja nagłówku <cstdlib>
deklarują przynajmniej funkcje abort
, atexit
, at_quick_exit
, exit
, i quick_exit
(18.5). Pozostałe nagłówki wymienione w tej tabeli muszą spełniać te same wymagania, co w przypadku hostowanej implementacji.
Tabela 16 - Nagłówki C ++ dla implementacji wolnostojących
Subclause Header(s)
<ciso646>
18.2 Types <cstddef>
18.3 Implementation properties <cfloat> <limits> <climits>
18.4 Integer types <cstdint>
18.5 Start and termination <cstdlib>
18.6 Dynamic memory management <new>
18.7 Type identification <typeinfo>
18.8 Exception handling <exception>
18.9 Initializer lists <initializer_list>
18.10 Other runtime support <cstdalign> <cstdarg> <cstdbool>
20.9 Type traits <type_traits>
29 Atomics <atomic>
Co z używaniem int main()
w C?
Norma §5.1.2.2.1 normy C11 pokazuje preferowaną notację - int main(void)
- ale są też dwa przykłady w normie, które pokazują int main()
: §6.5.3.4 ¶8 i §6.7.6.3 ¶20 . Należy teraz zauważyć, że przykłady nie są „normatywne”; są tylko przykładowe. Jeśli w przykładach występują błędy, nie wpływają one bezpośrednio na główny tekst standardu. To powiedziawszy, mocno wskazują na oczekiwane zachowanie, więc jeśli standard zawiera int main()
w przykładzie, sugeruje, że int main()
nie jest to zabronione, nawet jeśli nie jest to preferowany zapis.
6.5.3.4 Operatorzy sizeof
i_Alignof
…
8 PRZYKŁAD 3 W tym przykładzie wielkość tablicy o zmiennej długości jest obliczana i zwracana z funkcji:
#include <stddef.h>
size_t fsize3(int n)
{
char b[n+3]; // variable length array
return sizeof b; // execution time sizeof
}
int main()
{
size_t size;
size = fsize3(10); // fsize3 returns 13
return 0;
}