Каковы действительные сигнатуры для основной функции в C? Я знаю:
int main(int argc, char *argv[])
Существуют ли другие допустимые?
Каковы действительные сигнатуры для основной функции в C? Я знаю:
int main(int argc, char *argv[])
Существуют ли другие допустимые?
Текущий стандарт на момент этого ответа (C11) явно упоминает эти два:
int main(void);
int main(int argc, char* argv[]);
хотя он упоминает фразу "или эквивалент" со следующей сноской:
Таким образом,
intможет быть заменено именемtypedefопределенным какint, или типargvможет быть записан какchar ** argvи так далее.
Кроме того, он также предоставляет больше (определенных реализацией) возможностей.
В соответствующем разделе (раздел 5.1.2.2.1 раздела C11, но этот конкретный аспект не отличается от раздела C99) говорится:
Функция, вызываемая при запуске программы, называется
main. Реализация не объявляет прототип для этой функции. Он должен быть определен с типом возвратаintи без параметров:int main(void) { /* ... */ }или с двумя параметрами (именуемыми здесь как
argcиargv, хотя могут использоваться любые имена, поскольку они являются локальными для функции, в которой они объявлены):int main(int argc, char *argv[]) { /* ... */ }или эквивалент; или каким-либо другим способом, определяемым реализацией.
Если они объявлены, параметры
mainфункции должны подчиняться следующим ограничениям:
Значение
argcдолжно быть неотрицательным.
argv[argc]должен быть нулевым указателем.
Если значение
argcбольше нуля, члены массива отargv[0]доargv[argc-1]включительно должны содержать указатели на строки, которым перед установкой программы передаются значения, определяемые реализацией средой хоста. Намерение состоит в том, чтобы предоставить программе информацию, определенную до ее запуска, из другого места в размещенной среде. Если среда хоста не способна снабжать строки буквами как в верхнем, так и в нижнем регистре, реализация должна обеспечивать получение строк в нижнем регистре.
Если значение
argcбольше нуля, строка, на которую указываетargv[0]представляет имя программы;argv[0][0]должен быть нулевым символом, если имя программы недоступно из среды хоста. Если значениеargcбольше единицы, строки, на которые указываютargv[1]argv[argc-1]представляют параметры программы.
Параметры
argcиargvи строки, на которые указывает массивargvдолжны изменяться программой и сохранять свои последние сохраненные значения между запуском программы и ее завершением.
Обратите внимание, что это для размещенной среды, которую вы обычно видите в программах на Си. Автономная среда (такая как встроенная система) гораздо менее ограничена, как указано в 5.1.2.1 того же стандарта:
В автономной среде (в которой выполнение программы на С может происходить без какой-либо выгоды от операционной системы), имя и тип функции, вызываемой при запуске программы, определяются реализацией. Любые библиотечные средства, доступные для автономной программы, кроме минимального набора, требуемого в разделе 4, определяются реализацией.
Для размещенной среды (это нормальная среда) стандарт C99 гласит:
5.1.2.2.1 Запуск программы
Функция, вызываемая при запуске программы, называется
main. Реализация не объявляет прототип для этой функции. Он должен быть определен с типом возвратаintи без параметров:int main(void) { /* ... */ }или с двумя параметрами (именуемыми здесь как
argcиargv, хотя могут использоваться любые имена, поскольку они являются локальными для функции, в которой они объявлены):int main(int argc, char *argv[]) { /* ... */ }или эквивалент; 9) или каким-либо другим способом, определяемым реализацией.
9) Таким образом,
intможет быть заменено именем typedef, определенным какint, или типargvможет быть записан какchar **argv, и так далее.
Стандарты C11 и C18, по сути, соответствуют стандарту C99.
Стандарт C++ 98 гласит:
3.6.1 Основная функция [basic.start.main]
1 Программа должна содержать глобальную функцию main, которая является назначенным началом программы. [...]
2 Реализация не должна предопределять основную функцию. Эта функция не должна быть перегружена. Он должен иметь возвращаемый тип типа int, но в противном случае его тип определяется реализацией. Все реализации должны позволять оба следующих определения main:
int main() { /* ... */ }а также
int main(int argc, char* argv[]) { /* ... */ }
Стандарт C++ прямо говорит: "Он [основная функция] должен иметь тип возвращаемого значения типа int, но в противном случае его тип определяется реализацией", и для него требуются те же две подписи, что и для стандарта C. Таким образом, void main() напрямую не разрешен стандартом C++, хотя он ничего не может сделать, чтобы не допустить, чтобы нестандартная соответствующая реализация не позволяла альтернативы (или стандартная соответствующая реализация не позволяла альтернативы в качестве расширений стандарта).
Стандарты C++ 03, C++ 11, C++ 14 и C++ 17 говорят, по сути, о том же, что и C++ 98.
Классически 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с нулевым символом вchar, каждый из которых указывает на строку, предоставляющую информацию о среде для этого выполнения. программы (5.1.2.2.1).
Компилятор 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.
 Мне не ясно, что происходит (какой код выхода возвращается родителю или o/s), когда программа с void main() завершает работу - и веб-сайт MS тоже молчит.
 Интересно, что MS не предписывает версию main() с двумя аргументами, которая требуется для стандартов C и C++. Он только предписывает форму с тремя аргументами, где третий аргумент - char **envp, указатель на список переменных среды.
 На странице Microsoft также перечислены некоторые другие альтернативы - wmain() которая принимает строки широких символов, и некоторые другие.
 Версия этой страницы для Microsoft VS 2005 не содержит void main() в качестве альтернативы. Версии от Microsoft VS 2008 года и старше делают.
