Каково было обоснование того, что `return 0` в конце` main` опционально?
Начиная со стандарта C99, компилятор должен генерировать эквивалент return 0
или return EXIT_SUCCESS
, если в конце main
возврат невозможен. В то же время было также соответствующее и идентичное изменение для языка С++. Меня интересуют причины обоих, и я догадался, что вряд ли они были бы совершенно отдельными и несвязанными изменениями.
Мой вопрос:
Каково было документированное обоснование этого изменения?
Идеальный ответ привел бы авторитетные источники как для C, так и для С++, поэтому я поставил вопрос на оба языка.
Обратите внимание, что в отличие от вопроса Какие причины для возврата 0 из основного в ISO С++?, я не прошу совета о том, писать ли return 0
в моих программах - я спрашиваю, почему сами языковые стандарты были изменены.
Чтобы понять цель вопроса, вот немного больше контекста:
- Понимание того, почему было сделано изменение, полезно при принятии решения о его использовании.
- Обоснование часто включается в сам стандарт. Например, стандарт C90 включает в себя множество пояснительных сносок, таких как сноска 36, которая начинается: "Цель этого списка..."
Я изучил стандарты, которые искали ответ, прежде чем я спросил здесь, но не нашел ответа. Меня попросили помочь написать стандарты кодирования для обоих языков для группы программистов, и я хотел убедиться, что я понимаю, почему эта функция существует, чтобы я мог точно объяснить ее использование другим.
Ответы
Ответ 1
В Новый стандарт C 5.1.2.2.3 Окончание программы автор Derek Jones комментарий по этим строкам из стандарта C99:
достигая}, который завершает основную функцию, возвращает значение 0
является:
Стандарт, наконец, должен поклониться небрежным существующим практикам.
Это указывает на то, что логическое обоснование заключалось в том, чтобы устранить неправильные методы программирования в отношении явного возврата значения из main
. До этого возвращался статус undefined.
Он указывает, что многие реализации уже реализовали это даже в C90, поэтому, вероятно, также помог тот факт, что это изменение уже отразило общую реализацию.
Ответ 2
официальный документ обоснования для C99 вряд ли справится с этим. Похоже, что exit(0)
стал по умолчанию для потока управления с конца основного, потому что exit(0)
была предоставлена значимая переносная семантика.
Вот два соответствующих раздела:
5.1.2.2.1 Запуск программы
Поведение аргументов main
и взаимодействия exit
, main
и atexit
(см. §7.20.4.2) было кодифицировано для ограничения некоторого нежелательного многообразия в представлении строк argv
и в значении значений, возвращаемых main
.
Спецификация argc
и argv
в качестве аргументов main признает обширную предыдущую практику.
argv[argc]
должен быть нулевым указателем, чтобы обеспечить избыточную проверку для конца списка, также на основе обычной практики.
main
- единственная функция, которую можно условно объявить либо с нулевым, либо с двумя аргументами. (Число аргументов других функций должно точно совпадать между вызовом и определением.) Этот специальный случай просто распознает распространенную практику отказа от аргументов main
, когда программа не получает доступ к строкам аргумента программы. Хотя многие реализации поддерживают более двух аргументов main
, такая практика не является ни благословенной, ни запрещенной Стандартом; программа, определяющая main с тремя аргументами, не является строго (см. §J.1.1.).
Перенаправление ввода-вывода в командной строке не является обязательным стандартом, поскольку это считалось функцией базовой операционной системы, а не языка C.
и
7.20.4.3 Функция выхода
Аргумент exit
- это индикатор состояния, возвращаемый вызывающей среде. В операционной системе UNIX значение нуля - это успешный код возврата из программы. Поскольку использование C распространяется за пределы UNIX, exit(0)
часто сохранялось как идиома, указывающая на успешное завершение, даже в операционных системах с различными системами кодов возврата. Таким образом, это использование признанных стандартными. Никогда не было переносного способа указания неудачного завершения, поскольку аргументы exit
определены реализацией. Макрос EXIT_FAILURE
был добавлен в C89, чтобы обеспечить такую возможность. EXIT_SUCCESS
.
Помимо вызовов, явно закодированных программистом, при возврате из main
вызывается exit
. Таким образом, по крайней мере в этом случае тело exit
не может предполагать существование каких-либо объектов с автоматическим временем хранения, кроме тех, которые указаны в exit
.
Комитет рассмотрел вопрос о добавлении _exit
, но отклонил его, исходя из соображений несовместимости с спецификацией POSIX, на которой он основан. Например, одна проблема заключается в том, что _exit
был указан как способ выйти из обработчика сигнала без запуска другого сигнала, но на самом деле это не так, как _exit
ведет себя в среде POSIX. Комитет не хотел давать программистам такую ложную надежду. (Но см. §7.20.4.4 для C99.)