整数蓝色,短+ +短问题

Moh*_*ari 68 c# int types short

C#中的程序:

short a, b;
a = 10;
b = 10;
a = a + b; // Error : Cannot implicitly convert type 'int' to 'short'.

// we can also write this code by using Arithmetic Assignment Operator as given below

a += b; // But this is running successfully, why?

Console.Write(a);
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 71

这里有两个问题.第一个是"为什么短的加上短的结果在int?"

好吧,假设空头和空头很短,看看会发生什么:

short[] prices = { 10000, 15000, 11000 };
short average = (prices[0] + prices[1] + prices[2]) / 3;
Run Code Online (Sandbox Code Playgroud)

当然,如果这个计算是短暂的,那么平均值是-9845.总和大于最大可能的短,所以它包围负数,然后你除负数.

在整数运算环绕的世界中,在int中进行所有计算更为明智,这种类型可能具有足够的范围以使典型计算不溢出.

第二个问题是:

  • short plus short是int
  • 将int分配给short是非法的
  • a + = b与a = a + b相同
  • 因此短+ =短应该是非法的
  • 那为什么这是合法的?

这个问题有一个错误的前提; 上面的第三行是错误的.C#规范在7.17.2节中说明

否则,如果所选运算符是预定义运算符,如果所选运算符的返回类型可显式转换为x类型,并且如果y可隐式转换为x类型或运算符是移位运算符,则操作被评估为x =(T)(x op y),其中T是x的类型,除了x仅被计算一次.

编译器代表您插入强制转换.正确的推理是:

  • short plus short是int
  • 将int分配给short是非法的
  • s1 + = s2与s1 =(短)(s1 + s2)相同
  • 因此这应该是合法的

如果它没有为你插入演员表那么就不可能在许多类型上使用复合赋值.

  • 你的第一个样本不好.如果用`int`替换`short`,一切都会正常工作,但是如果我们输入更大的数字(使得和大于2 ^ 31),它将导致int溢出.我的问题是为什么`short + short = int`(和`byte`)和`int + int = int`(例如,不长). (9认同)
  • @LBushkin:它真的"同样可能"吗?我编写了以编译器为生的文章,我每天都在处理编译程序,这些程序的编程超过2 ^ 15种类型.如果我在一堆不同的程序集中添加类型的数量,我可以很容易地溢出一个短.我在编译器空间中从来没有遇到过可以合理地溢出int的问题.编译器在设法执行涉及具有20亿个类型的程序的算术之前很久就会耗尽虚拟内存.在大多数情况下,它不太可能有32位溢出. (8认同)
  • @Eric:int用于许多计算上下文中,其中一些与内存/进程空间无关.随着计算硬件功率和容量的增加,这些边界将很快定期超越.但也许更好的表达我的观点的方法是,如果编译器在执行算术时决定将较小的类型扩展到更宽的类型以避免意外的溢出,那么它应该使用具有保留范围和表示精度的可用更宽类型的所有类型.停止在int(而不是加宽到long)的选择有点出乎意料. (6认同)
  • @LBushkin:好的,你有没有让我们(1)说int​​ + int很长?这样做无异于说*所有的计算总是在长时间内完成*.您不希望让人们在每个整数计算中插入强制转换.(2)根据体系结构,C#有不同的行为,就像C一样吗?(3)自动扩展为更大的类型,如VBScript所做的那样; 放弃在C#中静态输入.(4)别的什么?这些方法中的每一种都具有严重的性能或便携性成本.成本值得吗? (5认同)
  • @LBushkin:你为什么要避免这种促销活动?我向你保证,CLR运行时层*和最终*CPU*都将扩展到int.假设为了争论,我们*希望*短期和短暂停留.IL层没有该操作的操作码.它只有整数加法的操作码.无论如何,CLR都会将这些短路转换为整数.假设我们在IL中添加了短加法运算符; 现在抖动是做什么的?当芯片注册时,芯片将把操作数扩展到32位. (3认同)
  • @Eric:另外,我的印象是至少在x86架构上,只能在16位非扩展寄存器上执行移动,加载和算术运算.您还可以访问低和高8位子标记(例如,AX内的AL和AH).显然,非x86架构上的行为可能存在实质性的不同. (3认同)
  • @Andrey:是的,整数算术可能会溢出。如果您想避免这种情况,则可以使用检查运算符来确保整数溢出导致异常。如果您认为您可能会使用足够大的整数,以至于它们上的常见数学运算符可能会溢出,那么您应该首先以长整型进行所有算术运算。 (2认同)

Dav*_*und 12

好吧,+=运营商说你会a用短路来增加价值,同时=说你会用操作的结果覆盖价值.该操作a + b产生一个int,不知道它可以做什么,并且你试图将该int分配给short.


UpT*_*eek 9

你必须使用:

a = (short)(a + b);
Run Code Online (Sandbox Code Playgroud)

至于赋值和赋值赋值行为之间的区别,我想它与此有关(来自msdn)

x+=y
is equivalent to
x = x + y
except that x is only evaluated once. The meaning of the + operator is
dependent on the types of x and y (addition for numeric operands, 
concatenation for string operands, and so forth).
Run Code Online (Sandbox Code Playgroud)

然而,它有点模糊,所以具有更深刻理解的人可以发表评论.

  • 在MSDN上它在哪里说?这是错误的**如果+是预定义的运算符**,在这种情况下,显然是.在这种情况下,它等于x =(T)(x + y),如指定的那样.如果您可以将链接发送给我,我会将其提交给文档管理员. (2认同)
  • @Eric:当然,它在这个页面上:http://msdn.microsoft.com/en-us/library/sa7629ew.aspx (2认同)

Mar*_*tos 7

发生这种情况是因为int是+已定义的最小签名类型.任何较小的东西首先被提升为int.该+=运营商相对于定义的+,但处理不符合目标结果的特殊情况规则.

  • 这个答案是不正确的.+ =未定义每种数字类型.请参阅C#规范的第7.17.2节. (2认同)