Чому `main` не може повернути дубль або String, а не int або void?


38

У багатьох мовах, таких як C, C ++ та Java, mainметод / функція має тип повернення voidабо int, але ні, doubleабо String. Які можуть бути причини цього?

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

Отже, моє запитання: чому у нього mainє підпис типу, який він має, а не інший?


16
Що б подвійне значення , що повертається в очах ? Що означає значення повернення рядка ?

1
ки розумієте, що це нічого не означає. Але будь-які інші причини та умовності?
JAVA

1
я думаю, що це нічого не означає, просто тому, що загалом було вибрано 0 для нормального виходу і не нуль для аномального. Int був обраний як найпростіший тип даних із широкою сумісністю між мовами. @ delnan
JAVA

@sunny З того, що мені вдалося зібрати з досвіду роботи з ОС, схожими на Unix, 0 використовується як "нормальний вихід" (0 помилок), оскільки це однозначно порівняно з іншими цілими значеннями. Оскільки більшість (не всі) сучасних мов розроблені так, щоб вони були схожі на (якщо вони не розроблені на звороті), а оскільки C був використаний для написання Unix, я б сказав, що це було історичне рішення KnR.
Джеймі Тейлор

3
@sunny "широка міжмовна сумісність" не була проблемою. C і UNIX були написані в тандемі. Причина, що багато інших мов повертають вкладиші, полягає в тому, що вони були створені для роботи в UNIX або UNIX-подібних середовищах

Відповіді:


85

Повернене значення mainмає передаватися операційній системі ( будь-якій операційній системі) єдиним, послідовним способом. Інформація, яку повинна знати операційна система, - це "програма успішно припинилася, або сталася помилка?"

Якщо це рядок, відповідь стає важкою для різних мов. Внутрішні рядки рядка Pascal (перший байт - довжина) та рядок FORTRAN (фіксований, доданий до деякого значення) та рядка C (нульове завершення) - всі різні. Це зробило б викликом повернення послідовного значення операційній системі. Якщо припустити, що це вирішено, що б ви зробили, щоб відповісти на питання, яке постало ОС у програмі? Порівняння рядків загрожує помилками ("успіх" проти "Успіх"), і хоча помилка може бути кориснішою людині, операційній системі або іншій програмі (оболонці) важче боротися. Існували також значні відмінності навіть у самих рядках - EBCDIC (з усіма кодовими сторінками) та ASCII.

Поплавці та подвійні не дають додаткового значення над цілим числом для передачі назад даних в ОС (і оболонку). Здебільшого жодна з цих частин комп'ютера не має чисел з плаваючою комою. Парні також не є численними, що ускладнює порівняння. Не перелічуючи, вони повідомляють про помилку (якщо ви вибрали певне значення для успіху). Знову ж таки, плаваючі точки не є послідовними - поплавок на 8-бітовій машині був іншим, ніж плаваючий на 16-бітній та 32-бітовій машині (а це лише "нормальні" - навіть у IBM, плаваюча точка не була стандартизована між машинами того ж виробника до 1980-х років). І тоді у вас є десятковий та двійковий комп'ютери. Значення з плаваючою комою не є послідовними і не надають змістовних даних назад.

Це дійсно залишає нам байт і ціле число як варіанти. Конвенція, яка була встановлена ​​як "0", була успішною, і все інше було помилкою. Ціле число дає більше місця, ніж байт для повідомлення про помилку. Його можна перерахувати (повернення 1 означає XYZ, повернення 2 означає ABC, повернення 3, означає DEF тощо) або використовувати як прапори ( 0x0001означає, що це не вдалося, 0x0002означає, що не вдалося, 0x0003означає і це, і те, що не вдалося). Обмеживши це лише байтом, можна легко вичерпати прапори (лише 8), тому рішення, ймовірно, було використовувати ціле число.


2
Я думаю, що main називається бібліотекою виконання / с ++ + до того, як os викличе її, яка також є шматочком коду, завантаженого разом з нашим кодом і викликається os @ MichaelT
JAVA

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

