4

Possible Duplicate:
Integer summing blues, short += short problem

I have summarized my problem into following code snippet.I have two short vaiable and I am adding these two variable into another short variable,but I am getting compile time error.Why is it so?

 1.short x = 1, y = 1;
 2.short z = x + y;   

Compile time error at line 2 EDIT:

If short+short=int

then why int+int !=long
Community
  • 1
  • 1
santosh singh
  • 27,666
  • 26
  • 83
  • 129

6 Answers6

6

By specification short + short -> int. Do short z = (short)(x + y);

Best answer is given by Eric Lippert here: Integer summing blues, short += short problem

Community
  • 1
  • 1
Andrey
  • 59,039
  • 12
  • 119
  • 163
  • Although I knew this answer, I will admit that this specification always seemed kind of weird to me. What is the reason for specifying it like this? – JasCav Apr 13 '11 at 16:29
  • 1
    @Andrey, if @geek uses your suggestion it is possible to get an unhandled runtime error if x + y is too large to store as a short. – Cos Callis Apr 13 '11 at 16:30
  • It's strange.If short+short->int then int+int_>long? – santosh singh Apr 13 '11 at 16:31
  • @geek follow the link to find the best explanation that you will ever find. – Andrey Apr 13 '11 at 16:32
  • @Cos Callis and two `int`s can make a `long`. Do you write `int a, int b; long c = a + b;` If he picks domain for his numbers that he takes responsibility. – Andrey Apr 13 '11 at 16:33
  • 1
    @JasCav: Possibly it's because the CLR only has 32-bit stack registers (minimum). Therefore if you had a more complex expression like (x + y) / z * 2, the compiler would have to do extra work to shrink the result of (x + y) to 16 bits, and to shrink the result of (x + y) / z to 16 bits again. The designers of C# may have felt that was wasteful (and probably not useful behavior to the programmer) so they chose to define all arithmetic results as 32 bits minimum. – Qwertie Apr 13 '11 at 16:34
  • 1
    @Cos Callis, by default, arithmetic overflow does not produce an error in C#. And geek has a point, since int+int=int, not long. – Qwertie Apr 13 '11 at 16:36
  • int + int = LONG and is not the scenario he presents. The question is short + short, which can not sum to a value which overflows an int. – Cos Callis Apr 13 '11 at 16:37
  • 1
    No, by C# rules, int + int = int (and for that matter, int * int = int even though it can overflow an int fairly easily) – Qwertie Apr 13 '11 at 16:38
  • 1
    @Cos Callis it doesn't matter. I am following your logic. By the way you are incorrect about exception, you have to do in `checked` body. – Andrey Apr 13 '11 at 16:39
  • @paolo thanks, fixed. I treat Eric's answers as ultimate references :) – Andrey Apr 13 '11 at 16:49
  • @andrey same for me. As a fellow fan I've deleted the previous comment... – Paolo Falabella Apr 13 '11 at 17:10
  • The Original question is "why doesn't this compile". The answer is because adding two shorts returns an int. This requirement does not exist for Int in an Int + Int scenario, why Ask Anders, it can overflow. Still if you over flow and CAST as suggested you get a result of -2 rather than the desired value. – Cos Callis Apr 13 '11 at 18:04
2

There is no addition operator defined for short. The compiler will automatically convert those values to int to do the addition. Therefore, the type of the expression x + y will be int. When assigning an int expression to a variable of type short a cast is required. Like this:

short z = (short)(x + y);

NOTE The following information is usually unnecessary.

If you are concerned about overflows in a checked context, do this:

short z = unchecked((short)(x + y));

This is usually not necessary, though, since unchecked is the default setting for most (or all) C# compilers, and that setting is hardly ever changed. If the assignment appears inside a checked statement, then presumably the person writing the code knows what they're doing.

Jeffrey L Whitledge
  • 58,241
  • 9
  • 71
  • 99
  • 1
    @Cos Callis promoting your answer by downvoting others *correct* answers is not cool. – Andrey Apr 13 '11 at 16:36
  • @Cos Callis - I have updated my answer to address your objection. – Jeffrey L Whitledge Apr 13 '11 at 16:46
  • @Jeffrey The adding of "unchecked" will suppress the compiler error, but not the potential for problems if an overflow occurs, which is what the compiler error is trying to warn about. – Cos Callis Apr 13 '11 at 18:18
  • @Cos Callis- 1.It does not supress any compiler error. Modifying the checked/unchecked context of an expression controls whether an overflow condition in the calculation will raise a *runtime* exception. 2.The compiler error is not trying "warn" about anything (if it were, then it would be a compiler warning rather than an error). When the OP attempted to write `short z = x + y;`, then, presumably, they knew whether the addition of two short values and the assignment to a short variable made sense in the context of their application. Whether the programs logic is valid or not isn't the issue. – Jeffrey L Whitledge Apr 13 '11 at 18:26
  • @Jeffery it does both if you look to: http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k(UNCHECKED_CSHARPKEYWORD);k(TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV3.5%22);k(DevLang-CSHARP)&rd=true and notice the paragraph that reads: --- If the unchecked environment is removed, a compilation error occurs. The overflow can be detected at compile time because all the terms of the expression are constants. --- But you are still missing the point, @QWERTIE was right when he pointed out that C# won't produce and overflow error, but it does produce a result of (-2). – Cos Callis Apr 13 '11 at 18:36
  • Bottom line I stand behind my original answer that changing line 2 of the original question to: int z = x + y; is best because it will ALWAYS work. – Cos Callis Apr 13 '11 at 18:39
  • @Cos Callis - Constants are treated differently than variables in expressions. Since constant expressions are evaluated at compile-time, the overflow error occurs at compile-time. The question relates the addition of two variables. – Jeffrey L Whitledge Apr 13 '11 at 18:49
  • @Cos Callis - Do you also always store the addition of two ints in a long? – Jeffrey L Whitledge Apr 13 '11 at 18:49
  • @Jeffery the range of possible numbers is (by definition) a full order of magnitude greater for Ints(Int32) than it is for Shorts(Int16). I will always find it "safer" just accept that short + short = int and live with that than to worry about the possibility of int + int > int.maxValue. As somebody pointed out, at some point the developer is responsible for the domain of numbers in that particular case. You ably pointed out why the system does not coerce us to follow an int + int = long but does promote the short + short = int. – Cos Callis Apr 13 '11 at 18:56
