由于 strtoll, strtoull 返回值不能标识处理是否成功,所以需要借助 errno, 看下面这段代码:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char* argv[])
{
if (argc != 2)
{
printf("Usage: %s <number>\n", argv[0]);
return -1;
}
// errno was set to some value in somewhere, but we don't know.
errno = ERANGE;
char * pEnd;
long long value = strtoll(argv[1], &pEnd, 0);
if (ERANGE == errno)
printf("out of range\n");
else
printf("%lld\n", value);
printf("---------------\n");
// 1 -9223372036854775809 -9223372036854775808 9223372036854775807 9223372036854775808 9223372036854775807.2
return 0;
}
输入 1 时误判为越界,所以在用 errno 时必须调用放手动置 errno 为 0, 系统提供的 api 内部是不会去将 errno 置为 0 的。
因为 errno 是全局的,整个线程都生效,在一个很大的项目中,errno 在哪里不小心被置为非 0 值是极有可能的,因此,需要使用者非常小心。
正确的使用方法:
Since strtoul() can legitimately return 0 or LONG_MAX (LLONG_MAX for strtoull()) on both success and failure, the calling program should set errno to 0 before the call, and then determine if an error occurred by checking whether errno has a non-zero value after the call.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char* argv[])
{
if (argc != 2)
{
printf("Usage: %s <number>\n", argv[0]);
return -1;
}
// errno was set to some value in somewhere, but we don't know.
errno = ERANGE;
// [Note] You must set errno to 0 before calling.
int errnoBackup = errno;
errno = 0;
char * pEnd;
long long value = strtoll(argv[1], &pEnd, 0);
if (ERANGE == errno)
printf("out of range\n");
else
printf("%lld\n", value);
printf("---------------\n");
// 1 -9223372036854775809 -9223372036854775808 9223372036854775807 9223372036854775808 9223372036854775807.2
// [Note] Recovery errno.
errno = errnoBackup;
return 0;
}