The CLR supports both unchecked and checked integer arithmetics. This post explains how this is exposed in the C# language.
As default, C# does integer arithmetics in a unchecked context. In a unchecked context division by zero throws a exception, whereas overflow does not. Overflow happens when the range of a type is exceeded, e.g. by adding to the byte b
, so that result exceeds the range of 0-255. When this happens, the CLR truncates the result, and simply count over from zero: 254, 255, 0, 1, 2 … Hence the following statement will not throw an exception:
for (int i = 0; i < 256; i++)
{
b++;
}
Checked context
But the CLR actually supports integer arithmetics with overflow checking. You can mark a portion of your code as checked
, or use the /checked
compiler option to make the whole code compile to in a checked context, causing the following code to throw an OverflowException
:
checked
{
for (int i = 0; i < 256; i++)
{
b++;
}
}
But the overflow checking comes with a performance penalty – actual code like the above (when not overflowing) runs about 3.5 times faster in a unchecked context than in a checked. As an alternative, you can check for overflow youself, given that you know the precise circumstances under which a overflow will happen:
for (int i = 0; i < 255; i++)
{
if (b < 255) b++;
}
This check runs a bit faster than the all encompassing CLR check, and reduces the performance penalty to about 2.5.
3 responses to “Overflow, checked and unchecked”
The third code should be i < 256 and b < 256.
Depending on what you want, you may want to throw an exception if !(b < 256).
I guess the performance penalty for using checked is that it checks both b++ and i++, but I can't be sure unless I look into the msil code (haven't learnt to do that yet). Perhaps a good compiler will optimize away the checking on integral variables that can be determined at compile-time never to cause an OverflowException.
I made a mistake in my previous comment. b < 255 is correct.
Hi Chunkit
Yeps – The check happens before the addition.
Regarding optimization I suspects that the compile will not replace a checked operation with an unchecked, when it is explicit written in the code even – if the check is redundant. I have not checked this however. I you want to go into the msil code, you can use the MSIL Disassembler (Ildasm.exe).
Regards Kristoffer