Как правильно объявить main в C ++?

Вопросы

  • Какова правильная сигнатура функции main в C ++?

  • Каков правильный тип возвращаемого значения и что означает возвращение значения из main?

  • Какие типы параметров разрешены и каковы их значения?

  • Это зависит от системы?

  • Изменились ли эти правила со временем?

  • Что будет, если я их нарушу?


person fredoverflow    schedule 17.11.2010    source источник
comment
Это очень близко связано или является дубликатом Что должно main возвращаться в C и C ++.   -  person Jonathan Leffler    schedule 18.05.2014
comment
@JonathanLeffler Без шуток ... он был добавлен в список дубликатов в редакции 6 около 8 месяцев назад.   -  person fredoverflow    schedule 18.05.2014


Ответы (5)


Функция main должна быть объявлена ​​как функция, не являющаяся членом в глобальном пространстве имен. Это означает, что он не может быть статической или нестатической функцией-членом класса и не может быть помещен в пространство имен (даже безымянное пространство имен).

Имя main не зарезервировано в C ++, за исключением функции в глобальном пространстве имен. Вы можете объявлять другие сущности с именем main, включая, помимо прочего, классы, переменные, перечисления, функции-члены и функции, не являющиеся членами, не в глобальном пространстве имен.

Вы можете объявить функцию с именем main как функцию-член или в пространстве имен, но такая функция не будет функцией main, определяющей место запуска программы.

Функция main не может быть объявлена ​​как static или inline. Его тоже нельзя перегружать; в глобальном пространстве имен может быть только одна функция с именем main.

Функцию main нельзя использовать в вашей программе: вам не разрешено вызывать функцию main из любого места вашего кода, а также вам не разрешено брать ее адрес.

Тип возврата main должен быть int. Никакой другой тип возврата не разрешен (это правило выделено жирным шрифтом, потому что очень часто можно увидеть некорректные программы, которые объявляют main с типом возврата void; это, вероятно, наиболее часто нарушаемое правило, касающееся функции main).

Должны быть разрешены два объявления main:

int main()               // (1)
int main(int, char*[])   // (2)

В (1) параметров нет.

В (2) есть два параметра, которые условно называются argc и argv соответственно. argv - указатель на массив строк C, представляющих аргументы программы. argc - количество аргументов в массиве argv.

Обычно argv[0] содержит название программы, но это не всегда так. argv[argc] гарантированно будет нулевым указателем.

Обратите внимание: поскольку аргумент типа массива (например, char*[]) на самом деле является просто замаскированным аргументом типа указателя, следующие два являются допустимыми способами записи (2), и оба они означают одно и то же:

int main(int argc, char* argv[])
int main(int argc, char** argv)

Некоторые реализации могут допускать другие типы и количество параметров; вам нужно будет проверить документацию своей реализации, чтобы узнать, что она поддерживает.

Ожидается, что main() вернет ноль для обозначения успеха и ненулевое значение для обозначения неудачи. От вас не требуется явно писать return оператор в main(): если вы позволите main() вернуться без явного return оператора, это будет так же, как если бы вы написали return 0;. Следующие две main() функции имеют одинаковое поведение:

int main() { }
int main() { return 0; }

Есть два макроса, EXIT_SUCCESS и EXIT_FAILURE, определенные в <cstdlib>, которые также могут быть возвращены из main() для обозначения успеха и неудачи соответственно.

Значение, возвращаемое main(), передается функции exit(), которая завершает программу.

Обратите внимание, что все это применимо только при компиляции для размещенной среды (неформально, среды, в которой у вас есть полная стандартная библиотека и есть ОС, запускающая вашу программу). Также можно скомпилировать программу на C ++ для автономной среды (например, для некоторых типов встроенных систем), и в этом случае запуск и завершение полностью определяются реализацией, а функция main() может даже не потребоваться. Однако если вы пишете C ++ для современной настольной ОС, вы компилируете для размещенной среды.

