将负数分配给无符号整数

Assign a negative number to an unsigned int

这段代码给出了有意义的输出

#include <iostream>

int main() {
    unsigned int ui = 100;
    unsigned int negative_ui = -22u;

    std::cout << ui + negative_ui << std::endl;

}

输出:

78

变量 negative_ui 存储 -22,但它是一个 unsigned int。 我的问题是为什么 unsigned int negative_ui = -22u; 有效。 unsigned int 如何存储负数?它是保存以供使用还是会产生未定义的行为?

我用的是intel编译器18.0.3。使用选项 -Wall 没有出现警告。

Ps。我已阅读What happens if I assign a negative value to an unsigned variable? and Why unsigned int contained negative number

Signed/Unsigned 是一个约定。它使用变量的最后一位(在 x86 int 的情况下,最后 31 位)。您存储在变量中的内容采用完整的位长度。

后面的计算就是把高位作为符号指示符或者忽略它。因此,任何"unsigned"变量都可以包含一个带符号的值,当无符号变量参与计算时,该值将被转换为无符号形式。

unsigned int x = -1; // x is now 0xFFFFFFFF.  
x -= 1; //  x is now 0xFFFFFFFE. 
if (x < 0) // false. x is compared as 0xFFFFFFFE.

int x = -1; // x stored as 0xFFFFFFFF
x -= 1; // x stored as 0xFFFFFFFE
if (x < 0) // true, x is compared as -2.

技术上有效,编程糟糕。

How can an unsigned int store a negative number?

没有。相反,它存储一个可表示的数字,该数字与该负数对所有可表示值的数量取模一致。对于大于最大可表示值的结果也是如此。

Is it save to be used or does this yield undefined behaviour?

没有UB。 Un有符号算术溢出定义明确。

相信结果是安全的。但是,它可能很脆。例如,如果您添加 -22u100ull,那么您会得到 UINT_MAX + 79(即假设 unsigned long long 是比 unsigned 更大的类型的大值)这是与 78 模 UINT_MAX + 1 一致,在 unsigned long long 中可表示,但在 unsigned.

中不可表示

注意有符号算术溢出未定义。