哪个“ C”实现未对有符号整数实现模运算?

问题描述 投票:-2回答:1

参考C11 draft, section 3.4.3C11 draft, section H.2.2,我正在寻找实现除带符号整数的模运算以外的行为的“ C”实现。

特别是,我正在寻找默认行为的实例,这可能是由于底层计算机体系结构所致。

这是一个代码示例和终端会话,它说明有符号整数的模算术行为:

overflow.c

#include <stdio.h>
#include <limits.h>

int main(int argc, char *argv[])
{
    int a, b;
    printf ( "INT_MAX = %d\n", INT_MAX );
    if ( argc == 2 && sscanf(argv[1], "%d,%d", &a, &b) == 2 ) {
        int c = a + b;
        printf ( "%d + %d = %d\n", a, b, c );
    }
    return 0;
}

终端会议:

$ ./overflow 2000000000,2000000000
INT_MAX = 2147483647
2000000000 + 2000000000 = -294967296
c undefined-behavior modulo integer-overflow
1个回答
0
投票

即使使用像gcc这样的“熟悉的”编译器,在x86这样的“熟悉的”平台上,有符号整数溢出也可以执行“显而易见的”二进制补码环绕行为以外的其他操作。

以下是一个有趣(或可能令人恐惧)的例子(see on godbolt:]

#include <stdio.h>

int main(void) {
    for (int i = 0; i >= 0; i += 1000000000) {
        printf("%d\n", i);
    }
    printf("done\n");
    return 0;
}

天真,您希望它输出

0
1000000000
2000000000
done

并且使用gcc -O0,您将是对的。但是使用gcc -O2,您会得到

0
1000000000
2000000000
-1294967296
-294967296
705032704
...

无限期继续。算术是二进制补码环绕,但是,循环条件中的比较似乎出了点问题。

实际上,如果您查看程序集输出,您会发现gcc完全省略了比较,并使循环无条件地变为无限。可以推断出,如果没有溢出,则循环永远不会终止,并且由于有符号整数溢出是未定义的行为,因此在这种情况下也可以使循环不终止。因此,最简单和“最有效”的法律代码永远不会终止,因为这避免了“不必要的”比较和有条件的跳转。

根据您的观点,您可能认为这很酷,也可能很反常。

© www.soinside.com 2019 - 2024. All rights reserved.