一个未签名的整数数组如何包含负整数?

4

我编写了这段代码,只是为了看看将负整数放入无符号整数数组中会发生什么。

#include <iostream>

int main()
{
    using namespace std;

    unsigned int array[4];
    array[0]=4;
    array[1]=4;
    array[2]=2;
    array[3]=-2;

    cout << array[0] + array[1] + array[2] + array[3] << endl;

    unsigned int b;
    b=-2;
    cout << b <<endl;

    return 0;
}

我原本期望在这两种情况下都会发生整数溢出。然而,只有第二种情况实际上发生了。在第一种情况下,一切都表现得像是一个普通的整数数组,而不是无符号整数数组。那么到底是什么导致了这种异常行为呢?我的编译器是gcc 4.8,如果有任何重要性,请告知。谢谢你的帮助。编辑:以下是我的电脑上的输出结果。

8
4294967294

预期输出是什么,实际输出又是什么? - Kristian Duske
1
整数溢出确实会发生。只是它恰好是你满意的那种类型。这并不保证可行,仅仅是常见的情况。 - Hans Passant
2
实际上,我非常确定无符号溢出和有符号转无符号的规则是这样定义的:第一个结果保证为8,第二个结果保证比最大无符号整数小1。只有有符号溢出会表现得很疯狂。 - user2357112
C++中的无符号算术运算是模2^N,这是有保障的。 - MSalters
如果您输出array[0]等的实际值而不仅仅是它们的总和,那么这将变得更加清晰。 - starsplusplus
显示剩余2条评论
6个回答

8

发生了整数溢出。原因是(这些数字被转换为无符号整型)

 1111 1111 1111 1111 1111 1111 1111 1110 // -2
+0000 0000 0000 0000 0000 0000 0000 0100 //+ 4
-------------------------------------------
 0000 0000 0000 0000 0000 0000 0000 0010 //= 2
+0000 0000 0000 0000 0000 0000 0000 0100 //+ 4
-------------------------------------------
 0000 0000 0000 0000 0000 0000 0000 0110 //= 6
+0000 0000 0000 0000 0000 0000 0000 0010 //+ 2
-------------------------------------------
 0000 0000 0000 0000 0000 0000 0000 1000 //= 8 -> the result

1
-2转换为unsigned int会得到值4294967294(因为您使用的C++实现中unsigned int是32位)。 unsigned int算术运算按照模4294967296(或一般情况下的UINT_MAX+1)进行。因此,在unsigned int中,4 + 4 + 2 + 4294967294等于8。
从技术上讲,根据标准,这并不被称为“溢出”,因为标准仅定义结果取决于UINT_MAX的值。当有符号整数算术超出其范围时,溢出是未定义的行为。

1
对于有符号整数,最后一位用于保存符号值。因此,在您的情况下,当您将负整数分配给无符号整数时,最后一位被用来表示数字而不是符号值。
负数通常以2的补码形式表示。所以
11111110  is represented as −1 if signed 
11111110  is represented as 254 if unsigned

1
当你执行以下操作时(假设unsigned int是uint32_t):
array[0] = 4;
array[1] = 4;
array[2] = 2;
array[3] = -2; // You store 4294967294 here

这里的array[0] + array[1] + array[2] + array[3]等于4294967304,无法适应一个uint32_t 0x1 0000 0008,结果为8


0

对于有符号整数,第31位被视为符号位(假设整数大小为4字节)。对于无符号整数,根本没有符号位,即每个位都对绝对值有贡献


0

您看到的是(定义)无符号整数溢出的结果。您的-2值变成了一个非常大的无符号整数,当加上另一个无符号整数时,会导致溢出(结果大于最大可能的unsigned int值),从而导致结果比另一个无符号整数小2。

例如:

unsigned int a = -2;
unsigned int b = 4;
unsigned int c = a + b; // result will be 2!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接