Kto otrzymuje wartość zwróconą przez main ()?


34

Wiem, że w komputerach wartość zwracana przez main()funkcję jest odbierana przez system operacyjny. Ale co dzieje się w main()funkcji mikrokontrolera?


7
Zawsze używam void main (), gdy używam C do mikrokontrolerów PIC. Kiedy używasz kompilatorów C do mikrokontrolerów, to naprawdę nie ma znaczenia. Ponieważ nie ma systemu operacyjnego, który uruchamia (powiedzmy) „main.c”. Jeśli w tym mikrokontrolerze działa coś takiego jak RTOS, wówczas systemem operacyjnym jest „main.c”.
abdullah kahraman


1
Sposób definiowania funkcji uruchamiania zwykle nie zależy od ciebie. Środowisko, którego używasz, udokumentuje obsługiwane formularze funkcji uruchamiania. Hostowane implementacje C są wymagane do obsługi dwóch form mainz dwoma różnymi podpisami, które zwracają int. Jeśli używasz wolnostojącej implementacji języka C, ta implementacja decyduje o sposobie pisania funkcji uruchamiania. Nie możesz napisać voidfunkcji zwracającej tylko dlatego, że ona nie zwraca. Zachowanie o powrocie nie różni się od funkcji rodzaju co wpływa na ogólne konwencje dzwoni.
Kaz

Odpowiedzi:


42

Na mikrokontrolerze main()tak naprawdę nie oczekuje się, że kiedykolwiek wyjdzie, a zachowanie, jeśli nie jest określone - zależy więc od tego, kto napisał środowisko uruchomieniowe C dla mikrokontrolera. Widziałem systemy, które:

  • Miej niejawną pętlę main(), aby po wyjściu z niego po prostu ponownie wywołać.
  • Mają prostą pętlę „skok do siebie”, która zostanie wykonana, jeśli main()kiedykolwiek wyjdzie.
  • Po prostu uruchom resztę pamięci kodu, która następuje po wywołaniu main(). Nazywa się to „uciekaniem w chwasty”.

Nigdy nie widziałem takiego, który faktycznie robi cokolwiek z wartością zwracaną przez main(). Jeśli tak naprawdę na tym ci zależy, powinieneś rzucić okiem - i być może zmodyfikować - kod źródłowy biblioteki środowiska uruchomieniowego C.


1
Pobiłeś mnie do tego. +1 za synchroniczność.
Adam Lawrence

9
Średnia C definiowania main()mieć intwartość zwracaną oczywiście nie został zaprojektowany z mikrokontrolerem OS-mniej w umyśle. Jest to więc nieokreślone zachowanie i wszystko może się zdarzyć w zależności od środowiska uruchomieniowego C, zgodnie z listą Dave'a.
ndim

4
C działające na mikrokontrolerze bez systemu operacyjnego można uznać za implementację wolnostojącą, a standard C nie wymaga nawet środowiska wolnostojącego, aby mieć, a main()tym bardziej zdefiniować jego wartość zwracaną. To zależy od implementatora.
KutuluMike,

2
@ndim - dzielić włosy, void main( void )to zachowanie zdefiniowane w implementacji , a nie zachowanie nieokreślone .
Andrew

1
@MichaelEdenfield: Rzeczywiście. Jednak cały kod w C jest zdefiniowany pod względem funkcji, więc nigdy nie jest możliwe, aby system odświeżania był całkowicie napisany w C; musi istnieć przynajmniej odrobina języka asemblera (lub cokolwiek innego), który tworzy minimalne środowisko, aby można było wywołać funkcję C. Najbardziej oczywistą nazwą tej funkcji jest main().
Dave Tweed

5

Powszechnym nieporozumieniem / mitem jest to, że int mainjest to jedyna poprawna forma określona przez standard. To nie jest prawda.

Standard C mówi o dwóch implementacjach: hostowanej i wolnostojącej. „Implementacja” w tym przypadku oznacza kompilator. Hostowane kompilatory kompilują się dla określonego systemu operacyjnego, a kompilatory wolnostojące kompilują dla określonej aplikacji bez systemu metalowego. Systemy wbudowane są prawie zawsze systemami wolnostojącymi - nawet w przypadku RTOS.

Implementacje wolnostojące mogą używać dowolnej formy main(), nawet nie muszą mieć funkcji o nazwie main. Najczęściej używają formularza void main (void), ponieważ nie ma sensu niczego zwracać.

Ważne jest, aby zdawać sobie sprawę z tego, że to zawsze kompilator decyduje o formie, main()a nie programista.

Wolnostojące implementacje, które coś zwracają, main()są bardzo wątpliwe. Sprawia, że ​​zastanawiasz się, czy ludzie, którzy stworzyli kompilator, faktycznie czytają ten standard ...

Szczegóły tutaj .


3

Standard języka C dopuszcza zmienność zdefiniowaną w implementacji void main( void )i jest to zwykła forma w systemach wbudowanych - po prostu dlatego, że nie oczekuje się ich powrotu.

Jeśli spojrzysz na ustawienia kompilatora, zwykle istnieje fragment kodu bootstrap, wywoływany z wektora resetowania, który wykonuje podstawową inicjalizację (w tym np. Kopiowanie wartości inicjujących do zmiennych) przed wywołaniem main ().

Będzie to również (zwykle) w nieskończonej pętli lub może wykonać reset, jeśli main()powróci


0

To (jak wspomniano inne odpowiedzi) zależy od twojego zestawu narzędzi, ale na przykład w GCC mainjest kompilowany jako inne funkcje, więc jego wartość zwracana będzie przechowywana zgodnie z konwencjami wywoływania (na ARM używam prawa nie z GCC, to zostanie ustawiony na R0 tuż przed powrotem).

Wydaje mi się, że tak jest w AVR-GCC, więc skrypt niestandardowy może użyć tej wartości po głównych zwrotach.


to raczej nie trafia w sedno
Chris Stratton

Podkreśla, że ​​ten, kto dzwoni, mainmoże uzyskać wartość zwrotu. Oczywiście jest to ignorowane w 99,9% sytuacjach, ale odpowiedź dostarcza informacji, kto może otrzymać tę zwracaną wartość.
kwesolowski,
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.