3

即使字符串转换成功,测试也会errno返回一个指示错误的值:

#include <stdlib.h>
#include <sys/errno.h>

const char* numberString = "7";
char* endPtr;
errno = 0;
long number = strtol(numberString, &endPtr, 10);
NSLog(@"%ld", number);
if (errno) {
    perror("string to integer conversion failed");
}

输出是(在模拟器上,iOS 7)

$ 2014-05-22 09:27:32.954 Test[2144:60b] 7
$ string to integer conversion failed: No such process

设备上的行为类似。

手册页在评论中strtol说:

返回值
strtol()、strtoll()、strtoimax() 和 strtoq() 函数返回转换结果,除非值会下溢或溢出。如果无法执行转换,则返回 0 并将全局变量 errno 设置为 EINVAL(最后一个功能不能在所有平台上移植)。如果发生上溢或下溢,则将 errno 设置为 ERANGE,并根据下表限制函数返回值。

目前还不清楚这对 iOS 究竟意味着什么。这里有什么见解吗?

编辑:

原来,函数调用NSLog确实 set errno。所以,@Mat 在他的回答和评论中说得很对,说“在errno调用不相关的函数后进行测试时,所有的赌注都被取消了(这里NSLog)。

4

1 回答 1

4

如果无法执行转换,则返回 0

你不是在那种情况下, 7 被退回。

如果发生上溢或下溢,... 根据下表对返回值进行钳位。

你也不是那种情况。

所以strtol没有失败。检查errno是没有意义的。记录在失败时设置errno的功能将在失败的情况下这样做。当没有失败发生时,值errno是“道德上”未定义的。不要检查它。

strtol不过是个特例。POSIX 需要以下内容:

errno如果成功,这些功能不应更改设置。

所以你的例子应该没​​问题。除了您在strtol调用和检查errno. 如果您 100% 确定该函数本身不会更改errno,或者调用可能设置它的另一个函数,那么在这种非常特殊的情况下您会没问题(记录的函数errno在成功的情况下不会更改 - 这不是规范)。显然情况并非如此。NSLog很可能会在某个时候使用一些系统调用,而那些(通常)不能保证不改变errno.

于 2014-05-22T07:47:25.003 回答