int main() таким же, как int main(void)? Для подробного анализа смотрите конец моего ответа на Что должно возвращать main() в C и C++. (Похоже, я когда-то считал, что этот вопрос относится к C++, хотя он этого не делал и никогда не делал. В C++ нет разницы между int main() и int main(void) и int main() является идиоматическим C++.)
 В C есть разница между двумя обозначениями, но вы заметите это только в эзотерических случаях. В частности, есть разница, если вы вызываете функцию main() из своего собственного кода, что вам разрешено делать в C и не разрешено делать в C++.
 Нотация int main() не предоставляет прототипа для main(), но это имеет значение, только если вы вызываете его рекурсивно. С помощью int main() вы можете позже (в той же функции или в другой функции) написать int rc = main("absolute", "twaddle", 2): и формально компилятор не должен жаловаться до степени отказа чтобы скомпилировать код, хотя он может на законных основаниях жаловаться (предупредить вас) (а использование -Werror с GCC преобразует предупреждение в ошибку). Если вы используете int main(void), последующий вызов main() должен выдать ошибку - вы сказали, что функция не принимает аргументов, но пыталась предоставить три. Конечно, вы не можете законно вызывать main() до того, как объявите или определили его (если только вы не используете семантику C90) - и реализация не объявляет прототип для main(). NB. Стандарт C11 иллюстрирует как int main() и int main(void) в разных примерах - оба действительны в C, хотя между ними есть небольшая разница.
POSIX поддерживает execve(), который, в свою очередь, поддерживает
int main(int argc, char *argv[], char *envp[])
Добавленный аргумент - это среда, то есть массив строк NAME = VALUE.
http://en.wikipedia.org/wiki/Main_function_(programming)#C_and_C.2B.2B
Помимо обычных int main(int argc, char *argv[]) и POSIX int main(int argc, char **argv, char **envp), в Mac OS X также поддерживается
int main(int argc, char* argv[], char* envp[], char* apple[]);
Конечно, это только для Mac.
В Windows есть
int wmain(int argc, wchar_t* argv[], wchar_t* envp[]);
как вариант Unicode (фактически, широко-символьный). Конечно, есть и WinMain.
int main(void)
В некоторых ОС (например, Windows) также допустимо:
int main(int argc, char **argv, char **envp)
где envp предоставляет среду, в противном случае доступную через getenv()