Keil C编译器奇葩问题

Getdone 2018-12-17 11:10:41
在一个简单的循环程序中时间老是不对,所以写了点测试代码:

#include <REG52.h>

#define OSC_FREQ 12000000UL
#define OSC_PER_INST 12
#define INST_PER_LOOP 9
#define CH_MOVE_TIME 100
#define CMOVENUM (CH_MOVE_TIME*OSC_FREQ/(1000*OSC_PER_INST*INST_PER_LOOP))

typedef unsigned int uInt16;
typedef unsigned long uInt32;

void main()
{
uInt32 i=CH_MOVE_TIME*OSC_FREQ; //1200000000
uInt16 t=OSC_PER_INST; //12
uInt16 q=INST_PER_LOOP; //9
uInt32 j=1000*t*q;
uInt16 k=i/j;
}

结果在Keil的DeBug模式下,看到:
i= 0x47868C00=1200000000;
t=0x6E63=28259;
q=0x2660=9824;
j=0x0000A5E0=42464;
k=0x6E63=28259;

同样的代码,在纯C的IDE,DEV C++下面就没问题。感觉好奇葩啊。。。。
...全文
147 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
Getdone 2018-12-18
  • 打赏
  • 举报
回复
确实是这个问题:一个是计算的中间结果超出范围,一个是代码优化的问题。

大神们真赞!
dceacho 2018-12-17
  • 打赏
  • 举报
回复
你可以用printf把t,q,j输出,这样watch窗口的值就不一样了
dceacho 2018-12-17
  • 打赏
  • 举报
回复
引用 2 楼 Getdone 的回复:
就这个简单的例子,发现也有问题啊

void main()
{
    uInt16 t=12;
    uInt16 q=9;
    uInt16 j=q*t;
}
做乘法j=q*t时,把t的值也改成j了。为什么呢?
还是优化的原因,你这3个U16,但实际上用2个就够了,t=t*q

void main()
{
    uInt16 t=12;//1行
    uInt16 q=9;//2行
    uInt16 j=q*t;//3行
    while(1);
}
如果你把优化级别再调高点,你会发现1,2,3行全优化没了,因为你的t,q,j对输出没半点作用
Getdone 2018-12-17
  • 打赏
  • 举报
回复
就这个简单的例子,发现也有问题啊

void main()
{
uInt16 t=12;
uInt16 q=9;
uInt16 j=q*t;
}



做乘法j=q*t时,把t的值也改成j了。为什么呢?
worldy 2018-12-17
  • 打赏
  • 举报
回复
Keilc对于无用的代码会做优化掉,你的代码要么没有运行到,要么超出了uint16的表达范围

27,375

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