完美解决VB中int to short溢出问题

 

工作笔记,英文烂没办法,如果不幸被你看到,请勿喷。。。

Summary:

  1. To unsigned type: just do And operator, or 2st method.

Eg. Dim a As Byte = CByte(300 And &HFF)

 

  1. To signed type: left shift n bits, then right shift n bits, which is to expand the signed bit. n = (sizeof(type1) - sizeof(type2)) * 8   or VB:use Len(New type) instead of sizeof(type)

 

Eg. Dim a As Short = CShort(34042 << 16 >> 16)

 

You can ignore the following information in case you don't want to know the detail.

 

int a = 34042;

short a1 = a;

 

You would got an error as follow:  

 

Language compilers do not perform this conversion automatically because it can involve data loss. Instead, they perform the conversion only if a casting operator (in C#) or a conversion function (such as CType or CShort in Visual Basic) is used. Otherwise, they display a compiler error.

 

In C#, we can use a casting operator:

int a = 34042;

short a1 = (short)a;

 

 

In VB, we should use a conversion function:

Dim a As Integer = 100

Dim a1 As Short = CShort(a)

  

 

But issues occurred when the value is beyond the rang of short type in VB.

' Short: -32768 ~ 32767( 0FFFF8000H ~ 7FFFH)       

Dim a As Integer = 34042

Dim a1 As Short = CShort(a)

 

 

In the 1st C# code, it works fine. But according to the value, how can we get -31494 from 34042? And why the VB code would catch an overflow exception(although it actually does)?

 

In fact, (short)a would generate IL:conv.i2  in C#. But CShort(a) would generate IL:conv.ovf.i2 in VB, and which might throw an overflow exception.

 

So, what we want to do is just to find out the rules of conversion.

 

conv.i2=Converts the value on top of the evaluation stack to int16, then extends (pads) it to int32.

 

Ok, let's follow it.

 

' Short: -32768 ~ 32767( FFFF8000H ~ 7FFFH)       

Dim a As Integer = 34042

'Dim a1 As Short = CShort(a)

Dim a2 As Short = CShort(a And &HFFFF)

 

But unfortunately failed again, and got the same exception.

 

Actually, a And &HFFFF is still an integer but grater than Short.MaxValue, so it failed again.

 

Short is a 16-bit signed integer type so that it only contains 15 data-bit and 1 signed-bit.

 

Short.MaxValue and Short.MinValue:

00000000 00000000 01111111 11111111

11111111 11111111 10000000 00000000

 

So, after you do the "And" operator, you must expand another 16 bits according to the signed bit.

 

My solution is that: Left shift 16 bits, and then right shift 16 bits.

' Short: -32768 ~ 32767( FFFF8000H ~ 7FFFH)       

Dim a As Integer = 34042

'Dim a1 As Short = CShort(a)

'Dim a2 As Short = CShort(a And &HFFFF)

Dim a3 As Short = CShort((a And &HFFFF) << 16 >> 16)

 

 

Let's see what happened.

a

84FAH

a And &HFFFF

84FAH

(a And &HFFFF) << 16

84FA 0000H

(a And &HFFFF) << 16 >> 16

FFFF 84FAH

 

Actually you can skip the And operator step.

Dim a3 As Short = CShort(a << 16 >> 16)

 

You can get these hex value by : Console.WriteLine("{0:X}", a) ...

 

Now it's all clear!

 

You can expand this method to other similar conversion, such as long to int( can use Fix()), long to short, etc.

posted on 2010-12-04 09:37  长空无忌  阅读(1833)  评论(0编辑  收藏  举报

导航