Does multiplying unsigned short cause undefined behaviour?

限于喜欢 提交于 2019-12-21 10:46:36

问题


As a follow-up to "https://stackoverflow.com/questions/33732041/why-static-castunsigned-intushrt-maxushrt-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.


回答1:


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.




回答2:


When you multiply unsigned short * unsigned short then there is an implicit conversion and the value is casted to int in C++11. The documentation says:

Prvalues of small integral types (such as char) may be converted to prvalues of larger integral types (such as int). In particular, arithmetic operators do not accept types smaller than int as arguments

So it will result in an Undefined behavior.



来源:https://stackoverflow.com/questions/33732489/does-multiplying-unsigned-short-cause-undefined-behaviour

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!