Вопрос

Должен ли я использовать exit() или просто return операторы в main()? Лично я одобряю операторы <=>, потому что я чувствую, что это похоже на чтение любой другой функции, и управление потоком, когда я читаю код, плавно (на мой взгляд). И даже если я хочу реорганизовать функцию <=>, наличие <=> кажется лучшим выбором, чем <=>.

Делает ли <=> что-то особенное, что не делает <=>?

Это было полезно?

Решение

На самом деле, есть разница, но она неуловима. Это имеет больше последствий для C ++, но различия важны.

Когда я вызываю return в main(), для моих локально ограниченных объектов будут вызываться деструкторы. Если я вызову exit(), не будет вызываться деструктор для моих объектов с локальной областью действия! Перечитайте это. static не возвращается . Это означает, что когда я это называю, & Quot; backsies нет. & Quot; Любые объекты, которые вы создали в этой функции, не будут уничтожены. Часто это не имеет значения, но иногда это имеет место, например закрытие файлов (конечно, вы хотите, чтобы все ваши данные были записаны на диск?).

Обратите внимание, что abort() объекты будут очищены, даже если вы вызовете <=>. Наконец, обратите внимание, что если вы используете <=>, ни один объект не будет уничтожен. То есть никакие глобальные объекты, никакие статические объекты и никакие локальные объекты не будут вызывать свои деструкторы.

Будьте осторожны, предпочитая выход, а не возврат.

http://groups.google.com/group/gnu. gcc.help/msg/8348c50030cfd15a

Другие советы

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

int main() { return 0; }

но для использования main вам понадобится включить:

#include <stdlib.h>
int main() { exit(EXIT_SUCCESS); }

Кроме того, это добавляет дополнительное предположение: вызов return из <=> имеет те же побочные эффекты, что и возврат нуля. Как уже отмечали другие, это зависит от того, какой тип исполняемого файла вы создаете (то есть, кто звонит <=>). Вы кодируете приложение, которое использует C-runtime? Плагин майя? Служба Windows? Водитель? Каждый случай потребует исследования, чтобы определить, является ли <=> эквивалентом <=>. ИМХО использование <=>, когда вы действительно имеете в виду <=>, просто делает код более запутанным. OTOH, если вы действительно имеете в виду <=>, то обязательно используйте это.

Существует по крайней мере одна причина для предпочтения exit: если какой-либо из ваших обработчиков atexit ссылается на данные автоматического хранения в main или если вы использовали setvbuf или setbuf для назначения один из стандартных потоков автоматически создает буфер продолжительности хранения в <=>, затем возврат из <=> приводит к неопределенному поведению, но вызов <=> допустим.

Другое возможное использование (обычно зарезервированное для игрушечных программ) - выход из программы с рекурсивными вызовами <=>.

Я всегда использую return, потому что стандартный прототип для main() говорит, что он возвращает int.

Тем не менее, некоторые версии стандартов предоставляют main особый режим и предполагают, что он возвращает 0, если нет явного foo() оператора. Учитывая следующий код:

int foo() {}
int main(int argc, char *argv[]) {}

G ++ генерирует предупреждение только для <=> и игнорирует пропущенный возврат из <=>:

% g++ -Wall -c foo.cc
foo.cc: In function ‘int foo()’:
foo.cc:1: warning: control reaches end of non-void function

Я STRONGLY второй комментарий Р. об использовании exit (), чтобы избежать автоматического восстановления в main() до того, как программа действительно закроется. Оператор return X; в exit(X); не совсем эквивалентен вызову exit(), поскольку динамическое хранилище return исчезает при возврате <=>, но не исчезает, если вызов <=> сделано вместо этого.

Кроме того, в C или любом C-подобном языке оператор <=> настоятельно подсказывает читателю, что выполнение будет продолжено в вызывающей функции, и хотя это продолжение выполнения обычно технически верно, если вы считаете подпрограмму запуска C, которая вызвал вашу <=> функцию, это не совсем то, что вы имеете в виду, когда хотите завершить процесс.

