哪个“C"实现不为有符号整数实现模运算? [英] Which "C" implementation(s) do not implement modulo arithmetic for signed integers?

查看:69
本文介绍了哪个“C"实现不为有符号整数实现模运算?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

参考 C11 草案,第 3.4.3 节C11 草案,H.2.2 部分,我正在寻找实现除有符号整数的模运算以外的行为的C"实现.

In reference to C11 draft, section 3.4.3 and C11 draft, section H.2.2, I'm looking for "C" implementations that implement behaviour other than modulo arithmetic for signed integers.

具体来说,我正在寻找这是默认行为的实例,这可能是由于底层机器架构造成的.

Specifically, I am looking for instances where this is the default behaviour, possibly due to the underlying machine architecture.

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

Here's a code sample and terminal session that illustrates modulo arithmetic behaviour for signed integers:

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

推荐答案

即使使用像 gcc 这样熟悉"的编译器,在像 x86 这样熟悉"的平台上,有符号整数溢出也可以做一些显而易见"的事情——补充环绕行为.

Even with a "familiar" compiler like gcc, on a "familiar" platform like x86, signed integer overflow can do something other than the "obvious" twos-complement wraparound behavior.

一个有趣(或可能令人恐惧)的例子如下(参见 Godbolt)::>

One amusing (or possibly horrifying) example is the following (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;
}

天真地,你会期望这个输出

Naively, you would expect this to output

0
1000000000
2000000000
done

使用 gcc -O0 你会是对的.但是使用 gcc -O2 你会得到

And with gcc -O0 you would be right. But with gcc -O2 you get

0
1000000000
2000000000
-1294967296
-294967296
705032704
...

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

continuing indefinitely. The arithmetic is twos-complement wraparound, all right, but something seems to have gone wrong with the comparison in the loop condition.

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

In fact, if you look at the assembly output, you'll see that gcc has omitted the comparison entirely, and made the loop unconditionally infinite. It is able to deduce that if there were no overflow, the loop could never terminate, and since signed integer overflow is undefined behavior, it is free to have the loop not terminate in that case either. The simplest and "most efficient" legal code is therefore to never terminate at all, since that avoids an "unnecessary" comparison and conditional jump.

根据您的观点,您可能认为这很酷或有悖常理.

You might consider this either cool or perverse, depending on your point of view.

(额外的信用:看看 icc -O2 做了什么并尝试解释它.)

(For extra credit: look at what icc -O2 does and try to explain it.)

这篇关于哪个“C"实现不为有符号整数实现模运算?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