Что должно возвращать main() в C и C++?
Как правильно (и наиболее эффективно) определить функцию main()
в C и C++ — использовать int main()
или void main()
— и почему? А что насчет аргументов? Если использовать int main()
, то следует ли возвращать return 1
или return 0
?
5 ответ(ов)
Возвращаемое значение функции main
указывает на то, как завершилась программа. Нормальное завершение представляется нулевым значением, возвращаемым из main
. Аномальное завершение сигнализируется ненулевым значением, однако для интерпретации ненулевых кодов нет стандартов. Как отмечают другие, использование void main()
запрещено стандартом C++ и не должно применяться. Допустимые сигнатуры функции main
в C++ выглядят так:
int main(void)
и
int main(int argc, char **argv)
что эквивалентно
int main(int argc, char *argv[])
Также стоит отметить, что в C++ функция int main()
может не содержать оператор return
, в этом случае по умолчанию возвращается 0. Это также верно для программы, написанной на C99. Должен ли оператор return 0;
быть опущен или нет — вопрос для обсуждения. Диапазон допустимых сигнатур функции main
в C гораздо шире.
Что касается эффективности, то с точки зрения стандарта C++ функции main
разрешается входить и выходить только один раз (что обозначает начало и завершение программы). В C повторный вход в main()
разрешен, но должен быть избегнут.
Принятый ответ, похоже, ориентирован на C++, поэтому я решил добавить ответ, касающийся C, который отличается в нескольких аспектах. Также стоит отметить, что между стандартами ISO/IEC 9899:1989 (C90) и ISO/IEC 9899:1999 (C99) были внесены некоторые изменения.
main()
должен быть объявлен следующим образом:
int main(void)
int main(int argc, char **argv)
Или эквивалентно. Например, int main(int argc, char *argv[])
является эквивалентом второго варианта. В C90 тип возвращаемого значения int
можно было опустить, так как он подразумевается по умолчанию, но в C99 и более поздних версиях тип int
нельзя опускать.
Если реализация это позволяет, main()
можно объявить другими способами (например, int main(int argc, char *argv[], char *envp[])
), но это делает программу зависимой от реализации и больше не соответствует строгим стандартам.
Стандарт определяет три значения для возврата, которые строго соответствуют требованиям (то есть не зависят от поведения реализации): 0
и EXIT_SUCCESS
для успешного завершения, и EXIT_FAILURE
для неуспешного завершения. Любые другие значения являются нестандартными и зависят от реализации. В C90 функция main()
должна иметь явное выражение return
в конце, чтобы избежать неопределенного поведения. В C99 и более поздних версиях вы можете опустить оператор возврата из main()
. Если вы это сделаете, и main()
завершится, будет подразумеваться return 0
.
В заключение, с точки зрения стандартов, нет ничего неправильного в том, чтобы вызывать main()
рекурсивно из программы на C.
Я считаю, что функция main()
должна возвращать либо EXIT_SUCCESS
, либо EXIT_FAILURE
. Эти макросы определены в заголовочном файле stdlib.h
. Использование этих значений позволяет более четко и стандартно указывать успешное или неуспешное завершение программы. Это упрощает обработку завершения программы в других приложениях или скриптах, которые могут использовать ваш код.
В стандартных спецификациях языка C и C++ различают две категории реализаций: свободно стоящая (freestanding) и хостинговая (hosted).
Хостинговая среда C90
Допустимые формы:
int main (void);
int main (int argc, char *argv[]);
main (void);
main (int argc, char *argv[]);
/*... и т.д., аналогичные формы с неявным int */
Комментарии:
Первые две формы явно указаны как допустимые, остальные считаются допустимыми неявно, поскольку в C90 разрешено "неявное int" для типа возврата и параметров функции. Никакие другие формы не допускаются.
Свободно стоящая среда C90
Любая форма или имя main допустимы.
Хостинговая среда C99
Допустимые формы:
int main (void);
int main (int argc, char *argv[]);
/* либо в каком-то другом способе, определяемом реализацией. */
Комментарии:
В C99 убрано "неявное int", поэтому main()
больше не действительно. Появилась странная и неоднозначная фраза "либо в каком-то другом способе, определяемом реализацией", которую можно интерпретировать как "параметры int main()
могут варьироваться" или как "main может иметь любую форму, определяемую реализацией".
Некоторые компиляторы стали интерпретировать стандарт во втором ключе. Тем не менее, трудно утверждать о несоответствии стандарту, так как он действительно аморфный. В то же время, вероятно, позволить совершенно произвольные формы main()
не было намерением добавления этой новой фразы. Обоснование к стандарту C99 подразумевает, что эта фраза относится к дополнительным параметрам для int main
.
Однако в разделе о завершении программы в хостинговой среде утверждается, что функция main может не возвращать int. Хотя этот раздел не является нормативным для объявления функции main, он определенно подразумевает, что main может быть объявлен полностью специфическим для реализации образом, даже в хостинговых системах.
Свободно стоящая среда C99
Любая форма или имя main допустимы.
Хостинговая среда C11
Допустимые формы:
int main (void);
int main (int argc, char *argv[]);
/* либо в каком-то другом способе, определяемом реализацией. */
Свободно стоящая среда C11
Любая форма или имя main допустимы.
Обратите внимание, что int main()
никогда не считалась допустимой формой для каких-либо реализаций C в вышеуказанных версиях. В C, в отличие от C++, ()
и (void)
имеют разные значения. Первое обозначает устаревшую функцию, которая может быть удалена из языка.
Хостинговая среда C++03
Допустимые формы:
int main ();
int main (int argc, char *argv[]);
Комментарии:
Обратите внимание на пустые скобки в первой форме. C++ и C различаются в этом случае, поскольку в C++ это означает, что функция не принимает параметры. Однако в C это значит, что она может принимать любые параметры.
Свободно стоящая среда C++03
Имя функции, вызываемой при запуске, определяется реализацией. Если оно называется main()
, оно должно следовать указанным формам:
// имя, определяемое реализацией, или
int main ();
int main (int argc, char *argv[]);
Хостинговая среда C++11
Допустимые формы:
int main ();
int main (int argc, char *argv[]);
Комментарии:
Текст стандарта был изменен, но смысл остался прежним.
Свободно стоящая среда C++11
Имя функции, вызываемой при запуске, определяется реализацией. Если оно называется main()
, оно должно следовать указанным формам.
Эти различия в допущенных определениях функции main в языках C и C++ важно учитывать при написании программ, чтобы избежать путаницы и несоответствий.
Возвращайте 0 при успешном завершении и ненулевое значение в случае ошибки. Это стандарт, принятый в UNIX и DOS-скриптах, позволяющий определить, что произошло с вашей программой.
В чем разница между #include <filename> и #include "filename"?
Разница между const int*, const int * const и int * const?
Как использовать extern для обмена переменными между исходными файлами?
Является ли < быстрее, чем <=?
Самый быстрый способ проверить существование файла с использованием стандартного C++/C++11, C++14, C++17/C?