Должен ли я возвращать EXIT_SUCCESS или 0 из main ()?

124

Это простой вопрос, но я продолжаю видеть противоречивые ответы: должна ли основная процедура программы на C ++ возвращаться 0или EXIT_SUCCESS?

#include <cstdlib>
int main(){return EXIT_SUCCESS;}

или

int main(){return 0;}

Это одно и то же? Следует использовать EXIT_SUCCESSтолько с exit()?

Я подумал, EXIT_SUCCESSчто это будет лучший вариант, потому что другое программное обеспечение может захотеть посчитать ноль как отказ, но я также слышал, что если вы вернетесь 0, компилятор в любом случае сможет изменить его на другое значение.

Тревор Хики
источник
Отвечает ли это на ваш вопрос? stackoverflow.com/questions/1188335/…
Blastfurnace
2
Этот ответ о C90 перефразирует стандарт - 0и EXIT_SUCCESSоба они интерпретируются как успех.
ta.speot.is
Я отвечу здесь, так как чувствую, что в будущем это будет читать кто-то другой. В основном существует множество парадигм того, как выглядит «правильный Си». Некоторые парадигмы предпочитают использовать литералы вместо макросов, например, вместо передачи NULL в качестве аргумента они могут передавать (const char *) 0, чтобы указать, что это не просто null, но если это не было null, это должно быть постоянный указатель на символ. Другие парадигмы предпочитают не зависеть от типа и, используя макротипы, они могут избежать необходимости изменять свою кодовую базу, когда что-то радикально меняется. Например, многие -
Дмитрий
@Dmitry <continued> Определения типов Windows API неверны на новых платформах, но, поскольку они были макросами, у них был простой способ изменить все типы на те, которые действительно работают, путем переопределения макроса, и многие из этих типов просто масштабируются по определению (например, int отличается на разных платформах). Подводя итог, используйте такие вещи, как EXIT_SUCCESS, если код возврата имеет значение и может измениться в будущем, в противном случае возврат 0 может показаться магическим числом, но это все еще совершенно допустимое стандартное соглашение. Код ошибки в основном предназначен для программ, которые перенаправляют результаты номеров друг в друга, -
Дмитрий
@Dmitry <continued> использование кодов ошибок для отладки вашей программы немного слабоват, поскольку, если он возвращает 0, это довольно бесполезная информация, за исключением некоторых случаев, когда в программе есть необработанные необработанные ошибки, которые могут заставить программу тихо прерваться, и вам нужно чтобы проверить, вернул ли он нормально (0) или произошла тихая ошибка. Возврат числа более полезен для передачи 0..255 из одной программы в другую на основе их входных данных, в противном случае нет причин думать об этом: либо верните 0, либо используйте предварительно скомпилированный main, который встраивает вызов void "init", чтобы не визуально раздражать вас бесполезной отдачей.
Дмитрий

Ответы:

151

EXIT_FAILUREлибо в операторе возврата, mainлибо в качестве аргумента exit(), - это единственный переносимый способ указать на сбой в программе C или C ++. exit(1)может фактически сигнализировать об успешном завершении работы, например, на VMS.

Если вы собираетесь использовать, EXIT_FAILUREкогда ваша программа терпит неудачу, вы также можете использовать, EXIT_SUCCESSкогда она успешна, просто ради симметрии.

С другой стороны, если программа никогда не сигнализирует об ошибке, вы можете использовать либо 0или EXIT_SUCCESS. Оба стандарта гарантируют успешное завершение. (Едва ли возможно, что это EXIT_SUCCESSможет иметь значение, отличное от 0, но оно равно 0 во всех реализациях, о которых я когда-либо слышал.)

Использование 0имеет небольшое преимущество, которое вам не нужно #include <stdlib.h>в C или #include <cstdlib>C ++ (если вы используете returnоператор, а не вызываете exit()), но для программы любого значительного размера вы собираетесь прямо или косвенно включать stdlib тем не мение.

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

