Why is unsigned short * unsigned short
converted to int
in C++11?
The int
is too small to handle max values as demonstrated by this line of code.
cout << USHRT_MAX * USHRT_MAX << endl;
overflows on MinGW 4.9.2
-131071
because (source)
USHRT_MAX = 65535 (2^16-1) or greater*
INT_MAX = 32767 (2^15-1) or greater*
and (2^16-1)*(2^16-1) = ~2^32
.
Should I expect any problems with this solution?
unsigned u = static_cast<unsigned>(t*t);
This program
unsigned short t; cout<<typeid(t).name()<<endl; cout<<typeid(t*t).name()<<endl;
gives output
t i
on
gcc version 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC) gcc version 4.8.2 (GCC) MinGW 4.9.2
with both
g++ p.cpp g++ -std=c++11 p.cpp
which proves that t*t
is converted to int
on these compilers.
Signed to unsigned conversion in C - is it always safe?
Signed & unsigned integer multiplication
https://bytes.com/topic/c-sharp/answers/223883-multiplication-types-smaller-than-int-yields-int
http://www.cplusplus.com/reference/climits
http://en.cppreference.com/w/cpp/language/types
Edit: I have demonstrated the problem on the following image.
As far as hardware goes, unsigned multiplication and signed multiplication are exactly the same (ignoring flags). When you multiply 11111111 and 11111111 , the result is 00000001 , regardless of whether the inputs are considered to mean -1 or 255.
Unsigned can hold a larger positive value and no negative value. Unsigned uses the leading bit as a part of the value, while the signed version uses the left-most-bit to identify if the number is positive or negative. Signed integers can hold both positive and negative numbers.
Both can store 256 different values, but signed integers use half of their range for negative numbers, whereas unsigned integers can store positive numbers that are twice as large.
There is no difference. unsigned and unsigned int are both synonyms for the same type (the unsigned version of the int type).
You may want to read about implicit conversions, especially the section about numeric promotions where it says
Prvalues of small integral types (such as
char)
may be converted to prvalues of larger integral types (such asint
). In particular, arithmetic operators do not accept types smaller thanint
as arguments
What the above says is that if you use something smaller than int
(like unsigned short
) in an expression that involves arithmetic operators (which of course includes multiplication) then the values will be promoted to int
.
It's the usual arithmetic conversions in action.
Commonly called argument promotion, although the standard uses that term in a more restricted way (the eternal conflict between reasonable descriptive terms and standardese).
C++11 §5/9:” Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions […]
The paragraph goes on to describe the details, which amount to conversions up a ladder of more general types, until all arguments can be represented. The lowest rung on this ladder is integral promotion of both operands of a binary operation, so at least that is performed (but the conversion can start at a higher rung). And integral promotion starts with this:
C++11 §4.5/1:” A prvalue of an integer type other than
bool
,char16_t
,char32_t
, orwchar_t
whose integer conversion rank (4.13) is less than the rank ofint
can be converted to a prvalue of typeint
ifint
can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of typeunsigned int
Crucially, this is about types, not arithmetic expressions. In your case the arguments of the multiplication operator *
are converted to int
. Then the multiplication is performed as an int
multiplication, yielding an int
result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With