0

最近我正在阅读 Glibc(2.16) 最新版本的源代码。在上时strtol,我得到了以下代码

/* some other code ... */
while (*nptr >= '0' && *nptr <= '9') {
    unsigned long int digval = *nptr - '0';
        if (result > LONG_MAX / 10 ||
            (sign > 0 ? result == LONG_MAX / 10 && digval > LONG_MAX % 10
                : (result == ((unsigned long int) LONG_MAX + 1) / 10 &&
                      digval > ((unsigned long int) LONG_MAX + 1) % 10))) {
                        errno = ERANGE;
                        return sign > 0 ? LONG_MAX : LONG_MIN;
                }
                result *= base;
                result += digval;
                ++nptr;
}

判断ERANGE错误的代码可能看起来很难阅读,为了更清楚,我这样重新编码

unsigned long int 
is_overflow(unsigned long int result, int sign, int digval) {
    if (result > LONG_MAX / 10) {
        goto error;
    }

    if (sign > 0) {
        if (result == LONG_MAX / 10 && digval > LONG_MAX % 10)
            goto error:
    } else {
        if (result == ((unsigned long int) LONG_MAX + 1) / 10 &&
                    digval > ((unsigned long int) LONG_MAX + 1) % 10)
                    goto error;
    }

error: 
    errno = ERANGE;
    return sign > 0 ? LONG_MAX : LONG_MIN;
}

我编写了一些代码来测试 long-if 语句:

#include <stdio.h>
#define LONG_MAX 2147483647L
int main() {
        int sign = 0;
        int expr_val = 0;
        int digval = '2';

        /* without any modification */
        expr_val = LONG_MAX / 10 && digval > LONG_MAX % 10;
        printf("%d\n", expr_val);

        expr_val = (unsigned long int) LONG_MAX + 1) / 10 &&
                digval > ((unsigned long int) LONG_MAX + 1) % 10;
        printf("%d\n", expr_val);

        return 0;
}

这些 glibc 源代码好像判断是否result等于true,因为expr_val总是等于true

我的问题是为什么代码添加这样的测试result,是

result > LONG_MAX / 10

足以判断连续溢出?result == 1并且无论result == 0它始终是有效的数字值,作者为什么要这样做?

4

1 回答 1

3
if (result == LONG_MAX / 10 && digval > LONG_MAX % 10)

方法

if ((result == LONG_MAX / 10) && (digval > LONG_MAX % 10))

并不是

if (result == (LONG_MAX / 10 && digval > LONG_MAX % 10))

result > LONG_MAX / 10仅检查是不够的,因为例如使用您的值LONG_MAX,如果result214748364,那么我们还需要检查digval,因为1不会溢出,但9会溢出。

于 2012-10-26T03:21:46.043 回答