MistyD
MistyD

Reputation: 17223

understanding widening and narrowing conversions C++

I wanted to understand C++ types along with widening and narrowing conversions in a little bit more details (C++03 specific).I am aware that you cannot put multiple questions on a single question thread however all these questions are related to the same topic. Now I have the C++ types and ranges msdn

Now consider the following example:

int a = 35000;
short b;
b=a;

Now in the above example I know a is 4 bytes and b is 2 bytes. I am aware that a widening conversion increases precision where as a narrowing conversion decreases precision. The above example I believe would be a narrowing cast (since there is loss of data) 4 bytes is going into two bytes. However I get confused in certain cases what conversion is taking place is it widening or is it narrowing ? Are we suppose to look at the number of bytes of types to determine if it will be a widening or a narrowing conversion or are we suppose to look at ranges? Also I read that for narrowing conversion explicit casting is required however in this case the compiler did not point out any error and implicitly did the conversion which was wrong. Any suggestions on why that happened ? I am using VS2010

Upvotes: 3

Views: 3429

Answers (2)

Jerry Coffin
Jerry Coffin

Reputation: 490218

Narrowing doesn't necessarily depend solely on size. For example, a long long and a double, are both normally the same size (64 bits apiece). Nonetheless, conversion in either direction is a narrowing conversion, because information can be lost either way. The same can happen with a conversion between a signed integer type and an unsigned integer type of the same size--conversion in either direction can lose information (i.e., result in a value that doesn't match the input) so both are considered narrowing conversions.

If you work solely within the same...class of types (e.g., all signed integers or all floating point), then you can use the size of the item to figure out whether a conversion will involve narrowing (in theory there might be times/situations where this was false, but it's true for the types provided by most hardware and compilers).

Also note that C++ does add some exceptions for conversions when the source is a literal, and the source value can be put in the destination without losing information, even though some values of the source type could lead to information loss.

For example, if I do something like float a = 3.5;, the literal 3.5 has type double, but since it's a literal and it can be converted to float without losing information, it's allowed even in places where narrowing conversions are prohibited (e.g., braced initialization lists).

Upvotes: 7

IdeaHat
IdeaHat

Reputation: 7881

For integral types, the precision is always 1. Widening conversion increases the range, narrowing conversion decreases the range.

http://msdn.microsoft.com/en-us/library/s3f49ktz.aspx

The range of a short is –32,768 to 32,767. your input, 3500 is bigger than that. What ends up happening is the number gets crammed into the smaller number of bytes, causing a wrap around error (b is negative). (The specifics of that have to do with complements of 2 and what not, but for your level it is suffice to say "you broke it, it don't work").

To avoid, compiler with -Wnarrowing or -Wall with gcc, or /Wall with the visual studio compiler (i don't actually know if /Wall will catch it though).

Upvotes: 0

Related Questions