Что должно возвращать main () в C и C ++? - PullRequest
632 голосов

Ответы [ 18 ]

2 голосов
/ 15 октября 2008

У меня сложилось впечатление, что стандарт определяет, что main не нуждается в возвращаемом значении, поскольку успешное возвращение основано на ОС (ноль в одном может быть либо успехом, либо неудачей в другом), поэтому отсутствие возврата было подсказка компилятору о вставке самого успешного возврата.

Однако я обычно возвращаю 0.

2 голосов
/ 23 ноября 2012

Возвращение 0 должно сообщить программисту, что программа успешно завершила работу.

1 голос
/ 04 октября 2017

Как правильно (наиболее эффективно) определить функцию main () в C и C ++ - int main () или void main () - и почему?

Эти слова "(наиболее эффективные)" не меняют вопрос. Если вы не находитесь в автономной среде, есть один универсально правильный способ объявить main(), и это как возвращение int.

Что должен main() вернуть в C и C ++?

Это не то, что должно main() вернуть, это то, что делает main(). main() это, конечно, функция, которую кто-то еще вызывает. Вы не можете контролировать код, который вызывает main(). Следовательно, вы должны объявить main() с правильной сигнатурой для соответствия вызывающей стороне. У вас просто нет выбора в этом вопросе. Вам не нужно спрашивать себя, что является более или менее эффективным, что лучше или хуже, или что-то в этом роде, потому что ответ для вас уже совершенно четко определен стандартами C и C +. Просто следуйте за ними.

Если int main (), вернуть 1 или 0?

0 для успеха, ненулевое значение для отказа. Опять же, не то, что вам нужно (или нужно) выбирать: это определяется интерфейсом, которому вы должны соответствовать.

1 голос
/ 03 марта 2011

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

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

Подробно, если вы хотите узнать, является ли возврат 0 более или менее эффективным, чем возврат 1, в некоторых случаях это может зависеть от компилятора, но, как правило, при условии, что они читаются из одного источника (локальный, поле константа, встроенная в код, результат функции и т. д.), для которого требуется одинаковое количество тактов.

1 голос
/ 10 марта 2011

Что вернуть, зависит от того, что вы хотите сделать с исполняемым файлом. Например, если вы используете вашу программу с оболочкой командной строки, вам нужно вернуть 0 для успеха и ненулевое значение для ошибки. Тогда вы сможете использовать программу в оболочках с условной обработкой в ​​зависимости от результата вашего кода. Также вы можете назначить любое ненулевое значение в соответствии с вашей интерпретацией, например, для критических ошибок разные точки выхода из программы могут завершить программу с разными значениями выхода, и которая доступна вызывающей оболочке, которая может решить, что делать, проверяя возвращенное значение. Если код не предназначен для использования с оболочками и возвращаемое значение никого не беспокоит, его можно опустить. Я лично использую подпись int main (void) { .. return 0; .. }

0 голосов
/ 23 февраля 2018

В C ++ основная функция должна быть объявлена ​​как int main (), а не как void main (), так как компилятор выдает ошибку в случае void main. Функция main может принимать любое количество аргументов, таких как int main (int k, int l, int arr []) или int main (void).

#include <iostream>
using namespace std;

int main(void) {
    // your code goes here
    cout<<"a";
    return 0;
}

Выход:

Success #stdin #stdout 0s 4416KB
a

Возвращаясь к возвращаемой части, он должен возвращать только 0, иначе компилятор выдаст ошибку. например, если вы вернете 1, вы получите желаемый результат, но он также выдаст ошибку времени выполнения.

Пример

#include <iostream>
using namespace std;

int main(int k,float m,char g, int arr[]) {
    // your code goes here
    k=0;
    cout<<k;
    g='a';
    cout<<g;
    cout<<"a";
    return 1;
}

Выход:

Runtime error   #stdin #stdout 0s 4448KB
0aa
0 голосов
/ 22 апреля 2017

Пропустить return 0

Когда программа на C или C ++ достигает конца main, компилятор автоматически сгенерирует код, возвращающий 0, поэтому нет необходимости явно указывать return 0; в конце main.

Примечание: когда я делаю это предложение, за ним почти всегда следует один из двух видов комментариев: «Я этого не знал». или "Это плохой совет!" Мое обоснование заключается в том, что безопасно и полезно полагаться на поведение компилятора, явно поддерживаемое стандартом. Для C, так как C99; см. ИСО / МЭК 9899: 1999, раздел 5.1.2.2.3:

[...] возврат из начального вызова функции main эквивалентен вызову функции exit со значением, возвращаемым функцией main в качестве аргумента; достижение }, которое завершает функцию main, возвращает значение 0.

Для C ++, начиная с первого стандарта в 1998 году; см. ИСО / МЭК 14882: 1998, раздел 3.6.1:

Если элемент управления достигает конца main, не встретив оператора return, результатом является выполнение return 0;

Все версии обоих стандартов с тех пор (C99 и C ++ 98) придерживались той же идеи. Мы полагаемся на автоматически сгенерированные функции-члены в C ++, и немногие люди пишут явные операторы return; в конце функции void. Кажется, причины против пропуска сводятся к "это выглядит странно" . Если, как и я, вас интересует обоснование изменения стандарта C , прочитайте этот вопрос . Также обратите внимание, что в начале 1990-х это считалось «небрежной практикой», потому что в то время это было неопределенное поведение (хотя и широко поддерживаемое).

Так что я рекомендую опустить это; другие не согласны (часто яростно!). В любом случае, если вы столкнетесь с кодом, который его пропускает, вы будете знать, что он явно поддерживается стандартом, и вы поймете, что он означает.

0 голосов
/ 11 февраля 2015

Вот небольшая демонстрация использования кодов возврата ...

При использовании различных инструментов, предоставляемых терминалом Linux, можно использовать код возврата, например, для обработки ошибок после завершения процесса. Представьте, что присутствует следующий текстовый файл myfile:

Это пример того, как проверить, как работает grep.

Когда вы выполняете команду grep, создается процесс. По завершении (и без прерывания) возвращается код от 0 до 255. Например:

$ grep order myfile

Если вы делаете

$ echo $?
$ 0

вы получите 0. Почему? Потому что grep нашел совпадение и возвратил код выхода 0, который является обычным значением для выхода с успехом. Давайте проверим это снова, но с чем-то, чего нет в нашем текстовом файле, и, следовательно, совпадение не будет найдено:

$ grep foo myfile
$ echo $?
$ 1

Поскольку grep не удалось сопоставить токен "foo" с содержимым нашего файла, код возврата равен 1 (это обычный случай, когда происходит сбой, но, как указано выше, у вас есть множество значений на выбор).

Теперь следующий скрипт bash (просто введите его в терминале Linux), хотя и очень простой, должен дать некоторое представление об обработке ошибок:

$ grep foo myfile
$ CHECK=$?
$ [ $CHECK -eq 0] && echo 'Match found'
$ [ $CHECK -ne 0] && echo 'No match was found'
$ No match was found

После второй строки ничего не выводится на терминал, так как "foo" заставляет grep вернуть 1, и мы проверяем, был ли код возврата grep равен 0. Второе условное выражение повторяет свое сообщение в последней строке, так как оно истинно из-за проверки == 1.

Как вы можете видеть, вызываете ли вы этот и тот процесс, иногда важно увидеть, что он вернул (по возвращаемому значению main ()).

...