Подтвердить что ты не робот

Обоснование за возвратом 0 в качестве значения по умолчанию в C/С++

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

Мне просто стало любопытно, увидев несколько тестов, выполненных с отрицательной логикой. Очень запутанно.

Почему бы не вернуть 1, или 0xff, или любое положительное число, если на то пошло?

4b9b3361

Ответ 1

Обоснование заключается в том, что вы хотите различить множество всех возможных (отрицательных) значений возврата, соответствующих различным ошибкам, из единственной ситуации, в которой все прошло нормально. Простейший, самый лаконичный и самый C-ish способ провести такое различие - логический тест, и поскольку в C все целые числа являются "истинными", кроме нуля, вы хотите вернуть нуль, чтобы означать "единственная ситуация", то есть вы хотите ноль как "хорошее" значение.

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

Ответ 2

Первоначально C не имел "пустоты". Если функция ничего не вернула, вы просто оставили тип возврата в декларации пустой. Но это означало, что он вернул int.

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

// Perfectly good K&R C code.
NoReturn()
{
   // do stuff;
   return;
}

int unknownValue = NoReturn();

Люди решили очистить это до нуля, чтобы избежать проблем.

Ответ 3

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

Возможно также, что они ничего не возвращают, что интерпретируется как 0. (По сути, это одно и то же понятие.)

Ответ 4

Другая (младшая) причина связана с скоростью машинного уровня и размером кода.

В большинстве процессоров любая операция, которая приводит к нулю, автоматически устанавливает флаг нуля, и существует очень дешевая операция для перехода к нулевому знаку.

Другими словами, если последняя работа с машиной (например, PUSH) привела нас к нулю, все, что нам нужно, это прыгать-на-ноль или прыгать не-ноль.

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

Ответ 5

Поскольку Bash и большинство других сред оболочки UNIX считают 0 успешным, а -x - системной, а x - определяемой пользователем ошибкой.

Ответ 6

Вероятно, есть куча забытой истории, относящейся ко временам, когда все было написано в asm. В общем, гораздо легче проверить нуль, чем для других конкретных значений.

Ответ 7

Возможно, я ошибаюсь, но я думаю, что это в основном по историческим причинам (истерические изюминки?). Я считаю, что K & R C (pre-ANSI) не имел типа void, поэтому логичный способ написать функцию, которая не возвращала ничего интересного, состояла в том, чтобы вернуть ее.

Конечно, кто-то здесь меня исправит, если я ошибаюсь...:)

Ответ 8

Я понимаю, что это связано с поведением системных вызовов.

Рассмотрим системный вызов open(); если он успешный, он возвращает неотрицательное целое число, которое является файловым дескриптором, который был создан. Однако на уровне ассемблера (где есть специальная, не-C-команда, которая ловутся в ядро), когда возвращается ошибка, она возвращается как отрицательное значение. Когда он обнаруживает возврат ошибки, оболочка кода C вокруг системного вызова сохраняет отрицательное значение в errno (поэтому errno имеет положительное значение), а функция возвращает -1.

Для некоторых других системных вызовов отрицательный код возврата на уровне ассемблера по-прежнему отрицается и помещается в errno, а -1 возвращается. Однако эти системные вызовы не имеют особого значения для возврата, поэтому для указания успеха был выбран нуль. Очевидно, что существует большое количество системных вызовов, но большинство из них могут соответствовать этим соглашениям. Например, stat() и его родственники возвращают структуру, но указатель на эту структуру передается как входной параметр, а возвращаемое значение - 0 или -1. Даже signal() управляет им; -1 был SIG_DFL, а 0 - SIG_IGN, а другие значения были указателями на функции. Существует несколько системных вызовов без возврата ошибки - getpid(), getuid() и т.д.

Этот механизм с нулевым показателем успеха затем был эмулирован другими функциями, которые на самом деле не были системными вызовами.

Ответ 9

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

Ответ 10

Потому что 0 - false и null в C/С++, и вы можете сделать короткие сокращения, когда это произойдет.

Ответ 11

Это связано с тем, что при использовании из оболочки UNIX команда, которая возвращает 0, указывает на успех.

Любое другое значение указывает на сбой. Как говорит Пол Беттс, положительные и отрицательные значения указывают, где ошибка, вероятно, возникла, но это только соглашение, а не абсолютное. Пользовательское приложение может возвращать отрицательное значение без каких-либо плохих последствий (кроме того, что оно указывает оболочке, что приложение не удалось).

Ответ 12

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

Рассмотрим:

if ( somefunc() ) {
   // handle error
}

намного чище, чем:

if ( !somefunc() ) {
   // handle error
}

или

if ( somefunc() == somevalue ) {
   // handle error 
}

Ответ 13

Этот аргумент распадается, поскольку: BOOL isTrue = TRUE; или boolean isTrue = true; isTrue = 1 Все, кроме 1, считается FALSE (включая 0).