(Кто - то спросил о OpenVMS. Я не использовал его в течение длительного времени, но , как я помню , нечетные значения состояния , как правило , обозначают успех , а четные значения обозначают ошибки. Реализация C отображает 0на 1, так что return 0;указывает на успешное завершение. Другие значения передаются без изменений , поэтому return 1;также указывает на успешное завершение. EXIT_FAILUREбудет иметь ненулевое четное значение.)

Кейт Томпсон
источник
@KeithThompson не могли бы вы пояснить свой ответ относительно VMS (OpenVMS?). Неясно, как связаны EXIT_SUCCESS / EXIT_FAILURE с 0 и 1. Вместо этого я бы объяснил нечетные / четные значения.
malat
@malat: Вы действительно используете VMS?
Кейт Томпсон
нет, никогда не использовал. Я искал канонический ответ, поскольку в википедии использовалась другая формулировка .
malat
1
@Rhymoid: это указано в C, а не в POSIX.
Кейт Томпсон
1
@DeanP: 0и EXIT_SUCCESSне гарантируется, что они будут иметь одинаковое значение (я упомянул об этом в своем ответе), но они оба означают успешное завершение. EXIT_SUCCESSстилистически лучше, если вы тоже используете EXIT_FAILURE, но exit(0)это нормально.
Кейт Томпсон
25

Не важно. Оба одинаковые.

Стандартные цитаты C ++:

Если значение статуса равно нулю или EXIT_SUCCESS, возвращается форма успешного завершения статуса, определяемая реализацией.

Алок Сохранить
источник
12
Для компилятора это не имеет значения, но может иметь значение с точки зрения стиля.
celtschk
2
@celtschk: Стиль стиля основан на восприятии, иначе говоря, нестандартизирован, поэтому это не считается разницей. Вы можете сравнивать только яблоки с яблоками, а не яблоки с грушами.
Alok Save
3
Нет никаких гарантий, что это EXIT_SUCCESS == 0. С другой стороны, для того, чтобы этого не было, нет никаких уважительных причин.
Кейт Томпсон
@KeithThompson: почему нет гарантии, что EXIT_SUCCESS == 0.? Пожалуйста, объясните это более четко.
Destructor
2
@PravasiMeet: в системе может быть несколько значений, указывающих на успех.
Кейт Томпсон
11

0 по определению является магическим числом. EXIT_SUCCESS почти всегда равно 0, к счастью. Так почему бы просто не вернуться / выйти 0?

Выход (EXIT_SUCCESS); совершенно ясен по смыслу.

Выход (0); с другой стороны, в некотором смысле противоречит здравому смыслу. Кто-то, не знакомый с поведением оболочки, может предположить, что 0 == false == плохо, как и любое другое использование 0 в C. Но нет - в этом особом случае 0 == успех == хорошо. Для большинства опытных разработчиков это не проблема. Но зачем сбивать с толку нового парня без всякой причины?

tl; dr - если для вашего магического числа есть определенная константа, почти никогда не бывает причин не использовать эту константу в первую очередь. Он более доступен для поиска, часто более понятен и т. Д., И это вам ничего не стоит.

Джеймс
источник
Я думаю, что ваши комментарии о людях, которые ожидают, что 0 будет автоматически плохим, неуместны. Очень многие API используют 0 для успеха и отличное от 0 для отказа, даже в stdlib. Например , STDLIB ( fclose(), setvbuf(), ...), POSIX ( listen(), pthread_create(), pipe(), ...), и многие, многие другие библиотеки (например , OpenGL [ glGetError()], Zlib [ deflate()/ inflate()/ ...], SDL [ SDL_CreateWindowAndRenderer()/ ...], и Больше).
Тим
2
Конечно, есть и другие случаи, когда 0 используется для «успеха», но он прав в том, что это сбивает с толку.
Paul Wintz
10

Это нескончаемая история, отражающая ограничения (миф) «универсальности и мобильности».

То, что программа должна вернуть для обозначения "успеха", должно определяться тем, кто получает значение (операционная система или процесс, вызвавший программу), а не спецификацией языка.

Но программисты любят писать код «переносимым способом», и поэтому они изобретают свою собственную модель концепции «операционной системы», определяющей возвращаемые символические значения.

