www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Checked oveflows in C#

reply bearophile <bearophileHUGS lycos.com> writes:
It seems one group of ideas and syntax I did suggest for D weren't so Krazy,
after all. I have just found that they can be seen almost equal in C#.

You can read something about them here:
http://msdn.microsoft.com/en-us/library/a569z7k8.aspx

There is the checked/unchecked keyword that can be used to denote a block of
code:

checked {
    z = x * y;
}

unchecked {
    z = x * y;
}

Or even just an expression:
z = checked(a + b);

z = unchecked(a + b);

Beside that, you also have a global compiler flag that activates or disables
the oveflow checks globally. So if you activate them globally, you can disable
them locally, and if you disable them globally you can activate them locally.

As you may remember, I did invent a similar design for D, but:
- I didn't invent the ability to activate/disable such checks for a single
expression. I am not sure how much this can be useful.
- I did invent a syntax to tell what controls to perform, for example:
safe(overflow, bounds, ...) { ... }
unsafe(overflow, bounds, ...) { ... }

Note that for non-English people it's not easy to write the keywords
checked/unchecked, that's why I think safe()/unsafe() words are better.

---------------------

To show something more real I have also compiled various variants of a small
program, using different integral numbers:


cast(short)(short + short):

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

00000033  movsx       eax,word ptr ds:[009393B8h] 
0000003a  movsx       edx,word ptr ds:[009393BCh] 
00000041  add         eax,edx 
00000043  jno         0000004A 
00000045  call        76BEABDA 
0000004a  cmp         eax,7FFFh 
0000004f  jle         00000056 
00000051  call        76BEABDA 
00000056  cmp         eax,0FFFF8000h 
0000005b  jge         00000062 
0000005d  call        76BEABDA 
00000062  mov         dword ptr [ebp-3Ch],eax 

-------------------------

The same cast(short)(short + short), but more optimized:

int z = checked((short)(x + y));
            
00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        edi  
00000004  push        esi  
00000005  push        ebx  
00000006  movsx       ecx,word ptr ds:[00932FE0h] 
0000000d  mov         edi,ecx 
0000000f  movsx       edx,word ptr ds:[00932FE4h] 
00000016  add         edi,edx 
00000018  jo          0000006D 
0000001a  cmp         edi,7FFFh 
00000020  jg          0000006D 
00000022  cmp         edi,0FFFF8000h 
00000028  jl          0000006D 

-------------------------

int + init => int

int z = checked(x + y);

00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        edi  
00000004  push        esi  
00000005  push        ebx  
00000006  mov         edi,dword ptr ds:[00932FE0h] 
0000000c  add         edi,dword ptr ds:[00932FE4h] 
00000012  jo          0000005E 

-------------------------

ubyte + ubyte => ubyte

int z = checked((byte)(x + y));

