c - 发生溢出,但 errno 不是 ERANGE。这是怎么发生的?

标签 c overflow errno

我正在尝试使用 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 int 来做这件事,所以不可能简单地将它转换成更大的数据类型。

编辑:

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

乘法:

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;
}

最佳答案

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

除了验证 c < c + 1 是否存在外,我不知道有什么技术可以检测您的要求。在每次循环迭代中。

编辑:经过一些研究,我找到了 this关于状态寄存器的维基百科,它是指示此类错误的 CPU 标志。

关于c - 发生溢出,但 errno 不是 ERANGE。这是怎么发生的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12869006/

相关文章:

html - html表格内的自动滚动文本

unix - 如何将UNIX中的errno转换为对应的字符串?

c - 双链表 - 无法编写为节点提供正确索引号的迭代器

c++ - 检测 32 位双字 + 双字进位/C++

c - 如何使用 PPAPI 插件或 PNACL 获取客户端计算机 MAC 地址

flutter - ListTile tileColor 溢出其容器外,Flutter

Python socket ConnectionResetError : [Errno 54] Connection reset by peer vs socket. 错误:[Errno 104] Connection reset by peer

c - 为什么 errno,当 POSIX 函数通过返回 -1 或 NULL 指示错误条件时

c - 为什么在尝试 "cat"我的字符设备驱动程序时收到错误消息?

C printf改变函数内部变量的内容