Хто отримує значення, повернене main ()?


34

Я знаю, що в комп'ютерах значення, повернене main()функцією, отримує операційна система. Але, що відбувається у main()функції мікроконтролера?


7
Я завжди використовую void main (), коли використовую C для мікроконтролерів PIC. Використовуючи компілятори C для мікроконтролерів, це насправді зовсім не має значення. Тому що немає операційної системи, яка б запускала (скажімо) "main.c". Якщо в цьому мікроконтролері працює щось на зразок RTOS, то операційна система є "main.c".
abdullah kahraman

4
Не справжній дублікат, але принаймні пов’язаний: electronics.stackexchange.com/q/30830/4950
PetPaulsen

1
Як визначати функцію запуску, зазвичай не вирішувати. Навколишнє середовище, яке ви використовуєте, документує підтримувані форми функції запуску. Розміщені C-реалізації потрібно підтримувати дві форми mainз двома різними підписами, обидві з яких повертаються int. Якщо ви використовуєте автономну реалізацію C, ця програма диктує, як слід записати функцію запуску. Ви не можете написати функцію voidповернення лише тому, що вона не повертається. Поведінка не повернення відрізняється від функції типу , яка впливає на загальні угоди про виклики.
Каз

Відповіді:


42

На мікроконтролері main()насправді не очікується, що він коли-небудь вийде, і поведінка, якщо вона є, не визначена - тож це залежить від того, хто написав час виконання C для мікроконтролера. Я бачив системи, які:

  • Майте неявну петлю навколо main(), так що якщо вона вийде, її просто знову викликають.
  • Майте простий цикл "стрибати до себе", який виконується, якщо він main()коли-небудь закривається.
  • Просто виконайте решту пам'яті коду, яка слідує за викликом main(). Це називається "біг у бур'яни".

Я ніколи не бачив жодного, який насправді робить щось взагалі зі значенням, яке повертає main(). Якщо це насправді вас хвилює, то слід поглянути на (і, можливо, змінити) вихідний код для бібліотеки виконання C вашої системи.


1
Ти побив мене до цього. +1 для синхронності.
Адам Лоуренс

9
Стандарт C визначення main()мати intзначення, що повертається , очевидно , ні розроблений з OS-менш мікро контролером на увазі. Отже, це не визначена поведінка, і все, що може статися, залежно від вашого C часу виконання, як перелічив Дейв.
ndim

4
C, що працює на мікроконтролері без ОС, можна вважати самостійною реалізацією, а стандарт C навіть не вимагає, щоб автономний оточуючий засіб мав, а main()тим більше визначав його повернене значення. Це залежить від виконавця.
KutuluMike

2
@ndim - для роздвоєння волосся, void main( void )це визначена поведінкою поведінка , а не визначена поведінка .
Андрій

1
@MichaelEdenfield: Дійсно. Тим НЕ менше, все - код в C визначається в термінах функцій, тому вона ніколи не може належати систему fresstanding повністю написаний на C; повинно бути принаймні крихітний бік мови складання (або будь-якого іншого), який створює мінімальне середовище, щоб можна було викликати функцію C. Найбільш очевидною назвою цієї функції є main().
Трейд Дейв

5

Поширене непорозуміння / міф - int mainце єдина дійсна форма, визначена стандартом. Це не правда.

Стандарт C говорить про дві реалізації: розміщену та автономну. "Реалізація" в цьому випадку означає компілятор. Розміщені компілятори для компіляції для певної ОС, а автономні компілятори компілюють для конкретної програми з голого металу. Вбудовані системи майже завжди є автономними системами - навіть у випадку RTOS.

Автономні реалізації можуть використовувати будь-яку форму для main(), їм навіть не потрібно мати функцію, яку називають main. Найчастіше вони використовують форму void main (void), оскільки не має сенсу нічого повертати.

Тут важливо усвідомити, що завжди компілятор визначає форму, main()а ніколи програміст.

Самостійні реалізації, які щось повертають main(), дуже сумнівні. Змушує задуматися, чи люди, які зробили компілятор, насправді читали стандарт ...

Деталі тут .


3

Стандарт мови C дозволяє застосовувати певні варіанти реалізації, void main( void )і це звичайна форма у вбудованих системах - просто тому, що від них не очікується повернення.

Якщо ви подивитесь на налаштування компілятора, перед тим, як викликати main (), зазвичай є фрагмент завантажувального коду, що викликається з вектора скидання, який виконує деякі основні ініціалізації (включаючи, наприклад, копіювання значень ініціалізації у змінні).

Це також (як правило) буде знаходитися в нескінченному циклі або, можливо, виконувати скидання, якщо main()повернеться


0

Це (як згадуються інші відповіді) залежить від вашої ланцюга інструментів, але, наприклад, у GCC mainскладається як інші функції, тому його повернене значення буде зберігатися відповідно до умовних викликів (для ARM, який я використовую правильно, а не GCC, він буде поставлений до R0 безпосередньо перед поверненням).

Я думаю, що це схоже на AVR-GCC, тому користувацький сценарій може використовувати це значення після основної віддачі.


це швидше пропускає суть
Кріс Страттон

Він підкреслює, що той, хто дзвонить, mainможе отримати свою віддачу. Звичайно, це ігнорується в 99,9% ситуацій, але відповідь дає інформацію, хто може отримати це повернене значення.
kwesolowski
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.