(the byte type is unsigned, so it's the ubyte of D)

00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        edi  
00000004  push        esi  
00000005  push        ebx  
00000006  movzx       ecx,byte ptr ds:[00932FE0h] 
0000000d  mov         edi,ecx 
0000000f  movzx       edx,byte ptr ds:[00932FE4h] 
00000016  add         edi,edx 
00000018  jo          00000064 
0000001a  test        edi,0FFFFFF00h 
00000020  jne         00000064 

-------------------------

64 bit long + 64 bit long => long 64 bit (all signed)

long z = checked(x + y);

(On a 32 bit operating system, depsite the CPU was a 64 bit one)

00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        edi  
00000004  push        esi  
00000005  push        ebx  
00000006  sub         esp,8 
00000009  mov         eax,dword ptr ds:[00932FE0h] 
0000000e  mov         edx,dword ptr ds:[00932FE4h] 
00000014  add         eax,dword ptr ds:[00932FE8h] 
0000001a  adc         edx,dword ptr ds:[00932FECh] 
00000020  jo          00000090 
00000022  mov         ebx,eax 
00000024  mov         edi,edx 

-------------------------

ulong + ulong => ulong

ulong z = checked(x + y);

00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  push        edi  
00000004  push        esi  
00000005  push        ebx  
00000006  sub         esp,8 
00000009  mov         eax,dword ptr ds:[00932FE0h] 
0000000e  mov         edx,dword ptr ds:[00932FE4h] 
00000014  add         eax,dword ptr ds:[00932FE8h] 
0000001a  adc         edx,dword ptr ds:[00932FECh] 
00000020  jb          00000090 
00000022  mov         ebx,eax 
00000024  mov         edi,edx 

So it seems I was right, after all, according to the designers of C#.

D is a system language, but it can (and generally is, it seems) used for
application-like code too. In such situations a certain percentage of code may
enjoy such extra (optional) controls.

Bye,
bearophile
Jan 26 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"bearophile" <bearophileHUGS lycos.com> wrote in message 
news:glk5pj$22rt$1 digitalmars.com...
 It seems one group of ideas and syntax I did suggest for D weren't so 
 Krazy, after all. I have just found that they can be seen almost equal in 
 C#.

 You can read something about them here:
 http://msdn.microsoft.com/en-us/library/a569z7k8.aspx

 There is the checked/unchecked keyword that can be used to denote a block 
 of code:

 checked {
    z = x * y;
 }

 unchecked {
    z = x * y;
 }

 Or even just an expression:
 z = checked(a + b);

 z = unchecked(a + b);

 Beside that, you also have a global compiler flag that activates or 
 disables the oveflow checks globally. So if you activate them globally, 
 you can disable them locally, and if you disable them globally you can 
 activate them locally.

 As you may remember, I did invent a similar design for D, but:
 - I didn't invent the ability to activate/disable such checks for a single 
 expression. I am not sure how much this can be useful.
 - I did invent a syntax to tell what controls to perform, for example:
 safe(overflow, bounds, ...) { ... }
 unsafe(overflow, bounds, ...) { ... }

 Note that for non-English people it's not easy to write the keywords 
 checked/unchecked, that's why I think safe()/unsafe() words are better.

Agreed. I've felt for a while that D should copy C#'s checked/unchecked system (maybe with your extensions, too).
Jan 26 2009
parent "Denis Koroskin" <2korden gmail.com> writes:
On Mon, 26 Jan 2009 20:54:38 +0300, Nick Sabalausky <a a.a> wrote:

 "bearophile" <bearophileHUGS lycos.com> wrote in message
 news:glk5pj$22rt$1 digitalmars.com...
 It seems one group of ideas and syntax I did suggest for D weren't so
 Krazy, after all. I have just found that they can be seen almost equal  
 in
 C#.

 You can read something about them here:
 http://msdn.microsoft.com/en-us/library/a569z7k8.aspx

 There is the checked/unchecked keyword that can be used to denote a  
 block
 of code:

 checked {
    z = x * y;
 }

 unchecked {
    z = x * y;
 }

 Or even just an expression:
 z = checked(a + b);

 z = unchecked(a + b);

 Beside that, you also have a global compiler flag that activates or
 disables the oveflow checks globally. So if you activate them globally,
 you can disable them locally, and if you disable them globally you can
 activate them locally.

 As you may remember, I did invent a similar design for D, but:
 - I didn't invent the ability to activate/disable such checks for a  
 single
 expression. I am not sure how much this can be useful.
 - I did invent a syntax to tell what controls to perform, for example:
 safe(overflow, bounds, ...) { ... }
 unsafe(overflow, bounds, ...) { ... }

 Note that for non-English people it's not easy to write the keywords
 checked/unchecked, that's why I think safe()/unsafe() words are better.

Agreed. I've felt for a while that D should copy C#'s checked/unchecked system (maybe with your extensions, too).

I agree. I have proposed the same a few times in the past. 'checked' can be implemented in a library (to some degree) but a full-fledged solution needs compiler support.
Jan 26 2009