简体   繁体   中英

Conversion from long to short error

I have the following code:

int main()
{
   short s(0);
   long l(10);

   s += static_cast<short>(l);
}

I'm compiling this with g++ and I get the following error:

..\src\main.cpp:6:7: warning: conversion to 'short int' from 'int' may alter its value [-Wconversion]

I absolutely have no idea why this is happening, as I thought that "static_cast" permitted to avoid this king of warnings.

Thanks for any help provided.

Integral promotion of short is required, so widening is unavoidable, however if you perform a static_cast you'll cast the result back to a short

In a nutshell:

  • you're performing a short = short + short
    • (the static_cast of the long made the second value a short )
  • Integral promotion happens before the operands are checked for type
    • so you'll get short = int + int
  • implicit conversion of the resulting int to short creates a warning

From [expr]:

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 , which are defined as follows:
...
Otherwise, the integral promotions (7.6) shall be performed on both operands. Then the following rules shall be applied to the promoted operands
- If both operands have the same type, no further conversion is needed.

From [conv.prom]

A prvalue of an integer type other than bool , char16_t , char32_t , or wchar_t whose integer conversion rank (7.15) 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 .

And indeed short has a lower rank than int :

From [conv.rank]

The rank of a signed integer type shall be greater than the rank of any signed integer type with a smaller size.

For performing the cast (to make the warning go away), see Richard Crittenden's comments on the OP or Nathan Oliver's answer

Even though you are casting l to a short you still have another conversion that is getting in the way. When you do

 s += static_cast<short>(l);

[expr.ass]/7 says it is the same as

s = s + static_cast<short>(l)

And this transformation is what is giving you the int in the warning you receive.

The reason for this is the built in operators don't exist for types smaller than int . Since both types are short they are converted to int which gives you an int for the result and now you are trying to assign that int to a short which could overflow. To workaround this you can use

s = static_cast<short>(s + l);

which converts the result to a short and then does the assignment.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM