Стандарт С - размещенная среда
Для размещенной среды (это нормальная среда) стандарт 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 приводит к выходу из функции main (уничтожению любых объектов с автоматическим хранением) и вызову std::exit
с возвращаемым значением в качестве аргумента. Если управление достигает конца main, не встречая оператора return, эффект заключается в выполнении
return 0;
Стандарт C ++ явно говорит: «Он [основная функция] должен иметь тип возвращаемого типа int
, но в противном случае его тип определяется реализацией», и для поддержки в качестве опций требуются те же две подписи, что и для стандарта C. Таким образом, void main () напрямую не разрешен стандартом C ++, хотя он ничего не может сделать, чтобы остановить нестандартную реализацию, допускающую альтернативы. Обратите внимание, что C ++ запрещает пользователю звонить main
(но стандарт C этого не делает).
Там в пункте §18.5 Начало и окончание в C ++ 11 стандарт , который идентичен пункту из §7.22.4.4 функции в стандарте C11 (процитированном выше), за исключением сноски (который просто документы, и определяются в )exit
EXIT_SUCCESS
EXIT_FAILURE
<cstdlib>
Стандарт C - Общее расширение
Классически системы Unix поддерживают третий вариант:
int main(int argc, char **argv, char **envp) { ... }
Третий аргумент представляет собой список указателей на строки с нулевым символом в конце, каждый из которых представляет собой переменную окружения, которая имеет имя, знак равенства и значение (возможно, пустое). Если вы не используете это, вы все равно можете попасть в среду через ' extern char **environ;
'. Эта глобальная переменная уникальна среди тех, что в POSIX, потому что у нее нет заголовка, который ее объявляет.
Это признано стандартом 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 не указана в качестве альтернативы. В версии от Microsoft Visual Studio 2008 года сделать.void main()
Стандарт С - автономная среда
Как уже отмечалось ранее, вышеуказанные требования применяются к размещенным средам. Если вы работаете с автономной средой (которая является альтернативой размещенной среде), то о стандарте можно сказать гораздо меньше. В автономной среде нет необходимости вызывать функцию, вызываемую при запуске программы, 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]
¶7 Определены два вида реализаций: размещенная реализация и автономная реализация . Для размещенной реализации этот международный стандарт определяет набор доступных библиотек. Автономная реализация - это та, в которой выполнение может осуществляться без использования операционной системы, и имеет определенный набор реализаций библиотек, который включает в себя определенные библиотеки поддержки языка (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()
в C?
Стандарт §5.1.2.2.1 стандарта C11 показывает предпочтительные обозначения - int main(void)
- но в стандарте также есть два примера, которые показывают int main()
: §6.5.3.4 ¶8 и §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;
}