迪文科技论坛

 找回密码
 立即注册
搜索
查看: 324|回复: 8

【提问】请问下编译器对于表达式的处理问题

[复制链接]

5

主题

8

回帖

64

积分

注册会员

Rank: 2

积分
64
发表于 2023-2-17 16:11:09 | 显示全部楼层 |阅读模式
就是我取了unix时间戳,因为要符合北京时间, 所以表达式是 unixtime = unixtime - (16*3600);  这样计算出来时间对应不上,但是如果是unixtime = unixtime -57600;  就对应上了,完整函数如下,
  1. idata u16 nian,yue,ri,shi,fen,miao;

  2. void newjudge(u32 unixtime)
  3. {
  4.   u16 year,month,day,hour,minute,second;
  5.   
  6.   u16 leap;
  7.   u16 days[12]={31,28,31,30,31,30,31,31,30,31,30,31};
  8.   //unixtime=unixtime+28800;
  9. //unixtime=unixtime-57600; //(-24+8) hour ok
  10. unixtime=unixtime-(16*3600); //error

  11.   second=unixtime % 60;
  12.   unixtime=unixtime / 60;
  13.   minute=unixtime % 60;
  14.   unixtime=unixtime / 60;
  15.   hour=unixtime % 24;
  16.   unixtime=unixtime / 24;
  17.   year=1970;
  18.   leap=0;
  19.   while (unixtime>=365)
  20.   {
  21.     if (leap==0)
  22.     {
  23.       if ((year % 4==0) && (year % 100!=0))
  24.       {
  25.         if (unixtime>=366)
  26.         {
  27.           unixtime=unixtime-366;
  28.           year++;
  29.         }
  30.         else
  31.           break;
  32.       }
  33.       else
  34.       {
  35.         unixtime=unixtime-365;
  36.         year++;
  37.       }
  38.     }
  39.     else
  40.     {
  41.       if (unixtime>=366)
  42.       {
  43.         unixtime=unixtime-366;
  44.         year++;
  45.       }
  46.       else
  47.         break;
  48.     }
  49.     if ((year % 4==0) && (year % 100!=0))
  50.       leap=1;
  51.     else
  52.       leap=0;
  53.   }
  54.   if (leap==1)
  55.     days[1]=29;
  56.   month=1;
  57.   while (unixtime>=days[month-1])
  58.   {
  59.     unixtime=unixtime-days[month-1];
  60.     month++;
  61.   }
  62.   day=unixtime+1;
  63.   miao=second;
  64.   fen=minute;
  65.   shi=hour;
  66.   ri=day;
  67.   yue=month;
  68.   nian=year;
  69. }
复制代码

麻烦大神们指点下

回复

使用道具 举报

5

主题

8

回帖

64

积分

注册会员

Rank: 2

积分
64
 楼主| 发表于 2023-2-20 09:32:51 | 显示全部楼层
大神们看看第十行和十一行,算出来编译后下载到屏里面时间就是正确的
回复

使用道具 举报

0

主题

17

回帖

562

积分

高级会员

Rank: 4

积分
562
发表于 2023-2-21 09:02:57 | 显示全部楼层
Keil C51是与ANSI C兼容的编译器,ANSI C规范规定十进制整数常量的默认数据类型是int、long int和unsigned long int的其中一种,对给定的常量是其中的哪一种要看这个常量的实际大小,如果常数在-32768~32767之间则按int类型处理。3600*16的运算超过32767,会变负,需要对表达式里面的常量进行强转。
回复

使用道具 举报

5

主题

8

回帖

64

积分

注册会员

Rank: 2

积分
64
 楼主| 发表于 2023-2-21 14:55:38 | 显示全部楼层
userdc 发表于 2023-2-21 09:02
Keil C51是与ANSI C兼容的编译器,ANSI C规范规定十进制整数常量的默认数据类型是int、long int和unsigned  ...

但是我程序里面是u32啊,FFFF就65535嘛,3600*16也才57600,很明显没超过啊
回复

使用道具 举报

0

主题

17

回帖

562

积分

高级会员

Rank: 4

积分
562
发表于 2023-2-21 16:30:55 | 显示全部楼层
错误是出现在(3600*16)这里的,这个地方只有常量计算,这里的计算会导致结果变成ffff E100。u32并没有定义3600或者16,这个运算里面会出错。
回复

使用道具 举报

5

主题

8

回帖

64

积分

注册会员

Rank: 2

积分
64
 楼主| 发表于 2023-2-23 09:52:47 | 显示全部楼层
userdc 发表于 2023-2-21 16:30
错误是出现在(3600*16)这里的,这个地方只有常量计算,这里的计算会导致结果变成ffff E100。u32并没有定 ...

还是不是很理解,所以这些运算就只能就在代码里面算出来是吗
回复

使用道具 举报

0

主题

17

回帖

562

积分

高级会员

Rank: 4

积分
562
发表于 2023-2-27 13:16:28 | 显示全部楼层
表达式里面的常数声明一下,而不是在括号外面,((u32)3600*16)
回复

使用道具 举报

17

主题

115

回帖

1305

积分

金牌会员

Rank: 6Rank: 6

积分
1305
QQ
发表于 2023-2-27 19:13:22 | 显示全部楼层
你这个问题确实和编译器有关系。
你可以试试
u32 a = 16,a = 3600;
unixtime=unixtime-(a*b);
这样应该没问题。
二哲科技,欢迎联系,帮你解决问题,为你提供方案~
VX:erzhekeji
QQ:1002866443
回复

使用道具 举报

1

主题

3

回帖

64

积分

注册会员

Rank: 2

积分
64
发表于 2023-3-2 14:11:00 | 显示全部楼层
可以把16和3600想象成两个装满水的杯子,而16*3600相当于两个杯子的水直接倒一起,溢出的部分就流走了,剩下一杯满的水。而((u32)16*3600)的作用相当于用一个桶去装两杯水,就不会溢出了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|迪文科技论坛 ( 京ICP备05033781号-1 )

GMT+8, 2025-4-3 10:10 , Processed in 0.032439 second(s), 22 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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