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