В конце концов, если вы хотите завершить свою программу из любой другой функции, кроме <=>, вы должны вызвать <=>. Такое постоянное выполнение в <=> также делает ваш код более читабельным, а также значительно упрощает повторный анализ вашего кода; код, скопированный из <=> в другую функцию, не будет работать неправильно из-за случайных <=> утверждений, которые должны были <=> вызывать.

Таким образом, объединяя все эти пункты вместе, можно сделать вывод, что вредная привычка , по крайней мере для C, использовать оператор <=> для завершения программы в <=>.

  

Выполняет ли exit () что-то особенное, что не делает return?

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

Стандарт требует идентичного поведения в этих случаях (в частности, он говорит, что возвращение чего-то int - совместимого с EXIT_SUCCESS должно быть эквивалентно вызову EXIT_FAILURE с этим значением). Проблема в том, что разные ОС имеют разные соглашения для интерпретации выходных значений. Во многих (МНОЖЕ!) Системах 0 означает успех, а все остальное - неудача. Но, скажем, в VMS нечетные значения означают успех, а четные - неудачу. Если вы вернули 0 из exit(0), пользователь VMS увидит неприятное сообщение о нарушении доступа. На самом деле не было нарушения прав доступа - это было просто стандартное сообщение, связанное с кодом ошибки 0.

Затем появился ANSI и благословил exit(EXIT_SUCCESS) и 0 в качестве аргументов, которые вы могли бы передать <=>. Стандарт также гласит, что <=> должен вести себя идентично <=>, поэтому большинство реализаций определяют <=> как <=>.

Таким образом, стандарт ставит вас в тупик в VMS, поскольку он не оставляет стандартного способа вернуть код fail , который имеет значение 0.

Поэтому компилятор VAX / VMS C начала 1990-х годов не интерпретировал возвращаемое значение из <=>, а просто возвращал любое значение в среду хоста. Но если бы вы использовали <=>, он бы сделал то, что требовал стандарт: перевести <=> (или <=>) в код успеха и <=> в общий код ошибки. Чтобы использовать <=>, вы должны были передать его <=>, вы не можете вернуть его из <=>. Я не знаю, сохранили ли такое поведение более современные версии этого компилятора.

Портативная программа на Си раньше выглядела так:

#include <stdio.h>
#include <stdlib.h>

int main() {
  printf("Hello, World!\n");
  exit(EXIT_SUCCESS);  /* to get good return value to OS */
  /*NOTREACHED*/ /* to silence lint warning */
  return 0;  /* to silence compiler warning */
}

В сторону: если я правильно помню, соглашение VMS для значений выхода более нюансировано, чем нечетное / четное. На самом деле он использует что-то вроде младших трех битов для кодирования уровня серьезности. В целом, однако, уровни нечетной серьезности указывают на успех или различную информацию, а четные указывают на ошибки.

В Си возврат из main точно такой же, как и вызов exit с тем же значением.

Раздел 5.1.2.2.3 в C стандарт гласит:

  

Если возвращаемый тип главной функции - это тип, совместимый с int    возврат из начального вызова основной функции эквивалентен   вызов функции выхода со значением, возвращаемым основным   функция в качестве аргумента ; 11) достижение}, который завершает   Функция main возвращает значение 0. Если тип возвращаемого значения   несовместим с int, статус завершения возвращен   среда хоста не указана.

Правила для C ++ немного отличаются, как упоминалось в других ответах.

На самом деле есть разница между exit(0) и return(0) в main & # 8211; & nbsp; когда ваша функция exit вызывается несколько раз.

Следующая программа

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  if (argc == 0)
    return(0);
  printf("%d", main(argc - 1, argv));
}

Запуск от имени

./program 0 0 0 0

Результатом будет следующий вывод:

00000

Однако этот:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  if (argc == 0)
    exit(0);
  printf("%d", main(argc - 1, argv));
}

Ничего не печатать независимо от аргументов.

Если вы уверены, что никто никогда не назовет ваш <=> явно, это не является большой технической разницей в целом, но поддержание более ясного кода <=> выглядело бы намного лучше. Если по какой-то причине вы хотите позвонить <=> & # 8211; Вы должны настроить его под свои нужды.

Говоря о Си.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top