Что послужило основанием для того, чтобы сделать `return 0` в конце`main` необязательным?

Начиная со стандарта C99, компилятор должен генерировать эквивалент return 0 или же return EXIT_SUCCESS если нет возврата в конце main, В это же время произошли соответствующие и идентичные изменения в стандарте языка C++. Меня интересуют причины обоих, и я догадывался, что вряд ли они были совершенно отдельными и не связанными изменениями.

Мой вопрос:

Каково было документированное обоснование этого изменения?

В качестве идеального ответа можно привести авторитетные источники как для C, так и для C++, поэтому я пометил вопрос обоими языками.

Обратите внимание, что в отличие от вопроса Каковы причины для / против возвращения 0 из основного в ISO C++? Я не прошу совета о том, чтобы написать return 0 в моих программах - я спрашиваю, почему изменились сами языковые стандарты.


Чтобы помочь понять цель вопроса, вот немного больше контекста:

  1. Понимание того, почему было внесено изменение, помогает решить, как его использовать.
  2. Обоснование часто включается в сам стандарт. Например, стандарт 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.)

Другие вопросы по тегам