搜索
bottom↓
回复: 20

分享:经典的Code VisionAVR错误!千万小心!!

[复制链接]

出0入0汤圆

发表于 2006-3-16 11:00:51 | 显示全部楼层 |阅读模式
大家请看下面的程序:



void Show_BMP(unsigned int Width,unsigned int Height)

{

unsigned long int position;

position=0x4d200+0x3e+Width/7+Height*408;

...

...

}

  以上程序的写法绝对没有任何语法错误!!Code VisionAVR编译的时候也不会报错,但是它却有一个致命的缺陷,就是在这里"Height*408"!!



  因为,虽然position是unsigned long int型的,大小绝对能容下后面的数据,但是Height却是unsigned int型的,在编译的时候,因为一般code visionAVR都是开了优化选项的,所以它会认为Height*408依然是一个unsigned int型,结果就是当Height超过了0XA1后,程序就绝对出错了,虽然前面的position是unsigned long int型,但是这里的运算依然会出错。而且,就算改成以下写法,也依然会出错的:

    position=(unsigned long int)(0x4d200+0x3e+Width/7+Height*408);



必须改成这个样子的才对:

    position=0x4d200+0x3e+Width/7+(unsigned long int)Height*408;



因为最近在编写一个显示BMP的程序,结果开始是对了, 到后面就出错了。查。  2天后,终于发现了这个问题,所以提出来,希望code visionAVR的朋友们注意(不管是1.24.6还是最新1.24.8,都是一样的,我试了的),呵呵!所以写程序的时候千万要小心!!要养成好的习惯!(GCC我测试了一下,不开优化的话没有错,但是开了的话我就无法用STUDIO调试了,所以不知道,请有条件的朋友帮忙测试一下:))




-----此内容被myhk007于2006-03-16,11:03:04编辑过

出0入0汤圆

发表于 2006-3-16 11:27:06 | 显示全部楼层
数据类型溢出,有点隐蔽。这个错误和开不开优化应该是没有任何关系的。

“显示BMP的程序”用的什么液晶啊?

出0入0汤圆

 楼主| 发表于 2006-3-16 12:16:29 | 显示全部楼层
两种都用了,3310,还有一块240*128的。

出0入0汤圆

发表于 2006-3-16 13:56:48 | 显示全部楼层
C数据类型道理上应该遵循向上靠原则,Height是int的,那么运算时候应该是按照long计算的,结果也是long型的.



cv计算很奇怪,但是最好养成一个数据类型强制转换习惯吧!



看看下面的计算(cv中的):



int c = (char a) * 200 + (char b) * 512;



这个结果很可能出错,请注意!



错误原因在这里:(char a) * 200 ,cv认为既然都是char的,那么他就认为结果也是char的,但是如果刚好两个char的:100 *100 = 10000就溢出了,cv就把结果转换成char的,结果是0,显然错误.但是如果这样:8 * 6 + (char b) * 512;结果就正确了.



这个式子:(char b) * 512; 有个512存在,cv就按照int进行计算,结果保留成int,结果正确.



正确的如下:



int c = (int)(char a) * 200 + (char b) * 512;



并且在cv的user manual中有乘法计算注意事项,就说的是这个,要求用户手动强制转换,建议用cv的还是要好好看看datasheet

出0入0汤圆

发表于 2006-3-16 20:00:30 | 显示全部楼层
象类似这种运算我都采用分部计算,如上面所说的运算式我会变换成如下:

void Show_BMP(unsigned int Width,unsigned int Height)

{

unsigned long int position;



position=Height

position*=408;

position+=(Width/7);

position+=(0x4d200+0x3e);

...

...

}

出0入0汤圆

发表于 2006-3-16 20:06:15 | 显示全部楼层
确实,这些数学_运算,写成分步计算更可靠,而且生成的代码通常都不会增多。

出0入0汤圆

发表于 2006-3-16 20:18:41 | 显示全部楼层
的确很恶心的错误,谢各位大虾了,日后用到尽量小心了。

出0入211汤圆

发表于 2007-6-9 12:31:43 | 显示全部楼层
低级错误!

出0入0汤圆

发表于 2007-6-9 14:03:34 | 显示全部楼层
对C语言不熟,还怪编译器。

出0入0汤圆

发表于 2007-6-9 15:17:27 | 显示全部楼层
其实这样的问题即使是VB、VC都存在,怪不上编译器吧,需要自己注意的。

出0入0汤圆

发表于 2007-6-9 17:54:01 | 显示全部楼层
嗯,多谢楼主提醒,以后碰到这种问题确实得注意点

出0入0汤圆

发表于 2007-6-10 09:42:29 | 显示全部楼层
这类的运算,CV125.5都会有警告的!

你的编译器该更新了.

出0入0汤圆

发表于 2007-6-10 10:26:03 | 显示全部楼层
VB,VC和几乎所有编译器都如此,不是编译器问题,要自己转换的

出0入0汤圆

发表于 2007-6-10 19:26:08 | 显示全部楼层
那我用UNSIGNED LONG型的数据与UNSIGNED INT相减居然出来了负数,我是用最新版的,后来都加了强制类型转换。

出0入0汤圆

发表于 2007-6-11 16:07:15 | 显示全部楼层
这个本来就是这样的,CVR帮助文档里有关于这个的说明!因为只有做乘法结果的长度会有可能是达到 sizeof(被乘数)+sizeof(乘数) 这个长度!

出0入0汤圆

发表于 2008-6-14 20:34:26 | 显示全部楼层
确实是不容易发现的错误,细心人

出0入0汤圆

发表于 2008-6-14 22:31:13 | 显示全部楼层
CV确实有是这样的

出0入0汤圆

发表于 2008-6-15 11:15:56 | 显示全部楼层
m

出0入0汤圆

发表于 2008-6-15 17:44:28 | 显示全部楼层
UP,学习了

出0入0汤圆

发表于 2008-6-16 20:12:13 | 显示全部楼层
对C语言不熟,怪不得编译器。

出0入0汤圆

发表于 2008-6-17 09:15:13 | 显示全部楼层
和编译器无关,你用IAR和ICC都是这样的。使用乘法和加法的时候最好习惯加个强制转换,除非保证结果不会溢出。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-3 10:51

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表