Что такое правильное объявление основного? - PullRequest
140 голосов
/ 17 ноября 2010

Какая правильная сигнатура функции main в C ++? Каков правильный тип возвращаемого значения и что означает возвращать значение из main? Каковы разрешенные типы параметров и каковы их значения?

Это зависит от системы? Изменились ли эти правила с течением времени? Что произойдет, если я нарушу их?

Ответы [ 5 ]

181 голосов
/ 17 ноября 2010

Функция 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 ++ для современной настольной ОС, вы компилируете для размещенной среды.

15 голосов
/ 18 ноября 2010

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

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

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

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

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

4 голосов
/ 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)
3 голосов
/ 17 ноября 2010

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

2 голосов
/ 02 января 2012

Сведения о возвращаемых значениях и их значении

По 3.6.1 ([basic.start.main]):

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

return 0;

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

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

...