为什么USHORT USHORT +等于为int? [英] Why is ushort + ushort equal to int?

查看:1393
本文介绍了为什么USHORT USHORT +等于为int?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

previously今天我尝试添加两个ushorts,我注意到,我不得不把结果返回到USHORT。我想这可能已经成为一个UINT(以prevent可能意外溢出?),但让我吃惊的是一个int(System.Int32)。

Previously today I was trying to add two ushorts and I noticed that I had to cast the result back to ushort. I thought it might've become an uint (to prevent a possible unintended overflow?), but to my surprise it was an int (System.Int32).

有一些聪明的原因还是它也许是因为INT被看作是基本整型?

Is there some clever reason for this or is it maybe because int is seen as the 'basic' integer type?

例如:

ushort a = 1;
ushort b = 2;

ushort c = a + b; // <- "Cannot implicitly convert type 'int' to 'ushort'. An explicit conversion exists (are you missing a cast?)"
uint d = a + b; // <- "Cannot implicitly convert type 'int' to 'uint'. An explicit conversion exists (are you missing a cast?)"

int e = a + b; // <- Works!

编辑:像GregS回答说,C#的规范说,两个操作数(在本例中A和B)应转换为int。我感兴趣的底层原因,为什么这是规范的一部分:为什么不C#规范允许操作直接在USHORT值

Like GregS' answer says, the C# spec says that both operands (in this example 'a' and 'b') should be converted to int. I'm interested in the underlying reason for why this is part of the spec: why doesn't the C# spec allow for operations directly on ushort values?

推荐答案

简单而正确的答案是因为C#语言规范是这么说的。

The simple and correct answer is "because the C# Language Specification says so".

显然,你不快乐与答案,想知道为什么它这么说。您正在寻找可信和/或官方消息人士,那将是一个有点困难。这些设计决定是很久以前做13年是一个很大的狗住在软件工程。他们被作为埃里克利珀呼吁他们,他们已经转移到更大更好的东西,不要在这里发表的答案提供的官方消息的老前辈的。

Clearly you are not happy with that answer and want to know "why does it say so". You are looking for "credible and/or official sources", that's going to be a bit difficult. These design decisions were made a long time ago, 13 years is a lot of dog lives in software engineering. They were made by the "old timers" as Eric Lippert calls them, they've moved on to bigger and better things and don't post answers here to provide an official source.

但是,可以推断出,在仅仅是可信的风险。任何托管的编译器,如C#的,有它需要产生code为.NET虚拟机的限制。该规则这是认真(和可读性相当)在CLI规范描述。它是ECMA-335规范,你可以从这里免费下载

It can be inferred however, at a risk of merely being credible. Any managed compiler, like C#'s, has the constraint that it needs to generate code for the .NET virtual machine. The rules for which are carefully (and quite readably) described in the CLI spec. It is the Ecma-335 spec, you can download it for free from here.

转到第三分区,章3.1和3.2。他们描述了可用于执行加法两个IL指令,添加 add.ovf 。点击链接表2,二进制数字运算,它描述了操作数是允许那些IL指令。请注意,有刚刚上市的有几种类型。字节和短以及所有无符号类型丢失。只有的int,long的IntPtr和浮点(float和double),是允许的。随着附加约束打上了一个X,你不能一个int添加到向往的例子。这些约束并非完全人造的,他们是根据事情可以做合理有效的可用硬件。

Turn to Partition III, chapter 3.1 and 3.2. They describe the two IL instructions available to perform an addition, add and add.ovf. Click the link to Table 2, "Binary Numeric Operations", it describes what operands are permissible for those IL instructions. Note that there are just a few types listed there. byte and short as well as all unsigned types are missing. Only int, long, IntPtr and floating point (float and double) is allowed. With additional constraints marked by an x, you can't add an int to a long for example. These constraints are not entirely artificial, they are based on things you can do reasonably efficient on available hardware.

任何管理编译器,以生成有效的IL来处理这个问题。这并不难,只需将USHORT转换成的表中的一个较大的值类型,转换这总是有效。 C#编译器选秀权INT,出现在表格中的下一个更大的类型。或在一般情况下,转换任何操作数的下一个最大的值的类型,这样它们都具有相同的类型和满足约束条件在表中。

Any managed compiler has to deal with this in order to generate valid IL. That isn't difficult, simply convert the ushort to a larger value type that's in the table, a conversion that's always valid. The C# compiler picks int, the next larger type that appears in the table. Or in general, convert any of the operands to the next largest value type so they both have the same type and meet the constraints in the table.

