5

我正在尝试使用errno来检测我是否执行了导致溢出的操作。然而,虽然我写了一个故意溢出的函数,但它errno == ERANGE是错误的。这里发生了什么?

这是代码:

#include <stdio.h>
#include <errno.h>

int main(int argc, char* argv[]) {
    unsigned char c = 0;
    int i;

    for (i = 0; i< 300; i++) {
        errno = 0;
        c = c + 1;
        if (errno == ERANGE) {// we have a range error
            printf("Overflow. c = %u\n", c);
        } else {
            printf("No error. c = %u\n", c);
        }
    }
    return 0;
}

我希望这会在我们将 1 添加到 255 时出现溢出错误,但没有错误。这是(截断的)输出:

No error. c = 245
No error. c = 246
No error. c = 247
No error. c = 248
No error. c = 249
No error. c = 250
No error. c = 251
No error. c = 252
No error. c = 253
No error. c = 254
No error. c = 255
No error. c = 0
No error. c = 1
No error. c = 2
No error. c = 3
No error. c = 4
No error. c = 5
No error. c = 6
No error. c = 7
No error. c = 8
No error. c = 9

有人可以解释为什么它没有检测到错误,以及我如何更改它或以其他方式制作一个可以检测我的值是否溢出的函数?注意:最终我想用long ints 来做这个,所以不可能简单地将它转换为更大的数据类型。

编辑:

从那以后,我发现了一些简单的函数来分别检测整数数据类型的加法和乘法溢出。它并不涵盖所有情况,但涵盖了很多情况。

乘法:

int multOK(long x, long y)
/* Returns 1 if x and y can multiply without overflow, 0 otherwise */
{
    long p = x*y;

    return !x || p/x == y;
}

签名补充:

int addOK(long x, long y)
/* Returns 1 if x and y can add without overflow, 0 otherwise */
{
    long sum = x+y;
    int neg_over = (x < 0) && (y < 0) && (sum >= 0);
    int pos_over = (x >= 0) && (y >= 0) && (sum < 0);
    return !neg_over && !pos_over;
}

无符号加法:

int unsignedAddOK(unsigned long x, unsigned long y)
/* Returns 1 if x and y can add without overflow, 0 otherwise */
{
    unsigned long sum = x+y;

    return sum > x && sum > y;
}
4

4 回答 4

2

除了其他人提出的观点之外errno,您正在使用unsigned char计数器。无符号类型被明确定义为环绕。换句话说,计算c=255; c=c+1;whenc是 8-bit不是错误unsigned char:结果总是0

于 2012-10-13T07:17:53.470 回答
2

Errno不是处理器设置的变量,它仅用于系统调用和一些标准函数来报告错误。

c < c + 1除了在每次循环迭代中验证 if 之外,我不知道任何检测您所问内容的技术。

编辑:经过一番研究,我发现了这个关于状态寄存器的维基百科,它是指示此类错误的 CPU 标志。

于 2012-10-13T01:15:13.687 回答
2

据我了解,errno是由功能设置的。除非您创建自己的函数,否则它不会检测到附加溢出错误。您可以测试以查看结果是否小于您的操作数之一。

#include <stdio.h>
#include <errno.h>

int main(int argc, char* argv[]) {
    unsigned char c = 0, result = 0;
    int i;

    for (i = 0; i< 300; i++) {
        result = c + 1;
        if (result < c) {// we have a range error
            printf("Overflow. c = %u\n", result);
        } else {
            c = result;
            printf("No error. c = %u\n", c);
        }
    }
    return 0;
}
于 2012-10-13T01:22:47.437 回答
1

整数溢出是未定义的行为。未定义的行为不是可检测的条件。是终局。一旦你调用了未定义的行为,你就不能得出关于程序状态的任何结论。

除此之外,errno与算术表达式无关。它用于报告库函数的错误。

于 2012-10-13T01:59:26.593 回答