无符号字符的减法运算

Posted

技术标签:

【中文标题】无符号字符的减法运算【英文标题】:Subtraction operation on unsigned char 【发布时间】:2014-01-29 04:18:45 【问题描述】:

我对 unsigned char 很好奇。我对 unsigned char 很好奇。我不小心对 unsigned char 进行了减法运算。我知道我不应该这样做。但我有点好奇一个特定的答案是怎么来的。任何人都可以在位级别上解释这一点吗?

unsigned char x = 150;
unsigned char y = 229;

unsigned char z = x - y;

最后我在调试过程中得到了 177 的 z

我在 Visual Studio 2008 中运行此代码。

【问题讨论】:

您确定您的代码中z 的类型是int,而不是unsigned char?如果是,请发布一个完整且可编译的示例来重现结果。 对不起,它是无符号字符。 【参考方案1】:

声明为无符号的无符号整数应遵守算术模 2^n 的定律,其中 n 是数字 该特定整数大小的值表示中的位数。

(C++11 标准,3.9.1.5)

在大多数平台上,unsigned char 是 8 位,因此结果是 150 - 229 mod 256 = -79 mod 256 = 177。

【讨论】:

【参考方案2】:

是的,如果你从150 中减去229,你最终会得到-79。但是,由于目标限制在0..255 范围内(假设为 8 位),因此它会环绕以确保保持该范围。因此,您基本上将256 添加到-79 以结束177

换句话说,9 - 10 会给你一个有符号值的-1,实际上给你一个 8 位的unsigned char255。同样,9 - 11 会给你254

这与加法没有什么不同,255 + 7 给你6,因为它在255 之后回绕到0

现在,规则比那个规则稍微复杂一点,因为可以将值提升为更大的数据类型,然后进行减法运算,然后截断结果。但是在数学上第一段是正确的。

【讨论】:

只有当z 的类型是unsigned char 时,你的推理才有效。最后一部分是完全错误的,算术运算符的操作数在执行算术运算之前进行整数提升。 Here's an example 这是如何工作的。 事实证明,z 毕竟是unsigned char,所以你答案的第一部分是正确的。最后一段仍然是错误的,因为积分促销仍然适用。算术运算符不会对小于int 的任何东西进行运算。在实践中,编译器可能会看到结果被放入 unsigned char 并且不执行提升,假设操作在 chars 上更有效。

以上是关于无符号字符的减法运算的主要内容,如果未能解决你的问题,请参考以下文章

有符号和无符号之间的减法,然后是除法

16位寄存器的SSE无符号/有符号减法

C 无符号整数减法、宏和类型转换

为啥 ~(true^true) 不正确?布尔运算符(否定)适用于“无符号字符”,但不适用于布尔值? (C++)

C语言中,64位无符号整型如何进行开方运算?

C语言中,64位无符号整型如何进行开方运算?