24
Я думаю, що ключовим моментом для розуміння є те, що main- на відміну від інших функцій у будь-якій програмі - це не частина протоколу, визначеного програмістом, а протокол, що використовується для взаємодії з хостом (ОС). Ви не можете його вибрати, тому що вибирати його ніколи не було. На більш прагматичному рівні UNIX очікує, що процес буде повернутий int, і протокол C-to-UNIX робить саме це. Аналогічний аргумент може бути зроблений для передачі аргументів: якби C був винайдений для ОС / хоста, який передав лише аргументи як аргументи (наприклад, жодного командного рядка), аргументи будуть замість рядків ints.
Євро Міцеллі

2
IBM взяла концепцію кодових сторінок з EBCDIC на свої ПК. Вони досі переслідують нас сьогодні, триває 35 років після введення IBM 5150. 7-бітний ASCII не має кодової сторінки, але 8-бітні коди символів можна інтерпретувати по-різному навіть на одному комп'ютері, залежно від налаштувань - - не кажучи вже про кодові сторінки, які кодують багатобайтові кодування. Тож насправді навіть гірше, ніж ви натякаєте в останньому реченні другого абзацу.
CVn

@EuroMicelli, це дуже приємна інформація, насправді дякую за це :)
JAVA

28

Ну, могло б .

Наприклад, в діалекті C, використовуваному в операційній системі Plan 9main , зазвичай оголошується voidфункцією, але статус виходу повертається в середовище виклику шляхом передачі вказівника рядка на exits()функцію. Порожній рядок позначає успіх, а будь-який не порожній рядок позначає певний збій. Це може бути реалізовано при наявності mainповертати char*результат.

І, безумовно, можна було б запровадити систему зі статусом floatабо doubleвихід.

То чому int? Це лише питання конвенції - і величезна цінність у тому, щоб операційні системи та програми, що працюють під ними, дотримувалися загальної конвенції.

Угода Unix полягає у використанні цілого коду статусу з 0, що позначає успіх і ненульове позначення провалу (тому що зазвичай існує лише один спосіб досягти успіху, але є кілька способів відмови). Я не знаю, що ця конвенція виникла з Unix; Я підозрюю, що він з'явився з попередніх операційних систем.

Плаваюча точка буде складнішою умовою, оскільки (a) підтримка з плаваючою комою не є універсальною; (b) складніше визначити відображення між значеннями з плаваючою комою та умовами помилок; (c) різні системи використовують різні плаваючі представлення точок та (d) просто уявіть собі задоволення відслідковувати помилку округлення у статусі виходу програми. Цілі особи, з іншого боку, дуже добре піддаються перерахуванню кодів помилок.

Як я вже згадував, план 9 використовує рядки, але це накладає певну складність для управління пам'яттю, кодування символів тощо. Наскільки я знаю, це була нова ідея, коли План 9 реалізував її, і вона не замінила існуючої поширена конвенція.

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


9

Значення, що повертається основним методом, є "кодом виходу". Він використовується програмою, що викликає абонент (як правило, баш) для перевірки, чи закінчилася програма, як очікувалося. Повернення цілого числа - це найпростіший спосіб зробити це на рівні ОС. Double не має сенсу для коду помилки, а String важко підтримувати на рівні ОС (немає GC).


3
Чому рядок потрібно збирати сміттям, а ціле число -?
Бред

4
@Brad, рядки мають змінну довжину до них і по суті будуть такими ж, як передача назад масиву, який може бути одним символом, а може бути тисячами. Динамічна пам'ять буде болем, тоді як int є досить фіксованим розміром, який не так важко впоратися.
JB King

-1

main повинен повернути статус програми, яка виконується. незалежно від того, чи вона виконується успішно (повернути 0, що є EXIT_SUCCESS), чи ні (повернення 1 означає EXIT_FAILURE) будь-яке ненульове число передає те саме значення, але нуль вказує на відсутність помилок або успішного виконання ..


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