无符号整数数组怎么可以包含负整数

How is it that an unsigned integer array can contain a negative integer?

本文关键字:包含负 整数 数组 无符号整数      更新时间:2023-10-16

我写这段代码只是为了看看如果我把一个负整数放入一个无符号整数数组中会发生什么。

#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

存在整数溢出。这是原因(数字转换为无符号 int)

 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
当你

这样做时(假设无符号的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]等于不适合导致8 uint32_t 0x1 0000 00084294967304

对于有符号整数,最后一位用于保存符号值。因此,在您的情况下,当您将负整数分配给无符号整数时,将使用最后一位来表示数字而不是符号值。

负数通常以 2 的补码形式表示。所以

11111110  is represented as −1 if signed 
11111110  is represented as 254 if unsigned

-2转换为unsigned int会产生值4294967294(因为在您使用的C++实现中unsigned int为 32 位)。

unsigned int算术是模4294967296(或一般UINT_MAX+1)进行的。因此在unsigned int中,4 + 4 + 2 + 4294967294是8。

从技术上讲,根据标准,这不称为"溢出",因为标准将结果定义为仅取决于UINT_MAX的值。溢出是有符号整数算术超出其边界时的未定义行为。

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

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

例如:

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