C:具有无符号操作数的一元减运算符行为
我似乎无法在 C 标准中找到完整定义具有无符号操作数的一元减运算符的行为的相关部分。
2003 C++ 标准(是的,C++,请耐心听我讲几行)在 5.3.1c7 中说:无符号数量的负数是通过从 2^n 中减去其值来计算的,其中 n 是位数
然而,1999 年的 C 标准不包含这样的显式语句,并且在 6.5.3.3c1,3 中也没有明确定义一元 - 行为6.5c4 中也没有。在后者中,它表示一些运算符(一元运算符 ~ 和二元运算符 <<、>>、&、^ 和 |、...)...返回值取决于整数的内部表示,并且有符号类型具有实现定义和未定义的方面。)
,其中排除了一元减号,事情似乎仍然模糊。
这个较早的问题引用了 K&R ANSI C 书的 A.7.4.5 节,内容如下:< code>无符号数量的负数是通过从提升类型的最大值中减去提升值并加一来计算的。
与上述书中引用等效的 1999 C 标准是什么?
6.2.5c9 说:涉及无符号操作数的计算永远不会溢出,因为无法由结果无符号整数类型表示的结果会以比结果可以表示的最大值大 1 的数为模进行减少类型。
是这样吗?还是我还缺少其他东西?
I can't seem to find the relevant parts in the C standard fully defining the behavior of the unary minus operator with unsigned operands.
The 2003 C++ standard (yes, C++, bear with me for a few lines) says in 5.3.1c7: The negative of an unsigned quantity is computed by subtracting its value from 2^n, where n is the number of bits in the promoted operand.
The 1999 C standard, however, doesn't include such an explicit statement and does not clearly define the unary - behavior neither in 6.5.3.3c1,3 nor in 6.5c4. In the latter it says Some operators (the unary operator ~, and the binary operators <<, >>, &, ^, and |, ...) ... return values that depend on the internal representations of integers, and have implementation-defined and undefined aspects for signed types.)
, which excludes the unary minus and things seem to remain vague.
This earlier question refers to the K&R ANSI C book, section A.7.4.5 that says The negative of an unsigned quantity is computed by subtracting the promoted value from the largest value of the promoted type and adding one
.
What would be the 1999 C standard equivalent to the above quote from the book?
6.2.5c9 says: A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.
Is that it? Or is there something else I'm missing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
是的,6.2.5c9 正是您要查找的段落。
Yes, 6.2.5c9 is exactly the paragraph that you looked for.
无符号操作数上的一元减运算符的行为与机器是否使用带符号数的补码算术无关。相反,给定
unsigned int x,y;
语句y=-x;
将导致y
接收它必须保留的任何值使 x+y 等于 0。如果x
为零,y
也将为零。对于x
的任何其他值,它将是UINT_MAX-x+1
,在这种情况下,x+y
的算术值将是 < code>UINT_MAX+1+(yy),当分配给无符号整数
时,将从中减去UINT_MAX+1
,结果为零。The behavior of the unary minus operator on unsigned operands has nothing to do with whether a machine uses two's-complement arithmetic with signed numbers. Instead, given
unsigned int x,y;
the statementy=-x;
will causey
to receive whatever value it would have to hold to makex+y
equal zero. Ifx
is zero,y
will likewise be zero. For any other value ofx
, it will beUINT_MAX-x+1
, in which case the arithmetic value ofx+y
will beUINT_MAX+1+(y-y)
which, when assigned to aunsigned integer
, will haveUINT_MAX+1
subtracted from it, yielding zero.在我所知道的每个实现中,负数的计算方式为 二进制补码...
..因此,负有符号整数和“负”无符号整数之间实际上没有物理差异 - 唯一的区别在于它们的解释方式。
所以在这个例子中...
...
b
和c
将包含完全相同的位。唯一的区别是b
被解释为 2^32-12(或 2^64-12),而c
被解释为“正常”-12。因此,无论“符号性”如何,都以完全相同的方式计算负数,并且无符号和有符号之间的转换实际上是无操作(并且永远不会导致溢出,因为某些位需要“剪切”) -离开”)。
In every implementation I know of, a negative is calculated as two's complement...
...so there is really no physical difference between negative signed and "negative" unsigned integers - the only difference is in how they are interpreted.
So in this example...
...the
b
andc
are going to contain the exact same bits. The only difference is thatb
is interpreted as 2^32-12 (or 2^64-12), whilec
is interpreted as "normal" -12.So, a negative is calculated in the exact same way regardless of "sign-ness", and the casting between unsigned and signed is actually a no-op (and can never cause an overflow in a sense that some bits need to be "cut-off").
这已经晚了,但无论如何......
C 声明(以一种相当困难的方式,正如其他答案中已经提到的那样)
任何无符号类型都是具有特定于类型的二进制表示形式
位数
无符号类型上的所有算术运算均已完成 (mod 2^N), 'mod'
是模数的数学定义,“N”是
用于表示类型的位数。
应用于无符号类型的一元减运算符的行为就好像该值已提升为下一个更大的有符号类型,然后取反,然后再次转换为无符号并截断为源类型。 (这是一个轻微的简化,因为所有类型的位数少于“int”时都会发生整数提升,但我认为它已经足够接近了。)
某些编译器在将一元减号应用于无符号类型时确实会发出警告,但是这个仅仅是为了程序员的利益。恕我直言,该构造定义明确且可移植。
但如果有疑问,请不要使用一元减号:写“0u - x”而不是“-x”,一切都会好起来的。任何像样的代码生成器都会从中创建一个否定指令,除非完全禁用优化。
This is late, but anyway...
C states (in a rather hard way, as mentioned in other answers already) that
any unsigned type is a binary representation with a type-specific
number of bits
all arithmetic operations on unsigned types are done (mod 2^N), 'mod'
being the mathematical definition of the modulus, and 'N' being the
number of bits used to represent the type.
The unary minus operator applied to an unsigned type behaves as if the value would have been promoted to the next bigger signed type, then negated, and then again converted to unsigned and truncated to the source type. (This is a slight simplification because of integer promotion happens for all types that have fewer bits than 'int', but it comes close enough I think.)
Some compilers do indeed give warnings when applying the unary minus to an unsigned type, but this is merely for the benefit of the programmer. IMHO the construct is well-defined and portable.
But if in doubt, just don't use the unary minus: write '0u - x' instead of '-x', and everything will be fine. Any decent code generator will create just a negate instruction from this, unless optimization is fully disabled.