c中整数的环绕

c中整数的环绕,c,integer-overflow,C,Integer Overflow,我已经用c语言编程很长时间了。但从未使用过发生整数环绕的程序。我知道如果integer分配了4个字节,那么integer的范围将变为-2147483648到2147483647。如果我们超过了极限,它就会卷起 我正在使用以下程序来了解环绕是如何发生的 #include <stdio.h> int main() { int n = 4, s = 2; for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j

我已经用c语言编程很长时间了。但从未使用过发生整数环绕的程序。我知道如果integer分配了4个字节,那么integer的范围将变为-2147483648到2147483647。如果我们超过了极限,它就会卷起

我正在使用以下程序来了解环绕是如何发生的

#include <stdio.h>

int main() {
int n = 4, s = 2;

for (int i = 0; i < n; ++i)
{
    for (int j = 0; j < n; ++j)
    {
        for (int k = 0; k < n; ++k)
        {
            s = 2 * s + 1;

        }
    }
}
printf("%d\n", s);
return 0;
}
#包括
int main(){
int n=4,s=2;
对于(int i=0;i
我使用gdb来找出变量s所取的值。我发现,当我们执行最里面的循环30次时,s的值变为负值,即-1073741825。然后,对于下一次迭代,它变为2147483647,对于第32次迭代,它变为-1

然后它将永远保持为-1。我的疑问是,为什么在值变为-1后不会发生环绕。我知道二进制中s的值都是1或十六进制中的FFFFFFFF。而且它不会永远改变(内部正在更新,但我们只能看到最后的32位,所以它是-1)。但是这次不会出现这种情况吗?它依赖于编译器吗?或者gcc只允许环绕一次?
任何形式的帮助都将不胜感激。谢谢

严格地说,有符号整数的溢出是不可能的。然而,在实践中,大多数实现使用2的整数补码表示法,而概括将按照您所描述的方式工作

记住这一点,让我们看看这里发生了什么

随着循环的进行,最终
s
的值将为1610612735。到目前为止,没有发生任何异常情况。现在我们乘2加1。此时,结果溢出。让我们看看这些数字的十六进制表示

1610612735d = 0101 1111 1111 1111 1111 1111 1111 1111 b = 0x5FFFFFFF
0x5FFFFFFF * 2 = 0xBFFFFFFE
0xBFFFFFFE + 1 = 0xBFFFFFFF
0xBFFFFFFE = 1011 1111 1111 1111 1111 1111 1111 1111 b = -1073741825d
从二进制的角度来看,乘以2相当于左移1。此操作将一个值移动到符号位,得到一个负值

在下一个操作中,再次乘以2溢出。这一次乘法将0移到符号位,在此之前有1,因此符号再次改变:

0xBFFFFFFF * 2 = 0x7FFFFFFE
0x7FFFFFFE + 1 = 0x7FFFFFFF
0x7FFFFFFF = 0111 1111 1111 1111 1111 1111 1111 1111 b = 2147483647
下一次迭代也会溢出:

0x7FFFFFFF * 2 = 0xFFFFFFFE
0x7FFFFFFE + 1 = 0xFFFFFFFF
0xFFFFFFFF = 1111 1111 1111 1111 1111 1111 1111 1111 b = -1
现在我们有-1。从现在开始,没有溢出:

-1 * 2 = -2
-2 + 1 = -1
这是同样的事情在十六进制:

0xFFFFFFFF * 2 = 0xFFFFFFFE
0xFFFFFFFE + 1 = 0xFFFFFFFF

正如你所看到的,将-1加倍,再加上1会再次得到-1,这就是为什么它不断重复。这也与2乘1的左移一致。

简短回答:只有无符号类型才能保证正确的换行。对于有符号类型,奇怪的事情可能会发生,因为它在技术上是未定义的。它不再更新,因为
2*(-1)+1=-1
“大多数实现都使用2的补码表示法来表示整数,而wrapparound将按照您所描述的方式工作。”这意味着2的补码机器将进行wrapparound。尽管这是一种常见的行为,但即使是带有2的补码机的兼容编译器,在各种情况下也可能/可能不会换行,因为它是未定义的行为。那些讨厌的新C编译器利用UB来优化代码。