person James McNellis    schedule 17.11.2010
comment
IIRC единственными гарантированными возвращаемыми значениями являются 0, EXIT_SUCCESS (тот же эффект, что и 0) и EXIT_FAILURE. РЕДАКТИРОВАТЬ: Ах, хорошо, могут быть возвращены другие ненулевые значения статуса, но со значением, определяемым реализацией. Гарантированно, что только EXIT_FAILURE каким-либо образом интерпретируется как значение ошибки. - person Derrick Turk; 17.11.2010
comment
Не мешало бы указать (на всякий случай), что это относится к C ++. Пользователи Java / C # могут быть сбиты с толку, поскольку эти языки на самом деле требуют точки входа, чтобы - что противоречит интуиции - находиться в классе (по какой-то причине). Кроме того, не является ли старый формат void main пережитком C? - person Synetech; 21.12.2010
comment
@Synetech: в первом предложении задается вопрос: какова правильная сигнатура основной функции в C ++? и вопрос отмечен как [c ++], так и [c ++ - faq]. Я ничего не могу поделать, если пользователи Java или C # (или кто-то еще) все еще сбиты с толку. C # требует, чтобы Main был статической функцией-членом, потому что он даже не имеет функций, не являющихся членами. Даже C89 требует main для возврата int. Я недостаточно знаком с K&R C, чтобы знать его точные правила, но я предполагаю, что он также требует main для возврата int, поскольку main без типа возврата был довольно распространенным, а type = implicit int в K&R. - person James McNellis; 21.12.2010
comment
@ Джеймс МакНеллис, не могли бы вы объяснить why the return type of main should be int? - person Suhail Gupta; 15.06.2011
comment
@Suhail: Потому что в стандарте языка указано, что возвращаемый тип должен быть int. - person James McNellis; 15.06.2011
comment
@ Джеймс МакНеллис. Есть ли вред, если я использую void? - person Suhail Gupta; 15.06.2011
comment
@Suhail: Да. Ваш код не будет соответствовать C ++, и многие компиляторы отклонят ваш код. - person James McNellis; 15.06.2011
comment
@ Джеймс МакНеллис Ой! Спасибо! Не могли бы вы назвать некоторые компиляторы, которые отклонят возвращаемый тип void. До сих пор я использовал только Visual studio c++ (а также древний turbo-c ++), который передает мой код. - person Suhail Gupta; 15.06.2011
comment
@ James McNellis. Почему компилятор Microsoft передает код с void типом возврата main. (экспресс-выпуск Microsoft Visual C ++ 2010) - person Suhail Gupta; 15.06.2011
comment
@Suhail: Visual C ++ допускает void возвращаемый тип в качестве языкового расширения . Компиляторы, которые не разрешают это, включают GCC и Comeau. - person James McNellis; 16.06.2011
comment
Была ли версия int main () {} всегда частью стандарта или это что-то, что было добавлено недавно? - person Chris Huang-Leaver; 21.09.2016
comment
Он был добавлен в C более пятидесяти лет назад, задолго до того, как появился стандарт C ++. - person arnt; 08.11.2017
comment
На менее распространенных платформах (например, VAX / VMS) с компиляторами, которые следовали очень старым версиям тогда еще более неоднозначного стандарта C, EXIT_SUCCESS и EXIT_FAILURE были надежными только в качестве аргументов для exit(). Возврат любого из них из main() может иметь непредвиденные последствия. Теперь, когда стандарт был уточнен, нет стандартного переносимого способа вернуть полностью произвольное значение в среду хоста; вам нужно будет использовать расширение для конкретного хоста. - person Adrian McCarthy; 15.03.2019

Из стандартной документации, 3.6.1.2 Основная функция,

Он должен иметь тип возвращаемого значения типа int, но в остальном его тип определяется реализацией. Все реализации должны допускать оба следующих определения main:

int main() { / ... / } и int main(int argc, char* argv[]) { / ... / }