现在有但一个新的问题,即驱动器C#程序员pretty坚果的问题。该相加结果是促进了类型。你的情况,这将是int。因此增加的,比方说,0×9000和0×9000 2 USHORT值有一个完全有效的int结果:0x12000。问题是:这是不适合回一个USHORT的值。该值的溢出的。但它的没有的溢于IL计算,只有当编译器试图填满它放回一个USHORT溢出。 0x12000被截断为0x2000。令人困惑的不同的值,当你有2个或16个手指头算,不是10,只有一定的道理。

Now there's a new problem however, a problem that drives C# programmers pretty nutty. The result of the addition is of the promoted type. In your case that will be int. So adding two ushort values of, say, 0x9000 and 0x9000 has a perfectly valid int result: 0x12000. Problem is: that's a value that doesn't fit back into an ushort. The value overflowed. But it didn't overflow in the IL calculation, it only overflows when the compiler tries to cram it back into an ushort. 0x12000 is truncated to 0x2000. A bewildering different value that only makes some sense when you count with 2 or 16 fingers, not with 10.

值得注意的是,该add.ovf指令不处理这个问题。它是该指令用来自动生成一个溢出异常。但事实并非如此,在转换的整数实际计算没有溢出。

Notable is that the add.ovf instruction doesn't deal with this problem. It is the instruction to use to automatically generate an overflow exception. But it doesn't, the actual calculation on the converted ints didn't overflow.

这是真正的设计决策发挥了作用。老前辈显然决定,简单地截断INT结果USHORT是一个bug工厂。这当然是。他们决定,你必须承认你的知道的是,除了可以溢出,它是好的,如果它发生。他们把它的的问题,主要是因为他们不知道如何使它他们仍然产生有效的code。你必须投。是的,这是令人发狂,我敢肯定你不想这个问题无论是。

This is where the real design decision comes into play. The old-timers apparently decided that simply truncating the int result to ushort was a bug factory. It certainly is. They decided that you have to acknowledge that you know that the addition can overflow and that it is okay if it happens. They made it your problem, mostly because they didn't know how to make it theirs and still generate efficient code. You have to cast. Yes, that's maddening, I'm sure you didn't want that problem either.

很明显的是,VB.NET的设计师采取了不同的解决问题的办法。他们实际上使得它的及其的问题,并没有推卸责任。您可以添加两个UShorts并将其分配给一个USHORT没有一个演员。所不同的是,VB.NET编译器实际生成的额外的的IL来检查溢出条件。这不是便宜code,使每一个短另外约3倍速度慢。但除此之外,这可以解释为什么微软维护的原因的两个的有,否则非常类似的功能的语言。

Quite notable is that the VB.NET designers took a different solution to the problem. They actually made it their problem and didn't pass the buck. You can add two UShorts and assign it to an UShort without a cast. The difference is that the VB.NET compiler actually generates extra IL to check for the overflow condition. That's not cheap code, makes every short addition about 3 times as slow. But otherwise the reason that explains why Microsoft maintains two languages that have otherwise very similar capabilities.

长话短说:你付出的代价,因为你使用的类型,这不是一个很好的搭配了现代的CPU架构。这本身就是一个很好的理由,而不是使用USHORT UINT。获得牵引出USHORT是很难的,你会操纵他们出的重量节省内存的成本之前需要他们中的很多。不只是因为有限的CLI规范的,在x86核心需要一个额外的CPU周期加载,因为在机器code中的操作数preFIX字节的16位值。实际上并不知道这在今天仍然如此,它曾经是回来的时候我还注意了计数周期。狗去年同期水平。

Long story short: you are paying a price because you use a type that's not a very good match with modern cpu architectures. Which in itself is a Really Good Reason to use uint instead of ushort. Getting traction out of ushort is difficult, you'll need a lot of them before the cost of manipulating them out-weighs the memory savings. Not just because of the limited CLI spec, an x86 core takes an extra cpu cycle to load a 16-bit value because of the operand prefix byte in the machine code. Not actually sure if that is still the case today, it used to be back when I still paid attention to counting cycles. A dog year ago.

确实注意到,你可以通过让C#编译器觉得这些丑陋的和危险的演员更好地生成相同的code。该VB.NET编译器生成。所以,你会得到一个OverflowException异常时,剧组竟然是不明智的。使用项目>属性>生成选项卡>高级按钮>勾选检查算术溢出/下溢复选框。只是调试版本。为什么这个复选框不被项目模板自动打开的是另一种非常神秘的问题,顺便说一句,这是做不久之前的决定。

Do note that you can feel better about these ugly and dangerous casts by letting the C# compiler generate the same code that the VB.NET compiler generates. So you get an OverflowException when the cast turned out to be unwise. Use Project > Properties > Build tab > Advanced button > tick the "Check for arithmetic overflow/underflow" checkbox. Just for the Debug build. Why this checkbox isn't turned on automatically by the project template is another very mystifying question btw, a decision that was made too long ago.

这篇关于为什么USHORT USHORT +等于为int?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