Unsigned Arithmetic and overflows

I've had this discussion before with unint64s. Setting what would normally be the sign bit causes an overflow. Now I'm seeing this in unint32s.

Dim aAs UInt32 = System.Drawing.Color.Black.ToArgb

will cause and overflow.

Dim a as Uint32 = now.ticks and &hFFFFFFFF will cause an overflow depending in the time.

This should not be. What it means effectively is the UInt32 is actually UInt31.

[598 byte] By [ReneeC] at [2007-12-24]
# 1

No, it does not mean that UInt32 is actualy UInt31.

The Ticks property of DateTime is Long and &hFFFFFFFF is an Integer constant. To apply the And operator the compiler extends &hFFFFFFFF to Long, that is to &hFFFFFFFFFFFFFFFF and does the And. Obviously you'll get a 64 bit value mots of the time that will never fit into a 32 bit UInt32.

I assume you wanted to get only the first 32 bit of the Ticks member so you should do something like this:

a = now.ticks and &hFFFFFFFFL

The L will tell the compiler to create a Long constant so it does not need to extend it from Integer to Long

MikeDanes at 2007-8-31 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 2

Ok Mike I have a better example.

Dim a as uint32 = &h7FFFFFFF is legal to the compiler

Dim a as uint32 = &h8FFFFFFF is not legal to the compiler. If uint32s functioned as true unsigned integers one should be able to set bit 31. Here the compiler will not even allow you to do it.

Only one bit has changed, Mike and that's but 31.

Also if you take a look at the MSIL when dealing with unint32, MSIL code mysteriously goes to 64 bit entities which are defined as
uint32s. Lets say I'm shifting. 32Bit entity >> 14 has to be faster than 64Bit entity >> 14 yet this is what MSIL indicates.

I also demonstrated the same thing with uint64s last oct, touching bit 63 in a uint64 will cause and overflow. Perhaps that's why it's no CLS compliant?

But uint32 is CLS compliant and you cannot touch bit 32 without getting an overflow.

ReneeC at 2007-8-31 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 3

Ok Mike I have a better example.

Dim a as uint32 = &h7FFFFFFF is legal to the compiler

Dim a as uint32 = &h8FFFFFFF is not legal to the compiler. If uint32s functioned as true unsigned integers one should be able to set bit 31. Here the compiler will not even allow you to do it.

Only one bit has changed, Mike and that's bit 31.

Also if you take a look at the MSIL when dealing with unint32, MSIL code mysteriously goes to 64 bit entities which are defined as
uint32s. Lets say I'm shifting. 32Bit entity >> 14 has to be faster than 64Bit entity >> 14 yet this is what MSIL indicates.

I also demonstrated the same thing with uint64s last oct, touching bit 63 in a uint64 will cause and overflow. Perhaps that's why it's no CLS compliant?

But uint32 is CLS compliant and you cannot touch bit 32 without getting an overflow.

ReneeC at 2007-8-31 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 4

However.............

Dim a As UInt32

Dim b As UInt32

a = 1

a = a << 31

b = a

Works absolutely fine. However the equivalent will not work with uint64.
I looked at the assembler and it's doing all of this in the ESI which I assume is 32
bits wide on a Pentium Prescot?

ReneeC at 2007-8-31 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 5

This is so wierd

Dim a as uint32

This is legal in the compiler: a = 1 << 30

This is not: a = 1 << 31

ReneeC at 2007-8-31 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 6

Yes,

Dim a as uint32 = &h8FFFFFFF

is not legal to the compiler, but this code is

Dim a as uint32 = &h8FFFFFFFUI

&h8fffffff is an Integer constant (that is -1879048193) and you cannot assign this value to an UInt32 because UInt32 are supposed to be in the range 0 to 2^32 - 1, and this value is negative.

By adding the UI suffix you are telling the compiler that &h8fffffff ia a UInt32 constant (that is 2415919103) which a valid value for an UInt32.

About the compiler using 64 bit entities. Yes, it can happen because of mixing Int32 and UInt32. Since UInt32 has a MaxValue that is larger than the MaxValue of Int32 the compiler converts them to the next type that is capable of containing both MaxValue s, that is Long and operates on Longs.

I don't know what you have demonstrated last oct... if you give me a link maybe I can comment on it

And UInt32 is not CLS compliant either...

MikeDanes at 2007-8-31 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 7

But this one is:

a = 1UI << 31UI

You really need this doc page:

