Что должно возвращать main() в C и C++?
Как правильно (наиболее эффективно) определить main()
функция в C и C++ - int main()
или же void main()
- и почему? Если int main()
затем return 1
или же return 0
?
Существует множество дубликатов этого вопроса, в том числе:
- Какие действительные подписи для C
main()
функционировать? - Тип возврата
main()
функция - Разница между
void main()
а такжеint main()
? main()
подпись в C++- Какова правильная декларация
main()
? - Для C++, с очень хорошим ответом. - Стили
main()
функции в C - Тип возврата
main()
метод в C int main()
противvoid main()
в С
Связанные с:
- C++ -
int main(int argc, char **argv)
- C++ -
int main(int argc, char *argv[])
- Является
char *envp[]
в качестве третьего аргументаmain()
портативный компьютер? - Должен
int main()
функция возвращает значение во всех компиляторах? - Почему тип
main()
Функция в C и C++ оставлена пользователю, чтобы определить? - Почему
int main(){}
компилировать? - Правовые определения
main()
в C++14?
22 ответа
Возвращаемое значение для main
должен указать, как программа вышла. Нормальный выход обычно представлен 0 возвращаемым значением из main
, Ненормальный выход обычно сигнализируется ненулевым возвратом, но не существует стандарта для интерпретации ненулевых кодов. Также, как отмечают другие, void main()
прямо запрещено стандартом C++ и не должно использоваться. Действительный C++ main
подписи:
int main()
а также
int main(int argc, char* argv[])
что эквивалентно
int main(int argc, char** argv)
Также стоит отметить, что в C++ int main()
может быть оставлено без возвращаемого значения, после чего по умолчанию возвращается 0. Это также верно для программы C99. Будь то return 0
должен быть опущен или не является открытым для обсуждения. Диапазон действительных основных сигнатур программы на Си намного больше.
Кроме того, эффективность не является проблемой с main
функция. Он может быть введен и оставлен только один раз (отмечен запуск и завершение программы) в соответствии со стандартом C++. Для C дело обстоит иначе и вводится повторно main()
разрешено, но следует избегать
Принятый ответ, по-видимому, предназначен для C++, поэтому я подумал, что добавлю ответ, относящийся к C, и он отличается в нескольких отношениях.
ISO / IEC 9899: 1989 (C90):
main()
должен быть объявлен как:
int main(void)
int main(int argc, char **argv)
Или эквивалент. Например, int main(int argc, char *argv[])
эквивалентно второму. Кроме того, int
возвращаемый тип может быть опущен, так как это значение по умолчанию.
Если реализация позволяет это, main()
может быть объявлено другими способами, но это делает реализацию программы определенной, и больше не является строго соответствующей.
Стандарт определяет 3 значения для возврата, которые строго соответствуют (то есть не зависят от поведения, определенного реализацией): 0
а также EXIT_SUCCESS
для успешного завершения, и EXIT_FAILURE
за неудачное завершение. Любые другие значения являются нестандартными и определяются реализацией. main()
должен иметь явное return
заявление в конце, чтобы избежать неопределенного поведения.
Наконец, с точки зрения стандартов, нет ничего плохого main()
из программы.
ISO / IEC 9899: 1999 (C99):
Для C99 все то же самое, что и выше, за исключением:
int
тип возврата не может быть опущен.- Вы можете опустить оператор возврата из
main()
, Если вы делаете, иmain()
закончено, есть неявноеreturn 0
,
Стандарт С - размещенная среда
Для размещенной среды (это нормальная среда) стандарт C11 (ISO/IEC 9899:2011) гласит:
5.1.2.2.1 Запуск программы
Функция, вызываемая при запуске программы, называется
main
, Реализация не объявляет прототип для этой функции. Он должен быть определен с типом возвратаint
и без параметров:int main(void) { /* ... */ }
или с двумя параметрами (упоминается здесь как
argc
а такжеargv
хотя могут использоваться любые имена, так как они являются локальными для функции, в которой они объявлены):int main(int argc, char *argv[]) { /* ... */ }
или эквивалент; 10) или каким-либо другим способом, определяемым реализацией.
Если они объявлены, параметры главной функции должны подчиняться следующим ограничениям:
- Значение
argc
должен быть неотрицательным.argv[argc]
должен быть нулевым указателем.- Если значение
argc
больше нуля, члены массиваargv[0]
черезargv[argc-1]
inclusive должен содержать указатели на строки, которым перед запуском программы передаются значения, определяемые реализацией хост-средой. Намерение состоит в том, чтобы предоставить программе информацию, определенную до ее запуска, из другой части размещенной среды. Если среда хоста не способна снабжать строки буквами как в верхнем, так и в нижнем регистре, реализация должна обеспечивать получение строк в нижнем регистре.- Если значение
argc
больше нуля, строка указанаargv[0]
представляет название программы;argv[0][0]
должен быть нулевым символом, если имя программы недоступно из среды хоста. Если значениеargc
больше единицы, строки, на которые указываетargv[1]
черезargv[argc-1]
представляют параметры программы.- Параметры
argc
а такжеargv
и строки, на которые указываетargv
массив должен изменяться программой и сохранять свои последние сохраненные значения между запуском программы и завершением программы.10) Таким образом,
int
может быть заменено именем typedef, определенным какint
или типargv
можно записать какchar **argv
, и так далее.
Завершение программы в C99 или C11
Значение, возвращаемое из main()
передается в "среду" способом, определяемым реализацией.
5.1.2.2.3 Завершение программы
1 Если тип возвращаемого значения
main
функция совместима с типомint
, возврат от первоначального вызова кmain
Функция эквивалентна вызовуexit
функция со значением, возвращаемымmain
функция в качестве аргумента; 11) достижение}
что завершаетmain
функция возвращает значение 0. Если тип возвращаемого значения не совместим сint
статус завершения, возвращаемый в хост-среду, не указан.11) В соответствии с 6.2.4 срок службы объектов с автоматической продолжительностью хранения, объявленный в
main
закончится в первом случае, даже если они не будут иметь во втором.
Обратите внимание, что 0
поручено как "успех". Ты можешь использовать EXIT_FAILURE
а также EXIT_SUCCESS
от <stdlib.h>
если вы предпочитаете, но 0 точно установлено, как и 1. Смотрите также. Коды выхода больше 255 - возможно?,
В C89 (и, следовательно, в Microsoft C) нет заявления о том, что произойдет, если main()
функция возвращает, но не указывает возвращаемое значение; следовательно, это ведет к неопределенному поведению.
7.22.4.4
exit
функцияFinally5 Наконец, управление возвращается в среду хоста. Если значение
status
ноль илиEXIT_SUCCESS
возвращается заданная реализацией форма успешного завершения статуса. Если значениеstatus
являетсяEXIT_FAILURE
возвращается форма реализации неудачного завершения статуса. В противном случае возвращаемый статус определяется реализацией.
Стандарт C++ - Хостинг-среда
Стандарт C++11 (ISO/IEC 14882:2011) гласит:
3.6.1 Основная функция [basic.start.main]
Program1 Программа должна содержать глобальную функцию main, которая является назначенным началом программы. [...]
An2 Реализация не должна предопределять основную функцию. Эта функция не должна быть перегружена. Он должен иметь возвращаемый тип типа int, но в противном случае его тип определяется реализацией. Все реализации должны позволять оба следующих определения main:
int main() { /* ... */ }
а также
int main(int argc, char* argv[]) { /* ... */ }
В последнем виде
argc
должно быть количеством аргументов, переданных программе из среды, в которой она запущена. Еслиargc
отличен от нуля эти аргументы должны быть представлены вargv[0]
черезargv[argc-1]
в качестве указателей на начальные символы многобайтовых строк с нулевым символом в конце (NTMBS) (17.5.2.1.4.2) иargv[0]
должен быть указателем на начальный символ NTMBS, который представляет имя, используемое для вызова программы или""
, Значениеargc
должен быть неотрицательным. Значениеargv[argc]
должно быть 0. [Примечание: рекомендуется добавлять любые дополнительные (необязательные) параметры послеargv
, —Конечная записка]№3 функция
main
не должны использоваться в программе. Связь (3.5) изmain
определяется реализацией. [...]Statement5 Оператор return в main приводит к выходу из главной функции (уничтожению любых объектов с автоматическим хранением) и вызову
std::exit
с возвращаемым значением в качестве аргумента. Если управление достигает конца main, не встречая оператора return, эффект заключается в выполненииreturn 0;
Стандарт C++ явно говорит: "Это [основная функция] должен иметь тип возвращаемого значения типа int
, но в противном случае его тип определяется реализацией "и требует, чтобы в качестве опций поддерживались те же две подписи, что и в стандарте C, поэтому стандарт void main() напрямую не разрешен стандартом C++, хотя он ничего не может сделать для остановить нестандартную реализацию, допускающую альтернативы. Обратите внимание, что C++ запрещает пользователю вызывать main
(но стандарт C не делает).
В стандарте C++11 есть параграф § 18.5 " Начало и конец", который идентичен абзацу из §7.22.4.4 . exit
функция в стандарте C11 (цитируется выше), кроме сноски (которая просто документирует, что EXIT_SUCCESS
а также EXIT_FAILURE
определены в <cstdlib>
).
Стандарт С - Общее расширение
Классически Unix-системы поддерживают третий вариант:
int main(int argc, char **argv, char **envp) { ... }
Третий аргумент представляет собой список указателей на строки с нулевым символом в конце, каждый из которых является переменной окружения, которая имеет имя, знак равенства и значение (возможно, пустое). Если вы не используете это, вы все равно можете получить в среду через extern char **environ;
". В течение долгого времени у этого не было заголовка, который объявил это, но стандарт POSIX 2008 теперь требует, чтобы он был объявлен в <unistd.h>
,
Это признано стандартом C как общее расширение, документированное в Приложении J:
J.5.1 Аргументы среды
In1 В размещенной среде главная функция получает третий аргумент,
char *envp[]
, что указывает на массив указателей с нулевым символом в концеchar
каждая из которых указывает на строку, которая предоставляет информацию о среде для этого выполнения программы (5.1.2.2.1).
Microsoft C
Компилятор Microsoft VS 2010 интересен. Веб-сайт говорит:
Синтаксис объявления для main
int main();
или, необязательно,
int main(int argc, char *argv[], char *envp[]);
В качестве альтернативы
main
а такжеwmain
функции могут быть объявлены как возвращающиеvoid
(нет возвращаемого значения). Если вы объявитеmain
или жеwmain
как возвращение void, вы не можете вернуть код завершения родительскому процессу или операционной системе с помощью оператора return. Чтобы вернуть код выхода, когдаmain
или жеwmain
объявлен какvoid
, вы должны использоватьexit
функция.
Мне не ясно, что происходит (какой код завершения возвращается родительскому или ОС), когда программа с void main()
выходит - и сайт MS тоже молчит.
Интересно, что MS не предписывает версию с двумя аргументами main()
что требуют стандарты C и C++. Это только предписывает форму с тремя аргументами, где третий аргумент char **envp
указатель на список переменных среды.
На странице Microsoft также перечислены некоторые другие альтернативы - wmain()
который принимает строки широких символов, и некоторые другие.
Microsoft Visual Studio 2005 версии этой страницы не перечислены void main()
как альтернатива. Версии от Microsoft Visual Studio 2008 и выше делают.
Стандарт С - автономная среда
Как уже отмечалось ранее, вышеуказанные требования применяются к размещенным средам. Если вы работаете с автономной средой (которая является альтернативой размещенной среде), то о стандарте можно сказать гораздо меньше. Для автономной среды не нужно вызывать функцию, вызываемую при запуске программы main
и нет никаких ограничений на его тип возвращаемого значения. Стандарт гласит:
5.1.2 Среды исполнения
Определены две среды исполнения: автономная и размещенная. В обоих случаях запуск программы происходит, когда назначенная функция C вызывается средой выполнения. Все объекты со статической продолжительностью хранения должны быть инициализированы (установлены их начальные значения) перед запуском программы. Способ и время такой инициализации в остальном не определены. Завершение программы возвращает управление среде выполнения.
5.1.2.1 Отдельно стоящая среда
В автономной среде (в которой выполнение программы на С может происходить без какой-либо выгоды от операционной системы), имя и тип функции, вызываемой при запуске программы, определяются реализацией. Любые библиотечные средства, доступные для автономной программы, кроме минимального набора, требуемого в разделе 4, определяются реализацией.
Эффект завершения программы в автономной среде определяется реализацией.
Перекрестная ссылка на пункт 4 Соответствие относится к этому:
A5 В строго соответствующей программе должны использоваться только те функции языка и библиотеки, которые указаны в настоящем международном стандарте. 3) Он не должен производить выходные данные, зависящие от какого-либо неопределенного, неопределенного или определенного реализацией поведения, и не должен превышать какого-либо минимального предела реализации.
¶6 Две формы соответствующей реализации являются размещенными и автономными. Соответствующая размещенная реализация должна принимать любую строго соответствующую программу. Соответствующая автономная реализация должна принимать любую строго соответствующую программу, в которой использование функций, указанных в разделе библиотеки (пункт 7), ограничено содержимым стандартных заголовков.
<float.h>
,<iso646.h>
,<limits.h>
,<stdalign.h>
,<stdarg.h>
,<stdbool.h>
,<stddef.h>
,<stdint.h>
, а также<stdnoreturn.h>
, Соответствующая реализация может иметь расширения (включая дополнительные библиотечные функции), при условии, что они не изменяют поведение любой строго соответствующей программы. 4)¶7 Соответствующая программа - это программа, приемлемая для соответствующей реализации. 5)
3) Строго соответствующая программа может использовать условные функции (см. 6.10.8.3) при условии, что использование защищено соответствующей директивой предварительной обработки условного включения с использованием соответствующего макроса. Например:
#ifdef __STDC_IEC_559__ /* FE_UPWARD defined */ /* ... */ fesetround(FE_UPWARD); /* ... */ #endif
4) Это подразумевает, что соответствующая реализация не оставляет никаких идентификаторов, кроме тех, которые явно зарезервированы в настоящем международном стандарте.
5) Строго соответствующие программы предназначены для максимальной переносимости среди соответствующих реализаций. Соответствующие программы могут зависеть от непереносимых функций соответствующей реализации.
Заметно, что единственный требуемый заголовок автономной среды, которая фактически определяет какие-либо функции, это <stdarg.h>
(и даже они могут быть - и часто это - просто макросы).
Стандарт C++ - автономная среда
Так же, как стандарт C признает как размещенную, так и автономную среду, то же самое относится и к стандарту C++. (Цитаты из ИСО / МЭК 14882: 2011.)
1.4 Соответствие реализации [intro.compliance]
Two7 Определены два вида реализаций: размещенная реализация и автономная реализация. Для размещенной реализации этот международный стандарт определяет набор доступных библиотек. Автономная реализация - это та, в которой выполнение может осуществляться без использования операционной системы, и имеет определенный набор реализаций библиотек, который включает в себя определенные библиотеки поддержки языка (17.6.1.3).
Implementation8 Соответствующая реализация может иметь расширения (включая дополнительные библиотечные функции), при условии, что они не изменяют поведение любой правильно сформированной программы. Внедрения необходимы для диагностики программ, использующих такие расширения, которые неправильно сформированы в соответствии с настоящим международным стандартом. Сделав это, однако, они могут компилировать и выполнять такие программы.
Each9 Каждая реализация должна включать документацию, которая идентифицирует все условно поддерживаемые конструкции, которые она не поддерживает, и определяет все специфичные для локали характеристики. 3
3) Эта документация также определяет поведение, определяемое реализацией; см. 1.9.
17.6.1.3 Отдельно стоящие реализации [соответствие]
Определены два вида реализаций: размещенный и автономный (1.4). Для размещенной реализации этот международный стандарт описывает набор доступных заголовков.
Автономная реализация имеет определенный набор реализаций заголовков. Этот набор должен включать как минимум заголовки, показанные в таблице 16.
Поставляемая версия шапки
<cstdlib>
должен объявить хотя бы функцииabort
,atexit
,at_quick_exit
,exit
, а такжеquick_exit
(18,5). Другие заголовки, перечисленные в этой таблице, должны соответствовать тем же требованиям, что и для размещенной реализации.Таблица 16 - Заголовки C++ для автономных реализаций
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>
Как насчет использования int main()
в С?
Стандарт §5.1.2.2.1 стандарта C11 показывает предпочтительные обозначения - int main(void)
- но в стандарте есть также два примера, которые показывают int main()
: §6.5.3.4 and8 и §6.7.6.3 ¶20. Теперь важно отметить, что примеры не являются "нормативными"; они только иллюстративны. Если в примерах есть ошибки, они напрямую не влияют на основной текст стандарта. Тем не менее, они строго указывают на ожидаемое поведение, поэтому, если стандарт включает int main()
в примере это предполагает, что int main()
не запрещено, даже если это не предпочтительное обозначение.
6.5.3.4
sizeof
а также_Alignof
операторы...
Пример 8 В этом примере размер массива переменной длины вычисляется и возвращается из функции:
#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; }
Я полагаю, что main()
должен вернуться либо EXIT_SUCCESS
или же EXIT_FAILURE
, Они определены в stdlib.h
Обратите внимание, что стандарты C и C++ определяют два вида реализаций: автономные и размещенные.
Размещенная среда C90
Разрешенные формы 1:
int main (void) int main (int argc, char *argv[]) main (void) main (int argc, char *argv[]) /*... etc, similar forms with implicit int */
Комментарии:
Первые два явно указаны как разрешенные формы, остальные неявно разрешены, потому что C90 допускает "неявное int" для возвращаемого типа и параметров функции. Никакая другая форма не допускается.
C90 автономная среда
Разрешается любая форма или имя главного лица 2.
C99 размещенная среда
Разрешенные формы 3:
int main (void) int main (int argc, char *argv[]) /* or in some other implementation-defined manner. */
Комментарии:
C99 убрал "неявный int" так
main()
больше не действителенБыло введено странное, неоднозначное предложение "или каким-то другим образом, определяемым реализацией". Это можно интерпретировать как "параметры для
int main()
может отличаться "или" main может иметь любую форму, определяемую реализацией ".Некоторые компиляторы решили интерпретировать стандарт последним способом. Можно утверждать, что нельзя легко утверждать, что они не являются строго соответствующими, цитируя стандарт сам по себе, поскольку он неоднозначен.
Тем не менее, чтобы позволить полностью дикие формы
main()
Возможно, (?) не было намерением этого нового предложения. Обоснование C99 (не нормативное) подразумевает, что предложение относится к дополнительным параметрам дляint main
4Тем не менее, раздел для завершения программы размещенной среды продолжает спорить о случае, когда main не возвращает int 5. Хотя этот раздел не является нормативным для того, как main должен быть объявлен, он определенно подразумевает, что main может быть объявлен полностью определяемым реализацией способом даже в размещенных системах.
C99 автономная среда
Разрешается любая форма или имя главного 6.
Размещенная среда C11
Разрешенные формы 7:
int main (void) int main (int argc, char *argv[]) /* or in some other implementation-defined manner. */
C11 автономная среда
Разрешается любая форма или имя главного лица 8.
Обратите внимание, что int main()
никогда не был указан в качестве допустимой формы для любой размещенной реализации C в любой из вышеуказанных версий. В C, в отличие от C++, ()
а также (void)
имеют разные значения. Первый является устаревшей функцией, которая может быть удалена из языка. Смотрите C11 будущие языковые направления:
6.11.6 Объявление функций
Использование деклараторов функций с пустыми скобками (не деклараторы типа параметров в формате prototype) является устаревшей функцией.
C++03 размещенная среда
Разрешенные формы 9:
int main () int main (int argc, char *argv[])
Комментарии:
Обратите внимание на пустые скобки в первой форме. C++ и C отличаются в этом случае, потому что в C++ это означает, что функция не принимает параметров. Но в C это означает, что он может принимать любой параметр.
C++03 автономная среда
Имя функции, вызываемой при запуске, определяется реализацией. Если это называется
main()
оно должно соответствовать заявленным формам 10:// implementation-defined name, or int main () int main (int argc, char *argv[])
C++ 11 размещенная среда
Разрешенные формы 11:
int main () int main (int argc, char *argv[])
Комментарии:
Текст стандарта был изменен, но он имеет то же значение.
C++ 11 автономная среда
Имя функции, вызываемой при запуске, определяется реализацией. Если это называется
main()
оно должно соответствовать заявленным формам 12:// implementation-defined name, or int main () int main (int argc, char *argv[])
Рекомендации
ANSI X3.159-1989 2.1.2.2 Размещенная среда. "Запуск программы"
Функция, вызываемая при запуске программы, называется основной. Реализация не объявляет прототип для этой функции. Он должен быть определен с типом возврата int и без параметров:
int main(void) { /* ... */ }
или с двумя параметрами (именуемыми здесь как argc и argv, хотя могут использоваться любые имена, так как они являются локальными для функции, в которой они объявлены):
int main(int argc, char *argv[]) { /* ... */ }
ANSI X3.159-1989 2.1.2.1 Отдельно стоящая среда:
В автономной среде (в которой выполнение программы на С может происходить без какой-либо выгоды от операционной системы), имя и тип функции, вызываемой при запуске программы, определяются реализацией.
ISO 9899: 1999 5.1.2.2 Размещенная среда -> 5.1.2.2.1 Запуск программы
Функция, вызываемая при запуске программы, называется основной. Реализация не объявляет прототип для этой функции. Он должен быть определен с типом возврата int и без параметров:
int main(void) { /* ... */ }
или с двумя параметрами (именуемыми здесь как argc и argv, хотя могут использоваться любые имена, так как они являются локальными для функции, в которой они объявлены):
int main(int argc, char *argv[]) { /* ... */ }
или эквивалентный;9) или каким-либо другим способом, определяемым реализацией.
Обоснование международного стандарта - языки программирования - C, редакция 5.10. 5.1.2.2 Размещенная среда -> 5.1.2.2.1 Запуск программы
Поведение аргументов main и взаимодействия exit, main и atexit (см. §7.20.4.2) было кодифицировано, чтобы обуздать некоторое нежелательное разнообразие в представлении строк argv и в значении значений, возвращаемых main.
Спецификация argc и argv в качестве аргументов для main признает обширную предшествующую практику. argv [argc] должен быть нулевым указателем, чтобы обеспечить избыточную проверку конца списка, также на основе обычной практики.
main - единственная функция, которая может быть объявлена переносимым образом либо с нулем, либо с двумя аргументами. (Число аргументов других функций должно точно совпадать между вызовом и определением.) Этот особый случай просто признает широко распространенную практику исключения аргументов из main, когда программа не имеет доступа к строкам аргументов программы. Хотя многие реализации поддерживают более двух аргументов для main, такая практика не благословляется и не запрещается Стандартом; программа, которая определяет main с тремя аргументами, не является строго соответствующей (см. §J.5.1.).
ISO 9899: 1999 5.1.2.2 Размещенная среда -> 5.1.2.2.3 Завершение программы
Если возвращаемый тип основной функции является типом, совместимым с int, возврат из начального вызова основной функции эквивалентен вызову функции выхода со значением, возвращаемым главной функцией в качестве аргумента; 11) достижение
}
которая завершает основную функцию, возвращает значение 0. Если возвращаемый тип не совместим с int, состояние завершения, возвращаемое в хост-среду, не указывается.ISO 9899: 1999 5.1.2.1 Отдельно стоящая среда
В автономной среде (в которой выполнение программы на С может происходить без какой-либо выгоды от операционной системы), имя и тип функции, вызываемой при запуске программы, определяются реализацией.
ISO 9899: 2011 5.1.2.2 Размещенная среда -> 5.1.2.2.1 Запуск программы
Этот раздел идентичен C99, приведенному выше.
ISO 9899: 1999 5.1.2.1 Отдельно стоящая среда
Этот раздел идентичен C99, приведенному выше.
ISO 14882:2003 3.6.1 Основная функция
Реализация не должна предопределять основную функцию. Эта функция не должна быть перегружена. Он должен иметь возвращаемый тип типа int, но в остальном его тип определяется реализацией. Все реализации должны позволять оба следующих определения main:
int main() { /* ... */ }
а также
int main(int argc, char* argv[]) { /* ... */ }
ISO 14882:2003 3.6.1 Основная функция
Определяется реализацией, требуется ли программе в автономной среде для определения главной функции.
ISO 14882: 2011 3.6.1 Основная функция
Реализация не должна предопределять основную функцию. Эта функция не должна быть перегружена. Он должен иметь возвращаемый тип типа int, но в остальном его тип определяется реализацией. Все реализации должны позволять
- функция (), возвращающая int и
- функция (int, указатель на указатель на символ), возвращающая int
как тип основного (8.3.5).
ISO 14882: 2011 3.6.1 Основная функция
Этот раздел идентичен C++03, приведенному выше.
Вернуть 0 в случае успеха и ненулевое значение в случае ошибки. Это стандарт, используемый сценариями UNIX и DOS для выяснения того, что случилось с вашей программой.
main()
в C89 и K&R для неопределенных типов возврата по умолчанию используется значение int.
return 1? return 0?
Если вы не напишите заявление о возврате в
int main()
Закрытие{
вернет 0 по умолчанию.return 0
или жеreturn 1
будет получен родительским процессом. В оболочке она переходит в переменную оболочки, и если вы запускаете свою программу из оболочки и не используете эту переменную, вам не нужно беспокоиться о возвращаемом значенииmain()
,
См. Как я могу получить то, что вернула моя основная функция?,
$ ./a.out
$ echo $?
Таким образом, вы можете видеть, что это переменная $?
который получает наименее значимый байт возвращаемого значения main()
,
В сценариях Unix и DOS, return 0
в случае успеха и ненулевые ошибки обычно возвращаются. Это стандарт, используемый сценариями Unix и DOS для выяснения того, что случилось с вашей программой, и контроля всего потока.
Помните, что, даже если вы возвращаете int, некоторые ОС (Windows) усекают возвращаемое значение до одного байта (0-255).
Возвращаемое значение может использоваться операционной системой для проверки того, как программа была закрыта.
Возвращаемое значение 0 обычно означает ОК в большинстве операционных систем (те, о которых я могу думать в любом случае).
Это также может быть проверено, когда вы сами вызываете процесс, и смотрите, правильно ли завершена программа.
Это НЕ просто соглашение о программировании.
Возвращаемое значение main()
показывает, как программа вышла. Если возвращаемое значение zero
это означает, что выполнение было успешным, в то время как любое ненулевое значение будет означать, что что-то пошло не так в выполнении.
не указывать return 0
Когда программа на C или C++ достигает конца main
компилятор автоматически сгенерирует код для возврата 0, поэтому нет необходимости ставить return 0;
явно в конце main
,
Примечание: когда я делаю это предложение, за ним почти всегда следует один из двух видов комментариев: "Я этого не знал". или "Это плохой совет!" Мое обоснование заключается в том, что безопасно и полезно полагаться на поведение компилятора, явно поддерживаемое стандартом. Для C, так как C99; см. ИСО / МЭК 9899:1999, раздел 5.1.2.2.3:
[...] возврат от начального вызова к
main
Функция эквивалентна вызовуexit
функция со значением, возвращаемымmain
функция в качестве аргумента; достигнув}
что завершаетmain
Функция возвращает значение 0.
Для C++, начиная с первого стандарта в 1998 году; см. ISO/IEC 14882:1998 раздел 3.6.1:
Если элемент управления достигает конца main, не встречая оператора return, результатом является выполнение return 0;
С тех пор все версии обоих стандартов (C99 и C++98) придерживались той же идеи. Мы полагаемся на автоматически сгенерированные функции-члены в C++, и мало кто пишет явно return;
заявления в конце void
функция. Причины против пропуска, кажется, сводятся к "выглядит странно". Если, как и я, вам интересно узнать причину изменения стандарта C, прочитайте этот вопрос. Также обратите внимание, что в начале 1990-х это считалось "небрежной практикой", потому что в то время это было неопределенное поведение (хотя и широко поддерживаемое).
Так что я призываю опустить это; другие не согласны (часто яростно!). В любом случае, если вы столкнетесь с кодом, который его пропускает, вы будете знать, что он явно поддерживается стандартом, и вы будете знать, что это значит.
Как правильно (наиболее эффективно) определить функцию main() в C и C++ - int main() или void main() - и почему?
Эти слова "(наиболее эффективные)" не меняют вопрос. Если вы не находитесь в автономной среде, есть один универсально правильный способ объявить main()
и это как возвращение int.
Что должно
main()
вернуть в C и C++?
Это не то, что должно main()
возвращение, это то, что делает main()
вернуть. main()
это, конечно, функция, которую кто-то еще вызывает. Вы не имеете никакого контроля над кодом, который вызывает main()
, Поэтому вы должны объявить main()
с типо-правильной подписью, чтобы соответствовать его вызывающему. У вас просто нет выбора в этом вопросе. Вам не нужно спрашивать себя, что является более или менее эффективным, что лучше или хуже, или что-то в этом роде, потому что ответ для вас уже совершенно четко определен стандартами C и C +. Просто следуй за ними.
Если int main(), тогда вернуть 1 или вернуть 0?
0 для успеха, ненулевой для неудачи. Опять же, не то, что вам нужно (или нужно) выбирать: это определяется интерфейсом, которому вы должны соответствовать.
У меня сложилось впечатление, что стандарт указывает, что main не нуждается в возвращаемом значении, поскольку успешное возвращение основано на ОС (ноль в одном может быть либо успехом, либо неудачей в другом), поэтому отсутствие возврата было сигналом для Компилятор для вставки самого успешного возврата.
Однако я обычно возвращаю 0.
Возвращение 0 должно сказать программисту, что программа успешно завершила работу.
Что вернуть, зависит от того, что вы хотите сделать с исполняемым файлом. Например, если вы используете вашу программу с оболочкой командной строки, вам нужно вернуть 0 для успеха и ненулевое значение для ошибки. Тогда вы сможете использовать программу в оболочках с условной обработкой в зависимости от результата вашего кода. Также вы можете назначить любое ненулевое значение в соответствии с вашей интерпретацией, например, для критических ошибок разные точки выхода из программы могут завершить программу с разными значениями выхода, и которая доступна вызывающей оболочке, которая может решить, что делать, проверив возвращаемое значение. Если код не предназначен для использования с оболочками и возвращаемое значение никого не беспокоит, его можно опустить. Я лично использую подпись int main (void) { .. return 0; .. }
Вот небольшая демонстрация использования кодов возврата...
При использовании различных инструментов, предоставляемых терминалом Linux, можно использовать код возврата, например, для обработки ошибок после завершения процесса. Представьте, что присутствует следующий текстовый файл myfile:
Это пример того, как проверить, как работает grep.
Когда вы выполняете команду grep, процесс создается. По завершении (и без прерывания) возвращается код от 0 до 255. Например:
$ grep order myfile
Если вы делаете
$ echo $?
$ 0
вы получите 0. Почему? Потому что grep нашел совпадение и возвратил код выхода 0, который является обычным значением для успешного завершения. Давайте проверим это снова, но с чем-то, чего нет в нашем текстовом файле, и, следовательно, совпадение не будет найдено:
$ grep foo myfile
$ echo $?
$ 1
Поскольку grep не удалось сопоставить токен "foo" с содержимым нашего файла, код возврата равен 1 (это обычный случай, когда происходит сбой, но, как указано выше, у вас есть множество значений на выбор).
Теперь следующий скрипт bash (просто введите его в терминале Linux), хотя и очень простой, должен дать некоторое представление об обработке ошибок:
$ grep foo myfile
$ CHECK=$?
$ [ $CHECK -eq 0] && echo 'Match found'
$ [ $CHECK -ne 0] && echo 'No match was found'
$ No match was found
После второй строки ничего не выводится на терминал, так как "foo" заставляет grep возвращать 1, и мы проверяем, был ли код возврата grep равен 0. Второе условное выражение повторяет свое сообщение в последней строке, поскольку оно истинно из-за CHECK == 1.
Как вы можете видеть, вызываете ли вы этот и тот процесс, иногда важно увидеть, что он вернул (по возвращаемому значению main()).
Если у вас действительно есть проблемы, связанные с эффективностью возврата целого числа из процесса, вам, вероятно, следует избегать вызова этого процесса столько раз, что это возвращаемое значение становится проблемой.
Если вы делаете это (вызываете процесс много раз), вы должны найти способ поместить свою логику непосредственно в вызывающую программу или в файл DLL, без выделения определенного процесса для каждого вызова; Многократное распределение процессов приносит вам соответствующую проблему эффективности в этом случае.
Подробно, если вы хотите знать только, является ли возврат 0 более или менее эффективным, чем возврат 1, в некоторых случаях это может зависеть от компилятора, но в целом, если предположить, что они читаются из одного и того же источника (локальный, полевой, константный, встроенный). в коде, результате функции и т. д.) требуется ровно столько же тактов.
«int» теперь предписывается ISO как для C, так и для C++ в качестве возвращаемого типа для «main».
Оба языка ранее допускали неявное объявление «int» и «main» без какого-либо возвращаемого типа. На самом деле, самая первая внешняя версия C++ (выпуск E "cfront" от февраля 1985 г.), которая написана на своем собственном языке, объявляла "main" без какого-либо возвращаемого типа... но возвращала целочисленное значение: количество ошибок или 127, в зависимости от того, что меньше
Что касается вопроса, что возвращать: стандарты ISO для C и C++ работают синхронно со стандартом POSIX. Для любой размещенной среды, соответствующей стандарту POSIX,
(1) 126 зарезервировано для оболочки ОС, чтобы указать утилиты, которые не являются исполняемыми,
(2) 127 зарезервировано для оболочки ОС, чтобы указать, что команда не найдена,
(3) значения выхода для утилит указаны отдельно для каждой утилиты,
(4) программы, которые вызывают утилиты вне оболочки, должны использовать аналогичные значения для своих собственных выходов,
(5) значения 128 и выше предназначены для использования чтобы указать завершение в результате приема сигнала,
(6) значения 1-125 соответствуют сбоям,
(7) значение 0 соответствует успеху.
В C и C++ значения EXIT_SUCCESS и EXIT_FAILURE предназначены для использования в наиболее распространенных ситуациях: для программ, которые сообщают об успехе или просто общем сбое. Они могут, но не обязательно, быть соответственно равными 0 и 1.
Это означает, что если вы хотите, чтобы программа возвращала разные значения для разных режимов сбоя или индикации состояния, продолжая использовать эти две константы, вам, возможно, придется сначала прибегнуть к проверке того, что ваши дополнительные значения «сбой» или «статус» лежат строго между max(EXIT_SUCCESS, EXIT_FAILURE) и 126 (и надеемся, что между ними достаточно места) и зарезервировать EXIT_FAILURE для обозначения общего режима отказа или режима отказа по умолчанию.
В противном случае, если вы не собираетесь использовать константы, вам следует придерживаться того, что требует POSIX.
Для программ, предназначенных для использования в автономных средах или на хостах, не совместимых с POSIX, я больше ничего не могу сказать, кроме следующего:
Я писал автономные программы - как многопоточные программы в пользовательской системе времени выполнения (и пользовательскую базу инструментов для всего остального). Общее правило, которому я следовал, заключалось в следующем:
(1) «main» запускал процессы переднего плана, которые обычно состояли только из процедур запуска, настройки или инициализации, но могли бы также включать процессы переднего плана, предназначенные для непрерывной работы (например, циклы опроса). ),
(2) «main» возвращается в бесконечный цикл ожидания и ожидания,
(3) возвращаемое значение для «main» не было определено или использовано,
(4) фоновые процессы выполнялись отдельно, как потоки, управляемые прерываниями, и потоки, управляемые событиями, независимо от "основного", завершается только получением сигнала сброса или другими потоками...
В C++ основная функция должна быть объявлена как int main(), а не как void main(), так как компилятор выдает ошибку в случае void main. Функция main может принимать любое количество аргументов, таких как int main(int k,int l,int arr[]) или int main(void).
#include <iostream>
using namespace std;
int main(void) {
// your code goes here
cout<<"a";
return 0;
}
Выход:
Success #stdin #stdout 0s 4416KB
a
Возвращаясь к возвращаемой части, он должен возвращать только 0, иначе компилятор выдаст ошибку. например, если вы вернете 1, вы получите желаемый результат, но он также выдаст ошибку времени выполнения.
пример
#include <iostream>
using namespace std;
int main(int k,float m,char g, int arr[]) {
// your code goes here
k=0;
cout<<k;
g='a';
cout<<g;
cout<<"a";
return 1;
}
Выход:
Runtime error #stdin #stdout 0s 4448KB
0aa
В C раздел 5.1.2.2.1 стандарта C11 (выделено мной):
Он должен быть определен с типом возврата
int
и без параметров:int main(void) { /* ... */ }
или с двумя параметрами (называемыми здесь
argc
иargv
, хотя могут использоваться любые имена, поскольку они являются локальными для функции, в которой они объявлены):int main(int argc, char *argv[]) { /* ... */ }
Однако для некоторых новичков, таких как я, абстрактный пример позволил бы мне понять это:
Когда вы пишете метод в своей программе, например
int read_file(char filename[LEN]);
, то вы хотите, как вызывающий этот метод, знать, все ли прошло хорошо (поскольку могут произойти сбои, например, файл не может быть найден). Проверяя возвращаемое значение метода, вы можете узнать, все ли прошло хорошо или нет, это механизм для метода, который сигнализирует вам об успешном выполнении (или нет), и позволяет вызывающему (например, в вашем основном методе) решать как справиться с неожиданной ошибкой.
Итак, теперь представьте, что я пишу программу на языке C для микромеханизма, который используется в более сложной системе. Когда система вызывает микромеханизм, она хочет знать, все ли прошло, как ожидалось, чтобы она могла обработать любую потенциальную ошибку. Если основной метод программы C вернет void, то как вызывающая система узнает о выполнении своей подсистемы (микромеханизма)? Не может, поэтому main() возвращает int, чтобы сообщить вызывающей стороне успешное (или нет) выполнение.
Другими словами:
Рациональным является то, что среда хоста (то есть операционная система (ОС)) должна знать, правильно ли завершилась программа. Без int-совместимого типа в качестве возвращаемого типа (например, void) "статус, возвращаемый в среду хоста, не указан" (т.е. неопределенное поведение в большинстве ОС).
В Windows, если программа вылетает из-за нарушения прав доступа, код выхода будет
STATUS_ACCESS_VIOLATION (0xC0000005)
. Аналогично другим видам сбоев из-за исключения x86.
Так что есть еще кое-что, кроме того, из чего вы вернетесь.
main
или перейти к
exit
это может вызвать появление кода выхода.
Это в основном зависит от вашей среды выполнения (ОС). C подразумевает, что он будет запущен UNIX-подобной ОС, которая ожидает, что программа возвратит целое (маленький? 1 байт? Не помню) целое число, указывающее на успех / неудачу.
Вы должны, вероятно, просто использовать int main(int argc, char** argv)
,