Ответ 1
Только авторы книг, похоже, относятся к месту, где разрешен тип возврата void
для main()
. Стандарт С++ запрещает его полностью.
В стандарте C говорится, что стандартные формы:
int main(void) { ... }
и
int main(int argc, char **argv) { ... }
разрешая альтернативные, но эквивалентные формы объявления для типов аргументов (и имена полностью дискреционные, конечно, поскольку они являются локальными переменными для функции).
Стандарт C делает небольшое положение для "в некоторой другой определенной реализации". В стандарте ISO/IEC 9899: 2011 говорится:
5.1.2.2.3 Окончание программы
Если тип возврата функции
main
является типом, совместимым сint
, возврат из начальный вызов функцииmain
эквивалентен вызову функцииexit
со значением возвращаемый функциейmain
в качестве аргумента; 11) достигающий}
, который завершает основная функция возвращает значение 0. Если тип возврата не совместим сint
, статус завершения, возвращенный в среду хоста, не указан.11) В соответствии с 6.2.4 время жизни объектов с автоматическим временем хранения, объявленным в основном закончится в первом случае, даже если они не были бы в последнем.
Это явно позволяет возвращать не int
, но дает понять, что он не указан. Таким образом, void
может быть разрешен как возвращаемый тип main()
некоторой реализацией, но вы можете найти только это из документации.
(Хотя я цитирую стандарт C2011, по сути, те же слова были на C99, и я считаю C89, хотя мой текст для этого находится в офисе, а я нет.)
Кстати, в Приложении J стандарта упоминается:
J.5 Общие расширения
Следующие расширения широко используются во многих системах, но не переносимы для всех Реализации. Включение любого расширения, которое может привести к строгому соответствию программа становится недействительной, что делает несоответствие реализации. Примеры таких расширения - это новые ключевые слова, дополнительные функции библиотеки, объявленные в стандартных заголовках, или предопределенные макросы с именами, которые не начинаются с подчеркивания.
J.5.1 Аргументы среды
В размещенной среде функция
main
получает третий аргумент,char *envp[]
,, который указывает на нуль-завершенный массив указателей наchar
, каждый из которых указывает на строку который предоставляет информацию об окружающей среде для этого выполнения программы (5.1.2.2.1).
Почему работает void main()
?
В вопросе отмечается, что void main()
работает. Он работает, потому что компилятор делает все возможное, чтобы генерировать код для программ. Компиляторы, такие как GCC, будут предупреждать о нестандартных формах для main()
, но будут обрабатывать их. Линкер не слишком беспокоится о типе возврата; ему просто нужен символ main
(или, возможно, _main
, в зависимости от системы), и когда он его найдет, связывает его с исполняемым файлом. Код запуска предполагает, что main
был определен стандартным образом. Если main()
возвращается к коду запуска, он собирает возвращаемое значение, как если бы функция возвращала int
, но это значение, скорее всего, будет мусором. Таким образом, это похоже на работу, пока вы не ищете статус выхода вашей программы.