我的strtol函数在溢出转换期间无法设置errno。
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <getopt.h>
#include <errno.h>
#include <stdlib.h>
int main(int argc, char **argv) {
errno = 0;
int e = strtol("1000000000000000", NULL, 10);
printf("%d %d\n", errno, e);
return 0;
}
返回
0 -1530494976
我做错了什么?
编译器
gcc (Ubuntu 4.9.2-10ubuntu13) 4.9.2
选项
gcc -Wall -std=gnu99 -O2
答案 0 :(得分:5)
strtol()
的实施没有任何问题,但是您的代码已经存在。
此函数的返回类型为long
(请参阅尾随l
),显然值1000000000000000
可由long
整数类型表示。但是,返回值已分配给e
,其类型为int
,无法表示此值。然后发生的是实现定义。
因此,将int e
更改为long e
,将"%d %d\n"
更改为"%d %ld\n"
。如果您想将其保留为int
,那么您必须自己检查该值是否超出其可表示值的范围:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <limits.h> // for INT_{MIN,MAX}
int
main(void)
{
errno = 0;
long f = strtol("1000000000000000", NULL, 10);
if (errno == ERANGE) {
puts("value not representable by long (or int)");
} else if (f < INT_MIN || f > INT_MAX) {
puts("value not representable by int");
} else {
int e = f;
printf("%d\n", e);
}
}
答案 1 :(得分:0)
你做得很好,但你没有检查errno
的{{1}}值,而是检查strtol
....不明白让我解释一下......
在printf()
语句之后,您必须先保存errno的值。因为在此声明之后,您将调用同样设置long f = strtol("1000000000000000", NULL, 10);
的{{1}}语句。
printf()
所以在这个声明中&#34; errno&#34;给出errno
的错误指示而不是printf("errno is: %d\n", errno);
...这样做可以保存&#34;错误&#34;在调用任何库函数之前,因为大多数库函数都与&#34; errno&#34;进行交互。
正确使用是:
printf()
现在检查一下。它肯定会提供正确的输出......还有一件事要将此strtol()
转换为一些有意义的字符串来表示错误。使用long f = strtol("1000000000000000", NULL, 10);
int saved_error = errno; // Saving the error...
printf("errno is: %d\n", saved_error);
功能为:
errno
strerror()
是正确的,但这更通用。
答案 2 :(得分:-1)
似乎Microsoft [1]和Apple [2]实现都将errno
的设置注释掉了。
[1] http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/strtol.c.htm
[2] http://www.opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/libkern/strtol.c