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