В последней форме argc должно быть количество аргументов, переданных программе из среды, в которой программа запускается. Если argc отличен от нуля, эти аргументы должны быть переданы в argv [0] через argv [argc-1] как указатели на начальные символы многобайтовых строк с завершающим нулем .....

Надеюсь, это поможет..

person liaK    schedule 18.11.2010
comment
есть ли какая-то конкретная причина, почему тип возврата main должен быть int? - person Suhail Gupta; 15.06.2011
comment
@SuhailGupta: Чтобы вызывающий процесс знал, следует ли считать этот процесс успешным или нет. Разрешение void ломает эту модель. Это даже не имеет смысла, если у вас это означает всегда считать успехом. Поскольку у вас не было возможности сказать, действительно ли процесс потерпел неудачу, так что вы действительно добились успеха? Нет, вернуть int. - person Lightness Races in Orbit; 02.01.2017

Точная формулировка последнего опубликованного стандарта (C ++ 14):

Реализация должна позволять как

  • функция () возврата int и

  • функция (int, указатель на указатель на char), возвращающий int

как тип main.

Это проясняет, что альтернативные варианты написания разрешены, пока тип main является типом int() или int(int, char**). Таким образом, также разрешено следующее:

  • int main(void)
  • auto main() -> int
  • int main ( )
  • signed int main()
  • typedef char **a; typedef int b, e; e main(b d, a c)
person M.M    schedule 01.07.2017
comment
NB. Я опубликовал этот ответ, как в комментариях к другому потоку, кто-то пытался процитировать эту ветку как доказательство того, что int main(void) был неправильным в C ++. - person M.M; 01.07.2017
comment
@Stargateur auto main() -> int не имеет выведенного типа возврата. Обратите внимание на {in (auto main () {... запрещено) и научитесь распознавать, когда вы еще не знаете достаточно, чтобы добавить что-нибудь значимое. - person ; 01.07.2017

Двумя допустимыми сетями являются int main() и int main(int, char*[]). Все остальное может компилироваться, а может и не компилироваться. Если main не возвращает значение явно, неявно возвращается 0.

person stonemetal    schedule 17.11.2010
comment
Я никогда не видел, чтобы код не компилировался, когда я упоминал, что возвращаемый тип main недействителен. Есть ли какая-то конкретная причина, по которой возвращаемый тип main должен быть int? - person Suhail Gupta; 15.06.2011
comment
Спецификация языка говорит, что main должен иметь тип возвращаемого значения int. Любой другой тип возвращаемого значения, разрешенный вашим компилятором, является улучшением, специфичным для компилятора. В основном использование void означает, что вы программируете на языке, похожем, но не на C ++. - person stonemetal; 16.06.2011
comment
Причина, по которой стандарт требует int в качестве типа возвращаемого значения main, заключается в том, что это значение передается оболочке в качестве кода выхода программы, а sh ожидает int. - person uckelman; 12.07.2013
comment
Может, причина в дисциплине? Может быть несколько выходов. Если тип возврата void, все они молчат. С int мы должны определить конкретное значение выхода для каждого возврата из main. - person Andreas Spindler; 30.10.2018

Подробная информация о возвращаемых значениях и их значении

Согласно 3.6.1 ([basic.start.main]):

Оператор return в main имеет эффект выхода из функции main (уничтожение любых объектов с автоматической продолжительностью хранения) и вызов std::exit с возвращаемым значением в качестве аргумента. Если элемент управления достигает конца main, не встречая оператора return, результатом будет выполнение

return 0;

Поведение std::exit подробно описано в разделе 18.5 ([support.start.term]) и описывает код состояния:

Наконец, управление возвращается в среду хоста. Если статус равен нулю или EXIT_SUCCESS, возвращается форма успешного завершения статуса, определяемая реализацией. Если статус равен EXIT_FAILURE, возвращается форма, определяемая реализацией неудачного завершения статуса. В противном случае возвращаемый статус определяется реализацией.

person Ben Voigt    schedule 02.01.2012