Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is unsigned short (multiply) unsigned short converted to signed int? [duplicate]

Tags:

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.


Usefull resources:

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.

enter image description here

like image 662
Slazer Avatar asked Nov 16 '15 08:11

Slazer


People also ask

Can we multiply signed and unsigned numbers?

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.

Why do we need signed and unsigned integer?

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.

Can signed and unsigned integers store the same number of values?

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.

Is unsigned the same as unsigned int?

There is no difference. unsigned and unsigned int are both synonyms for the same type (the unsigned version of the int type).


2 Answers

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 as int). In particular, arithmetic operators do not accept types smaller than int 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.

like image 192
Some programmer dude Avatar answered Oct 03 '22 08:10

Some programmer dude


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, or wchar_t whose integer conversion rank (4.13) is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned 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.

like image 38
Cheers and hth. - Alf Avatar answered Oct 03 '22 08:10

Cheers and hth. - Alf