【问题标题】:Assign a negative number to an unsigned int将负数分配给 unsigned int
【发布时间】:2019-10-07 18:42:20
【问题描述】:

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

#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 如何存储负数?是保存使用还是会产生未定义的行为?

我使用英特尔编译器 18.0.3。使用选项 -Wall 不会出现警告。

附言。我读过What happens if I assign a negative value to an unsigned variable?Why unsigned int contained negative number

【问题讨论】:

  • 不适用于 MSVC 2019:错误 C4146:一元减号运算符应用于无符号类型,结果仍无符号
  • 不安全而且没用。不要在这样的事情上浪费你的时间。
  • 请解释this 为何尚未回答您的第一个问题。对于您的问题 2 和 3:unsigned 不能存储负数,“保存”是什么意思?
  • iirc,解析器将:- 视为一元减号,22u 视为无符号。所以它是“二十二的一元减运算”。它被解析为-22u(负二十二)。我必须进行实验才能看到后果。
  • 22u 的类型为 unsigned int,正如预期的那样。 -22u 也有 unsigned int 类型,这可能违反直觉。结果是-22u 不是负数。

标签: c++ unsigned-integer


【解决方案1】:

unsigned int 如何存储负数?

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

是保存以供使用还是会产生未定义的行为?

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

相信结果是安全的。但是,它可能很脆。例如,如果将-22u100ull 相加,则得到UINT_MAX + 79(即,假设unsigned long long 是比unsigned 更大的类型,则为一个较大的值),它与可表示的78 模UINT_MAX + 1 一致在unsigned long long 中,但在unsigned 中无法表示。

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

【讨论】:

    【解决方案2】:

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

    这是将高位作为符号指示符或忽略它的计算。因此,任何“无符号”变量都可以包含有符号值,当无符号变量参与计算时,该值将转换为无符号形式。

    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.
    

    技术上有效,糟糕的编程。

    【讨论】:

    • 您将硬件的功能与 c++ 标准定义的功能混合在一起。在标准 c++ 中,有符号/无符号不仅是一种约定,而且是两种不同的类型。两种类型的硬件完全相同是另一回事
    • 他在问为什么他能够将无符号分配给有符号变量。尽管有不同的类型,但 C++ 将允许它,所以我试图解释原因。不同或没有不同的故事,这就是正在发生的事情,所以他必须理解它。
    • 是的,我的批评者是:什么是允许的,什么是有效的,与硬件的作用或值在内存中的实际表示方式无关。以溢出为例。它对无符号整数定义良好,但对有符号整数定义为 ub,即使对于硬件没有任何区别
    猜你喜欢
    • 2017-05-14
    • 1970-01-01
    • 2014-08-23
    • 1970-01-01
    • 2017-07-30
    • 1970-01-01
    • 2012-01-27
    • 1970-01-01
    • 2013-09-05
    相关资源
    最近更新 更多