Вопрос

Каковы на самом деле допустимые сигнатуры для функции main в 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] inclusive должен содержать указатели на строки, которым перед запуском программы присваиваются значения, определенные реализацией в среде хоста.Цель состоит в том, чтобы предоставить программе информацию, определенную до ее запуска, из другого места в размещенной среде.Если среда хоста не способна предоставлять строки с буквами как в верхнем, так и в нижнем регистре, реализация должна гарантировать, что строки принимаются в нижнем регистре.

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

  • Параметры argc и argv и строки, на которые указывает argv Массив должен быть доступен для изменения программой и сохранять свои последние сохраненные значения между запуском программы и ее завершением.

Обратите внимание, что это касается размещенной среды, которую вы обычно видите в программах на C.Автономная среда (например, встроенная система) гораздо менее ограничена, как указано в 5.1.2.1 того же стандарта:

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

Другие советы

Стандарт C

Для размещенной среды (это обычная среда) стандарт 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 ++

Стандарт C ++ 98 гласит:

3.6.1 Основная функция [basic.start.main]

1 Программа должна содержать глобальную функцию с именем main, которая является назначенным началом программы.[...]

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

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 Аргументы в пользу окружающей среды

¶1 В размещенной среде функция main получает третий аргумент, char *envp[], который указывает на завершающийся нулем массив указателей на char, каждый из которых указывает на строку , которая предоставляет информацию об окружении для данного выполнения программы (5.1.2.2.1).

Microsoft C

Тот Самый Microsoft ПРОТИВ 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 НАЧИНАЯ с 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().Примечание:Стандарт C11 иллюстрирует оба варианта int main() и int main(void) в разных примерах — оба допустимы на C, хотя между ними есть тонкая разница.

POSIX поддерживает исполнительный(), что, в свою очередь, поддерживает

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

Дополнительным аргументом является окружающая среда, т.е.массив строк вида ИМЯ=ЗНАЧЕНИЕ.

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()

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top