Почему мы не используем (void) в основном?
Люди используют void main() /*empty parens ()*/
Меня научили писать void main(void)
Есть идеи, в чем разница?
5 ответов
Я не уверен, каковы стандарты в настоящее время, но в традиционных ANSI C использование пустых скобок означает, что функция может принимать любое количество аргументов. Объявление void
Параметр, с другой стороны, указывает, что функция принимает только нулевые аргументы. В этом случае (и многих других) это не имеет большого значения.
Если вы хотите быть строгим, вероятно, лучше всего определить void
параметр. Конечно, main
Функция также может быть определена как int main(int argc, const char* argv[])
- что совершенно правильно, но часто не нужно, если вас не интересуют аргументы.
Из стандарта C99:
5.1.2.2.1 Запуск программы
Функция, вызываемая при запуске программы, называется основной. Реализация не объявляет прототип для этой функции. Он должен быть определен с типом возврата int и без параметров:
int main(void) { /* ... */ }
или с двумя параметрами (именуемыми здесь как argc и argv, хотя могут использоваться любые имена, так как они являются локальными для функции, в которой они объявлены):
int main(int argc, char *argv[]) { /* ... */ }
или эквивалент; или каким-либо другим способом, определяемым реализацией.
Когда main определен без параметров, будут ли argc и argv все еще присутствовать в стеке?
Эти прототипы main() являются нестандартными.
Точность в этом вопросе можно найти в comp.lang.c faq: http://c-faq.com/decl/main.html
РЕДАКТИРОВАТЬ: изменил "неправильно" на "нестандартный", так как норма допускает реализации прототипов.
Разницы нет, но обычно main должен возвращать int. Некоторые компиляторы выдают предупреждение (по крайней мере компилятор GNU - gcc):
$ cat x.c
void main(void){}
$ gcc x.c
x.c: In function `main':
x.c:1: warning: return type of 'main' is not `int'
Как уже упоминалось, прототип основного является (согласно стандарту):
int main(int argc, const char* argv[])
main
это функция, как и другая функция. Почти. В любом случае, будучи функцией, она вызывается каким-то другим кодом (кодом запуска). Обычно (читай: почти всегда) int main()
является правильным, но действительно то, что действительно правильно, зависит от платформы, на которой вы работаете. Поскольку, как уже было сказано, функция main может вызываться кодом запуска, который вообще не передает никаких аргументов и не ожидает возврата значения в конкретном регистре (так что void main(void)
верно).
int main()
является правильным, поскольку обычно запускаемый код ожидает возвращаемого значения и передает два аргумента. Говоря int main(void)
Вы говорите, что main не принимает аргументов вообще, в большинстве случаев это ложь. С ()
Вы говорите, что есть аргументы (один, два, три, вам все равно), но вы не заинтересованы в них, поэтому вам не интересно говорить, кто они и какой тип.
Как я вижу в кодах, наиболее часто используемый прототип для "нормальных" сред (без встроенного устройства или других "странных" сред, в которых main можно называть по-другому) int main()
когда вы игнорируете пройденное int argc, char **argv
аргументы. (GCC жалуется, так как мы используем версию для gcc, подходящую для среды; протестируйте ее с кросс-версией GCC для одной из сред, где код запуска не передает никаких аргументов и не ожидает возврата)
редактировать
Просто быть добрым к скептикам; в среде, где главная функция вызывается с двумя аргументами, следующее
int func()
{
return 0;
}
int func2(void)
{
return 1;
}
int main(void)
{
int a;
a = func(a, a); /* A */
a = func2(a); /* B */
return 0;
}
говорит, что нет ошибки для А, а для В говорит too many arguments to function ‘func2’
составлено с gcc -std=c99 -pedantic
, изменения int main(void)
в int main()
не имеет значения, и никаких предупреждений.
В других средах (я не могу делать практические тесты сейчас), void main(void)
все в порядке, в то время как в этом случае это вызывает предупреждение. Предупреждение не из-за одного стандарта, а только потому, что в используемой среде прототип для main не совпадает. Стандарт, кажется, допускает любую другую "конфигурацию" для основного.
В случае OP, учитывая "нормальную" среду (например, ОС, например, GNU/Linux), где два аргумента передаются главному, и ожидается возвращаемое значение, int main()
предпочтительнее (аргументы помещаются в стек стартовым кодом, говорите ли вы int main(void)
или нет, так int main()
для меня больше смысла)
редактировать
Еще одна заметка, всегда для скептиков. Как уже доказано, B вызывает ошибку, так как я сказал, что это int func2(void)
но я называю это передачей аргумента. Затем предположим, что мы можем скомпилировать код запуска и связать его, как любой другой код. Где-то это будет называться основным, таким образом, как
retval = main(argc, argv);
Если бы мы использовали int main(void)
компилятор остановится, выдав ошибку, так как код запуска (в этой среде) пытается вызвать main с двумя аргументами. Если мы используем int main()
ничего не происходит и код компилируется правильно.
Так, int main()
превосходит int main(void)
(в среде, где мы ожидаем, что два аргумента для главного возможны)
редактировать
Скорее вызов как
retval = main(_argc, _argv, environ);
на многих системах, но это не меняет предыдущую речь.
окончательное редактирование
Кто-нибудь обнаружил, что при создании инструмента командной строки (т.е. в системах, где int argc, char **
имеет смысл) с int main(void)
выбранный компилятор / компоновщик связывает код запуска, где main
вызывается без аргументов (какими бы ни были соглашения о вызовах), а вместо этого при сборке с int main(int argc, char **argv)
код запуска отличается и на самом деле вызывает main
с этими двумя аргументами (даже если main
сама их не использует)?