Keil C常量乘法的问题

来源:互联网 发布:sql语句格式化工具 编辑:程序博客网 时间:2024/05/21 05:23

http://bbs.ednchina.com/BLOG_ARTICLE_1793308.HTM

 

写汇编写多了,用C的时候问题一大堆,今天调试一个乘法,问题就来了。


代码如下:


void test(void)


{    


      unsigned long temp,temp1;


      temp = 1600 *4950*16;


(icon第一次用这个博客呢,没想到还不支持tab键啊,晕死,那就space space)


   temp1 = 1600;


   temp1 *= 1600;


   temp1 *= 4950;


   temp1 *=16;


}


调试结果temp为FFFF9C00,temp1为063F9300。为什么呢?


难不成常量默认为int型,在强制转换的时候,因为溢出,自动就添到高字节去了,那也添太多了,全成F了。


baidu一下,看了人家的经验总结,原来是那么一回事啊。看来C语言也不够智能嘛,也不是我想的那么无所不能啊,还以为是编译器的问题呢。


现在来看看抄来的解释。iconhttp://blog.ednchina.com/nevsayno/18640/post.aspx


void test(void)


{


       unsigned long mid1,mid2,mid3;


       mid1=6*10000;//index1


       mid2=7*10000;//index2


        mid="8"*10000;//index3


}


咋一看,这段代码似乎是对的,其实不然,如果跟踪调试一下代码就会发现:


mid1=0xea60=60000;


mid2=0x1170=4464;


mid3=0x3880=14464;


mid1是正确的,mid2和mid3是错误的!


产生错误的原因是:


编译器在编译的时候把6*10000、7*10000以及8*10000计算得来的结果存在了一个unsigned int类型的变量当中,unsigned int类型变量的最大值是0xffff,即65536,因此在 index2与index3行中发生了数据溢出,导致计算错误!


解决方法:


void test(void)


{


       unsigned long mid1,mid2,mid3;


       mid1=6*(unsigned long)10000;//index1


       mid2=7*(unsigned long)10000;//index2


        mid="8"*(unsigned long)10000;//index3


}


请注意,以下代码是错误的!至于错误原因,大家自己分析吧。


void test(void)


{


       unsigned long mid1,mid2,mid3;


       mid1=(unsigned long)(6*10000);//index1


       mid2=(unsigned long)(7*10000);//index2


        mid=(unsigned long)(8*10000);//index3


}


由于同级算术运算遵守从左到右的顺序,所以建议将指定常量类型的ul放在左边。