2

This is documented behaviour

You need to cast short z = (short)(x + y);

Paolo Falabella
  • 24,914
  • 3
  • 72
  • 86
1

It's a "feature". Seriously, I posted a similar question to Microsoft regarding byte math a while back. I don't know if you can see my posting without logging in, but the reply was:

https://connect.microsoft.com/VisualStudio/feedback/details/92880/byte-bit-wise-and-math-requires-work-around#details

It is by design, and is due to the rules around numeric promotion, and there not being predefined operators for byte. (It tripped me up too, when I first encountered it. ;-)

Here is relevant portion of the Language Specification. Though the example is for multiply, the same holds for plus.

hope it helps

Santosh

14.2.6 Numeric promotions This subclause is informative. Numeric promotion consists of automatically performing certain implicit conversions of the operands of the predefined unary and binary numeric operators. Numeric promotion is not a distinct mechanism, but rather an effect of applying overload resolution to the predefined operators. Numeric promotion specifically does not affect evaluation of user-defined operators, although user-defined operators can be implemented to exhibit similar effects. As an example of numeric promotion, consider the predefined implementations of the binary * operator: int operator *(int x, int y); uint operator *(uint x, uint y); long operator *(long x, long y); ulong operator *(ulong x, ulong y); void operator *(long x, ulong y); void operator *(ulong x, long y); float operator *(float x, float y); double operator *(double x, double y); decimal operator *(decimal x, decimal y); When overload resolution rules (§14.4.2) are applied to this set of operators, the effect is to select the first of the operators for which implicit conversions exist from the operand types. [Example: For the operation b * s, where b is a byte and s is a short, overload resolution selects operator *(int, int) as the best operator. Thus, the effect is that b and s are converted to int, and the type of the result is int. Likewise, for the operation i * d, where i is an int and d is a double, overload resolution selects operator *(double, double) as the best operator. end example] End of informative text.

Jim
  • 2,034
  • 1
  • 22
  • 43
0

Two Shorts CAN make an INT so it is not possible to implicitly cast X + Y as a short. change it to

int z = x + y; 

and it will run

Based on comments I am adding the following code sample to clear up some issues:

    class BasicMath
   {

         short s_max = short.MaxValue; // the max value for a short (or an Int16) is 32767
         int i_max = int.MaxValue; // the max value for an int (or an Int32) is 2,147,483,647
         long l_max = long.MaxValue; // the max value for a long (Int64) is 9,223,372,036,854,775,807

      public int AddingShorts(short x, short y)
      {


         short addedvalues = (short)(x + y);
         //yes this will compile and run, but the result of 32767 + 32767 = -2

         //short addedShorts = (short)s_max + s_max;

         int addedInts = i_max + i_max;
         //No, this doesn't require a cast, but it also achieves the spectaclar result of 
         //2,147,483,647 + 2,147,483,647 = -2
         return addedvalues;
         //casting a short to an int works implicitly (note the return type here is int, not short)
         //still if you pass in values of exceeding 32767 you will end up with -2 because attempting
         //cast as a short a value of greater than 32767 results in -2. 
      }


   }

Why does the compiler require short + short to be (at least) an int and does not apply the same rule to ints? Ask Anders... The fact is this is 'the rule the compiler enforces' on all days ending in "Y"

If you attempt to simply CAST the sum of two shorts as a short, yes it will compile but it is also prone to produce a result you will not be happy with.

Cheers

Cos Callis
  • 5,051
  • 3
  • 30
  • 57
  • 2
    This answer is incorrect. For example, two ints can be added to make a long, but that does not cause a compile-time error. The reason for the error in the case of short is, ultimately, because there is no short addition operator defined. – Jeffrey L Whitledge Apr 13 '11 at 16:36
  • If you noticed question is stated as **"Why is it so?"**. Two `int` doesn't produce `long`, but two `short` do. – Andrey Apr 13 '11 at 16:37
  • The reason for these rules is very clear (and it is not to avoid overflows on short values). The CLR was designed to run on machines with a register size of 32 bits. Doing math on a short requires extra truncation steps between every operation. Rather than implicity kill the performance of every application that uses shorts, they decided to explicity encourage the use of higher-performance types in the C# language by requiring the calculations to be done in ints. If a program requires the logic of shorts, then casts may always be inserted to do the truncation (at the expense of performance). – Jeffrey L Whitledge Apr 13 '11 at 18:34
  • @Jeffrey, I hadn't thought about it that way, interesting point. Still this suggests it is better to just accept that short + short = int rather than trying to coerce the result into a short, because an int will work 100% of the time for any valid shorts being summed. – Cos Callis Apr 13 '11 at 18:44
0

That's because the sum of two Int16s is an Int32 so you might need a cast:

 short z = (short)(x + y); 
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928