Strtol在溢出转换时没有设置errno

时间:2015-08-19 20:10:36

标签: c

我的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

3 个答案:

答案 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)