Теперь, в сценарии «многие ко многим» (где многие языки служат для написания программ для многих систем) соответствие между языковым соглашением об «успехе» и соглашением операционной системы (которое никто не может гарантировать, что он всегда одинаков) должно обрабатываться конкретной реализацией библиотеки для конкретной целевой платформы.

Но, к сожалению, эти концепции были не так ясны в то время, когда был развернут язык C (в основном для написания ядра UNIX), и гигаграммы книг, в которых говорилось, что «return 0 означает успех», поскольку это было верно для ОС в в то время был компилятор C.

С тех пор не было сделано никакой четкой стандартизации того, как следует обрабатывать такое соответствие. В C и C ++ есть собственное определение «возвращаемых значений», но никто не предоставляет правильный перевод ОС (или лучше: никакая документация компилятора ничего не говорит об этом). 0 означает успех, если верно для UNIX - LINUX и - по независимым причинам - также для Windows, и это покрывает 90% существующих "потребительских компьютеров", которые - в большинстве случаев - игнорируют возвращаемое значение (так что мы можем обсуждать десятилетиями, бу никто и не заметит!)

В этом сценарии, прежде чем принимать решение, задайте следующие вопросы: - Интересно ли мне сообщить вызывающему абоненту что-нибудь о моем существовании? (Если я просто всегда возвращаю 0 ... за всем этим нет ключа) - У моего вызывающего абонента есть соглашения об этом общении? (Обратите внимание, что одно значение не является соглашением: оно не допускает представления информации)

Если оба ответа отрицательны, вероятно, хорошее решение - вообще не писать основной оператор возврата. (И пусть компилятор решает, в отношении какой цели работает).

Если нет соглашения, 0 = успех соответствует большинству ситуаций (и использование символов может быть проблематичным, если они вводят соглашение).

Если существуют соглашения, убедитесь, что используются согласованные с ними символические константы (и обеспечьте согласованность соглашений, а не согласованность значений между платформами).

Эмилио Гаравалья
источник
4

Как только вы начнете писать код, который может возвращать множество статусов выхода, вы начинаете #defineих все. В этом случае EXIT_SUCCESSимеет смысл не быть « магическим числом ». Это делает ваш код более читабельным, потому что любой другой код выхода будет EXIT_SOMETHING. Если вы просто напишете программу, которая вернется, когда она будет выполнена, return 0будет правильной и, вероятно, даже более чистой, потому что предполагает отсутствие сложной структуры кода возврата.

Phonon
источник
0

То, что вы возвращаете из программы, - это просто соглашение.

Нет, я не могу придумать никаких обстоятельств, при которых "EXIT_SUCCESS" не было бы "0".

Лично я бы рекомендовал «0».

ПО МОЕМУ МНЕНИЮ...

paulsm4
источник
1
Я программировал на C ++ 10 лет и до сих пор не могу вспомнить, означает ли 0 успех или неудачу с точки зрения возвращаемых значений.
lahjaton_j
@lahjaton_j Я понимаю. Он думает, что это потому, что это противоречит интуиции: 0ложно, и многие функции возвращаются 0при неудаче / ничего не делают.
смысл-имеет значение
-4

Если вы используете EXIT_SUCCESS, ваш код будет более переносимым.

http://www.dreamincode.net/forums/topic/57495-return-0-vs-return-exit-success/

Мохаммад Могими
источник
5
Я очень сомневаюсь, что это сделает ваш код более или менее переносимым.
Бенджамин Линдли
9
Нет, не будет. Стандарт гарантирует, что 0 и EXIT_SUCCESSоба означают успешное завершение.
Кейт Томпсон
-5

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

двуличный
источник
Я имел в виду, что на Mac EXIT_SUCCESS работал без включения cstdlib.
Ambidextrous
4
Если он EXIT_SUCCESSработал без включения одного <stdlib.h>или <cstdlib>, его должен прямо или косвенно определять какой-либо другой заголовок. В C ++ стандартные заголовки обычно используются для #includeдругих стандартных заголовков. Если это компилируется без ошибок: int main() { return EXIT_SUCCESS; }вероятно, ваш компилятор глючит.
Кейт Томпсон