谈谈C#的数值类型——顺便给for循环做个补充
补充一下:上次讲for循环的文章 详解for循环(各种用法)
假如变量的值 i = int.MaxValue;这个时候运行;Console.WriteLine(++i);输出什么?
假如我的循环写成这样:
int max = int.MaxValue;
for (int i = start; i < max + 100; i++)
{
Console.WriteLine(i);
}
又会输出什么?
答案令人大跌眼镜。
Console.WriteLine(int.MaxValue);
i++;
Console.WriteLine(i);
输出了
2147483647
-2147483648
而上面的循环,编译正确,却没有被执行。为什么没有被执行?推断一下,int的最大值+1是负数,那么+100估计(嘿嘿,这里带有估计的一种情感)也是负数。那么i是int最大值减去10,是个正数,怎么也不能小于负数不是?那就不执行了。果然,int.MaxValue+100 = -2147483549。
为啥会这样?这就要从数字的补码说起了。你也猜到了吧?呵呵,-2147483648就是2147483647的补码嘛!
2147483647 的16进制是 0x7FFFFFFF ,2进制就是32个1,
而-2147483648 的16进制就是0x80000000,2进制就是1和32个0。
看出来啦,C#内部并没有对int做溢出运算。加个checked就搞定了。
checked
{
i++;
}
这个时候就会抛出一个异常。但是,一般还是少抛出异常的好,自己动手检查一下就好了。
再回到循环,要是溢出,会对循环产生什么影响呢?把上面的循环改成:
int max = int.MaxValue;
for (int i = start; i <= int.MaxValue; i++)
{
Console.WriteLine(i);
}
输出什么呢? 成无限循环了!!!
在int中可能不太会出现这种问题,在byte里就会有这种状况。
{
Console.WriteLine(i);
}
在上面的情况中,可能就想对byte的各种取值进行处理而已,但是,现在办不到了,因为这个循环成无限循环了。以下代码就可以解决这种状况:
{
static void Main(string[] args)
{
for (byte i = 0; IsMax(ref i); )
{
Console.WriteLine(i);
}
Console.Read();
}
static bool IsMax(ref byte i)
{
if (i == 255)
return false;
else
{
i++;
return true;
}
}
}
这是比较特殊的解决方案。事实上还有其他运算来保证不溢出。
就是用&运算。比如:
i = (i = i + 2) & 0x7FFFFFFF;
Console.WriteLine(i);
这段代码,输出的结果就是1.有兴趣的朋友可以自己做2进制的与运算看看,0x7FFFFFFF就是int的最大值的16进制的表达方式。
这种用法看似没有用。
但下面的代码中就能有效避免错误了,呵呵
{
static string[] s = new string[128];
static void Main(string[] args)
{
byte b = 129;
setValue((sbyte)b, "asdasd");
Console.WriteLine(getValue((sbyte)b));
Console.Read();
}
static string getValue(sbyte b)
{
return s[b & 0x7F];
}
static void setValue(sbyte b, string value)
{
s[b & 0x7F] = value;
}
}
最后讲最后一种数据类型,其他的都和上面三种类似,但是最后一种是个特例。
看看这句代码
decimal d = decimal.MaxValue;
Console.WriteLine(++d);
这个会输出什么呢?自己去试试吧,呵呵。
看了以上的代码对你也许没什么用,起一个警惕作用也是不错的。至于下面点的与操作,可能会对你看别人写的代码有所帮助。
这篇文章讲的比较简单,不过要完全理解,我是说深刻理解数据类型,不是我这个文章,还是需要了解很多方面的东西的。这种可以说是程序员的内功,不但要去学OOP,OOD,SOA等等设计上的东西,对底层还是要多学一学,设计的那是招式,内功还是要多练练的。练好内功有助于写出稳定的代码,架构再好,程序也需要稳定不是吗?
2008年8月5日 by yurow @ http://www.cnblogs.com/birdshover/