Почему мы не используем (void) в основном?

Люди используют void main() /*empty parens ()*/

Мне научили писать void main(void)

Любые идеи в чем разница?

Ответ 1

Я не уверен, что стандарты в настоящее время, но в традиционном ANSI C, используя пустые круглые скобки, указывает, что функция может принимать любое количество аргументов. Объявление параметра void, с другой стороны, указывает на то, что функция принимает только нулевые аргументы. В этом случае (и многих других) это действительно не имеет большого значения.

Если вы хотите быть строгим, лучше всего определить параметр void. Разумеется, функция main также может быть определена как int main(int argc, const char* argv[]) - это абсолютно корректно, но часто не нужно, если вам не нужны аргументы.

Ответ 2

Из стандарта C99:

5.1.2.2.1 Запуск программы

Функция, вызванная при запуске программы, называется main. Реализация не объявляет прототип для этой функции. Он определяется с типом возврата int и без Параметры:

int main(void) { /* ... */ }

или с двумя параметрами (называемыми здесь argc и argv, хотя любые имена могут быть используются, поскольку они являются локальными для функции, в которой они объявлены):

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

или эквивалент; или каким-либо другим способом реализации.

Когда main определяется без параметров, argc и argv все еще присутствуют в стеке?

Ответ 3

Эти прототипы main() являются нестандартными.

Точность в этом вопросе можно найти на comp.lang.c faq: http://c-faq.com/decl/main.html

EDIT: изменено "неправильно" на "нестандартное", поскольку эта норма позволяет использовать прототипы, определенные реализацией.

Ответ 4

Нет никакой разницы, но обычно 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'

Как упоминалось, прототип main (согласно стандарту):

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

Ответ 5

main является функцией, как и другая функция. Почти. В любом случае, будучи функцией, он вызывается каким-то другим кодом (стартовый код). Обычно (читайте: почти всегда) int 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;
}

не говорит об ошибке для A, а для B говорит too many arguments to function ‘func2’, скомпилировано с gcc -std=c99 -pedantic. Изменение int main(void) на int main() не имеет значения и никаких предупреждений.

В других средах (сейчас я не могу делать практические тесты), void main(void) в порядке, в то время как в этом случае он вызывает предупреждение. Предупреждение не связано только с стандартом, но только потому, что в используемой среде прототип для основного не соответствует. Стандарт, по-видимому, допускает любую другую "конфигурацию" для основного.

В случае 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 не использует их)?