是否乘以无符号短因子未定义行为? [英] Does multiplying unsigned short cause undefined behaviour?
问题描述
作为为什么static_cast< unsigned int>(USHRT_MAX * USHRT_MAX)产生正确的值?
我问自己如果促销所有类型code> int 到 int
执行算术运算可能会导致UB。
例如:
无符号短a = 0xFFFF;
unsigned short b = a * a;
无符号short被提升为 int
算术运算将导致:
无符号短a = 0xFFFF;
unsigned short b =(int)a *(int)a;
As (int)0xFFFF *(int)0xFFFF
导致溢出,并且有符号类型的溢出是UB:在 x,y
> x * y> INT_MAX :
>
这个问题专门针对 int
是32位和 short
是16位。
C ++ 11§3.9.1/ 4,完整报价:
已声明为
unsigned
的无符号整数应符合算术模2的规则 n 其中 是整数的特定大小的值表示中的位的数字
。
除了有关 unsigned
的略有误导的措辞这似乎适用于每个只涉及某个给定无符号类型的参数的算术表达式将产生模2 n 的结果。
但是,对于没有符号的低于 int
的转换级别,没有算术表达式:明显这种表达式中的所有参数都被转换最多为(1)至少 int
,或者取决于C ++实现的数字范围,最多为 unsigned int
因此, a * b
其中 a
和 b
是无符号short
值,(2)可以有正式未定义的行为。因为它不是无符号short
表达式。这是(在实践中)一个 int
表达式。
在其中注意正式UB,并且在实践中的8位字节和无符号短
最大值,可由 int
和普通二进制补码有符号整数表示,结果,当转换回 unsigned short
时,将会像是模运算范围 unsigned short
。这是因为在机器代码级别上的二进制补码只是以0为中心的范围的模运算。
(1)在实践中,通常使用一个8位每字节实现,其中 unsigned short
非常适合 int
范围内,因此在实践中我们讨论的转换最多为 int
。
(2)例如,对于16位无符号短
和32位 int
,(2 16 -1) 2 = 2 32 -2×2 < 2 31 -1,其中最后一个值是最大正< int
值。
As a follow-up to "Why static_cast<unsigned int>(USHRT_MAX*USHRT_MAX) yields correct value?"
I was asking myself if promoting all types (except some exceptions) with a lower rank than int
to int
to perform arithmetic operations might cause UB in some cases.
e.g.:
unsigned short a = 0xFFFF;
unsigned short b = a*a;
As unsigned short is promoted to int
for arithmetic operations this would result in:
unsigned short a = 0xFFFF;
unsigned short b = (int)a*(int)a;
As (int)0xFFFF*(int)0xFFFF
causes an overflow, and overflow of signed types is UB: Can multiplying two unsigned shorts x,y
cause undefined behaviour in the case that x*y > INT_MAX
UPDATE:
The question specifically aims at the case that int
is 32-bit and short
is 16-bit.
C++11 §3.9.1/4, full quote:
” Unsigned integers, declared
unsigned
, shall obey the laws of arithmetic modulo 2n where n is the number of bits in the value representation of that particular size of integer.
Apart from the slightly misleading wording about “declared unsigned
” this might seem to apply that every arithmetic expression that involve only argument of some given unsigned type, will yield a result modulo 2n for that type.
However, there are no arithmetic expressions at all for unsigned types of lower conversion rank than int
: all arguments in an apparent such expression are converted up to (1)at least int
, or depending on the number ranges of the C++ implementation, up to unsigned int
.
As a result, a*b
where a
and b
are unsigned short
values, (2)can have formally Undefined Behavior. Because it's not an unsigned short
expression. It's (in practice) an int
expression.
That said, with a reasonable compiler that doesn't introduce special casing where it notices formal UB, and with in-practice 8 bit bytes and unsigned short
max value that is representable by int
, and common two's complement signed integer representation, the result, when converted back down to unsigned short
, will be as if it was modular arithmetic in the range of unsigned short
. That's because two's complement, at the machine code level, is just modular arithmetic with a range centered on 0.
(1) In practice one will usually be using an 8 bits-per-byte implementation where the maximum value of unsigned short
fits well within the int
range, so in practice we're talking about a conversion up to int
.
(2) E.g., for 16-bit unsigned short
and 32-bit int
, (216−1)2 = 232−2×216+1 > 231−1, where the last value is the maximum positive int
value.
这篇关于是否乘以无符号短因子未定义行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!