Первый фрагмент кода просто неверен, и я объясню почему позже, но сначала нам понадобится некоторая предыстория.
errno
- это локальная переменная потока. Он устанавливается в ненулевое значение, когда системный вызов или определенные библиотечные функции терпят неудачу. Он остается неизменным при успешном выполнении системного вызова. Таким образом, он всегда содержит номер ошибки последнего неудачного вызова.
Это означает, что у вас есть два варианта. Либо установите errno
в 0 перед каждым вызовом, либо используйте стандартную идиому для errno
. Вот псевдокод стандартной идиомы
if ( foo() == some_value_that_indicates_that_an_error_occurred )
then the value in errno applies to foo
else
foo succeeded and the errno must be ignored because it could be anything
Большинство программистов будут использовать стандартную идиому, потому что установка errno
в 0 перед каждым системным вызовом раздражает и повторяется. Не говоря уже о том, что вы можете забыть установить errno
в 0 в том месте, где это действительно важно.
Вернемся к первому фрагменту кода. Это неверно, потому что от strtol
не возвращается значение, однозначно указывающее на сбой strtol
. Если strtol
возвращает LONG_MAX
, возможно, произошла ошибка или строка действительно содержала число LONG_MAX
. Невозможно узнать, был ли вызов strtol
успешным или неудачным. Это означает, что стандартная идиома (которую пытается реализовать первый фрагмент кода) не может использоваться с strtol
.
Чтобы правильно использовать strtol
, вам нужно установить errno
в 0 перед вызовом, например
errno = 0;
result = strtol( buffer, &endptr, 10 );
if ( errno == ERANGE )
{
// handle the error
// ERANGE is the only error mentioned in the C specification
}
else if ( endptr == buffer )
{
// handle the error
// the conversion failed, i.e. the input string was empty,
// or only contained whitespace, or the first non-whitespace
// character was not valid
}
Обратите внимание, что некоторые реализации определяют другие ненулевые значения для errno
. Подробности см. На соответствующей странице руководства.
person
user3386109
schedule
18.03.2016
LONG_MAX/LONG_MIN
, иERANGE
. Помимо того факта, что на странице руководства это показано в качестве примера. Единственный разумный вариант использования, который я могу придумать, - это различать переполнение и потерю значимости. Мне тоже было бы интересно узнать, есть ли другие причины. - person kaylum   schedule 18.03.2016errno != 0 && result == 0
. Хотя, честно говоря, я не уверен, что могло вызвать это, потому что если strtol возвращает 0, то я уверен, что strtol не устанавливает errno ни на что, если изначально он был установлен в ноль. - person Luis Averhoff   schedule 18.03.2016if(errno)
- person chux - Reinstate Monica   schedule 18.03.2016