http://msdn2.microsoft.com/en-us/library/s9cz43ek.aspx

See "Forced Literal Types" section.

Keep in mind that anytime when you specify a numeric constant without one of those suffixes the compiler thinks that it is an Integer constant, hence all the trouble.

MikeDanes at 2007-8-31 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 8

Hey Mike,

I'll find the link for you in just a moment.

Here's THE Problem:

Dim a As UInt32 = &H80000000 is not legal

Dim a As UInt32 = &H80000000L is legal. So as you say the ISSUE is with the constant. However I'm going to call it a problem because

a CONSTANT should be CONSTANT. I am an enginner that wrote in assembly for years and there was one thing you could count on which was.
If a constant does relate to the data type it's being used with, as programmers we lose a lot of control.

MOVL R0, #80000000 ; or

BISL R0, #80000000

The constant you could count on. Notice that you are moving or setting a longword (32 bit entity) the constant is defined by the instruction length and you
could count on that.

Dim a As UInt32 = &H80000000

is the same thing.

ReneeC at 2007-8-31 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 9

Well, that was assembly language. The thing is that, as yourself stated, for assembly language you can infer the type of the constant from the size of the instruction itself. MOVL tells you clear that, hey, I'm moving 32 bit here, not less, not more. Not to mention that in the assembly language things like the sign of a value only come to play when you are testing the flags after doing a compare or a logic/arithmetic operation. MOVL does not care about signed/unsigned.

And probably the biggest difference between assembly language and high level languages (Not only VB.NET uses "typed" constants but also C/C++/C# do this, at least. Almost for sure Java does it too but I don't remember right now.) is that in assembly language you can't have expressions. You can have constant expressions (like in MOVL R0, 2+3) but you cannot have expression with variables, and more important you cannot have expression with variables of different types.

In high level languages what comes to the right of the = operator is always an expression. And an expression always has a type and the expression type is never inferred from what's in the left side of the = operator but from the variables and constants that make up the expression. This led to the need that the constants themself be typed just like variables are.

Should the compiler be smart and in the simple case of

Dim a As UInt32 = &H80000000

infer the type of the constant from the type of the variable ?

Maybe, but I for myself prefer consistency. If variables have types, let the constants have too.

MikeDanes at 2007-8-31 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 10

Hi Mike,

I liked your last question because it was interesting. I would prefer that simple case because without it there is a loss of control for the programmer.

How is the following evaluated?

Dim a as uint32

a = 1 << 31

That's illegal where

a = 1 << 30

Is legal. Are those evaluated as constants? I'd hope not actually as a programmer, I may want that done at run time.

Dim a As UInt32

Dim b As UInt32 = 1

a = b << 31

This "works". but it does not seem consistent that Dim b As UInt32 = 1 << 31

is not legal to the compiler.

These fundament behavioral differences do not seem consistent to me.

ReneeC at 2007-8-31 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 11

MOVL does not care about signed/unsigned.

Exactly !!!!!!!!!!!!!!!!!!!! but the entire purpose of declaring a Uint32 is to have that exact same behavior.

ReneeC at 2007-8-31 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 12

Most of the modern compiler (be it VB, C# or C/C++) will evaluate 1 << 31 at compile time. There is no point in evaluating it at runtime other than wasting CPU cycles.

Since 1 << 31 is evaluated at compile time so the compiler is able to detect the overflow and complain. b << 31 obviously cannot be evaluated at compile time and the compiler cannot guess that it will result in an overflow or not (you get no overflow if b = 0 for example).

As for consistency, hmmm, indeed it's a bit inconsistent that some errors are caught at compile time and some at runtime... but after all this nothing out of the ordinary. Wouldn't be nice if all the possible programming error would be caught at compile time ? Unfortunately this is not possible but the compiler tries its best to help.

I remember when I moved to C/C++ after some years of assembly language for x86 (which included writing an assembler) I felt weird about various things that high level languages do. But that's the deal, you lose a part of control to gain other things.

MikeDanes at 2007-8-31 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 13

Well, you get the same behavior as long as you tell the compiler what type the constants are. It's not big deal to add an UI suffix after all.

MikeDanes at 2007-8-31 > top of Msdn Tech,Visual Basic,Visual Basic Language...
# 14

Your're right. Everyonce in while, I need those descriptors. What are they called?

ReneeC at 2007-8-31 > top of Msdn Tech,Visual Basic,Visual Basic Language...