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と等しいかどうかを判断するようです。trueexpr_valtrue

私の質問は、なぜコードが に対してそのようなテストを追加するのかということresultです

result > LONG_MAX / 10

連続オーバーフローを判断するのに十分ですか?そして、それが常に有効なデジタル値であることに関係なくresult == 1result == 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値が の場合result、がオーバーフローしないため、214748364もチェックする必要があるためです。digval19

于 2012-10-26T03:21:46.043 に答える