标题: 请问C语言比较数YEAR为什么不能大于255,大于会出错(之前的举例程序有问题) [打印本页]

作者: hym8085hym    时间: 2022-6-30 12:50
标题: 请问C语言比较数YEAR为什么不能大于255,大于会出错(之前的举例程序有问题)
bit volatile ADCY@((unsigned)&sbstatus*8+0;
unsigned short  YEAR;
ADCY=0;YEAR=2000;

for(;;)
{

  YEAR=YEAR+1;
   if(YEAR>=2020)
   ADCY=1;

}


请教一下大神们:unsigned short  YEAR;改为unsigned char  YEAR;就可以编译通过,是不是比较的数据只能用一个8位数据?用16位的数据是不可以直接比较的。我用PICC9.83编译

作者: datouyuan    时间: 2022-6-30 15:02
我用PICC9.83编译你的代码,二者都可以编译通过,并且编译结果(分析汇编代码)是正确的。
用unsigned char会有警告。警告信息如下:
Warning [766] FER039.C; 38. degenerate signed comparison
Warning [766] FER039.C; 38. degenerate signed comparison
Warning [1090] FER039.C; 32. variable "_year" is not used


通常编译器是不会有问题的,你应该检查你的代码。
作者: Y_G_G    时间: 2022-6-30 17:10
我这只有XC8的,但楼上已经帮你测试过了,并没有问题,那就像他说的那样,检查一下你自己的代码
试想一下你也能明白这个道理的,再垃圾的编译器,它也不会到连一个16位数大小都不能比较的地步吧,那三角函数,浮点运算怎么办呢?
作者: Hephaestus    时间: 2022-6-30 21:15
出什么错都不贴出来,让大家盲猜?
作者: xiaoyuxinke    时间: 2022-6-30 21:24
你只是定义一个变量的东东,这个变量定义不能用8位变量,不然只能小于255,也可以用unsigned int 定义一个变量
作者: glinfei    时间: 2022-7-1 09:48
我没有试过,但如果unsigned short 通过不了,我会用 unsigned int 替代的,毕竟给单片机的编译器嘛。
作者: zjswuyunbo    时间: 2022-7-1 10:11
sizeof(unsignd short),看一下这个类型是不是16位
作者: datouyuan    时间: 2022-7-1 11:35
zjswuyunbo 发表于 2022-7-1 10:11
sizeof(unsignd short),看一下这个类型是不是16位

PICC中short是16位。



作者: 17337161031    时间: 2022-7-1 19:35
数据是8位的
作者: hym8085hym    时间: 2022-7-2 10:39
17337161031 发表于 2022-7-1 19:35
数据是8位的

我发现PICC编译器,运算的数据是可以用16位或浮点数,比较数据大小却只能是8位,是这样的吗?我是新手。
作者: hym8085hym    时间: 2022-7-2 10:42
datouyuan 发表于 2022-6-30 15:02
我用PICC9.83编译你的代码,二者都可以编译通过,并且编译结果(分析汇编代码)是正确的。
用unsigned cha ...

我的意思是我发现PICC编译器,能运算浮点数和16位数据,比较数据却只能8位。是不是设置有问题
作者: hym8085hym    时间: 2022-7-2 10:45
xiaoyuxinke 发表于 2022-6-30 21:24
你只是定义一个变量的东东,这个变量定义不能用8位变量,不然只能小于255,也可以用unsigned int 定义一个变量

我的意思啊PICC编译器,浮点数和16位数据运算都不会出错,比较数据8位(char)就正常,16位(int)就出错。
作者: datouyuan    时间: 2022-7-2 10:54
hym8085hym 发表于 2022-7-2 10:39
我发现PICC编译器,运算的数据是可以用16位或浮点数,比较数据大小却只能是8位,是这样的吗?我是新手。

有点烦了。
出现问题,竟然怀疑编译器有问题,而不怀疑自己的代码。
你这新手太牛逼了。
作者: Hephaestus    时间: 2022-7-2 12:11
hym8085hym 发表于 2022-7-2 10:42
我的意思是我发现PICC编译器,能运算浮点数和16位数据,比较数据却只能8位。是不是设置有问题

1)你用的是什么单片机?
2)报错的内容必须贴出来,一句“编译不通过”无法给出足够的信息。
3)最好把代码贴出来。
作者: hym8085hym    时间: 2022-7-2 13:40
datouyuan 发表于 2022-6-30 15:02
我用PICC9.83编译你的代码,二者都可以编译通过,并且编译结果(分析汇编代码)是正确的。
用unsigned cha ...

很奇怪:pic16f884芯片就不会出错;PIC16F676在中断地方比较就会出错,不在中断地方比较就不会出错。
作者: hym8085hym    时间: 2022-7-2 13:42
datouyuan 发表于 2022-7-2 10:54
有点烦了。
出现问题,竟然怀疑编译器有问题,而不怀疑自己的代码。
你这新手太牛逼了。

用PIC16F884芯片就可以通过;用PIC16F676芯片在中断的地方比较就会出错,正常的程序里面不会出错!奇怪的是这个
作者: Hephaestus    时间: 2022-7-2 14:49
PIC16F676只有64bytes RAM,哪里经得起你这么瞎折腾?
作者: Y_G_G    时间: 2022-7-2 15:56
PIC16F676只有64个字节的RAM,比传统8051的128个字节还少
而且,PIC16F676只有8级的硬件堆栈,不知道你对硬件堆栈了解与否?
如果不了解,那就告诉你几个要注意的点
1,函数可以多,但尽量少在函数中调用函数,而你调用的函数中又有调用其它函数的情况
2,中断函数只做一些必需要做的操作,只要能在主函数做的事情,不要在中断中进行,中断函数只做清除中断标志位,或者置位某个标志,用于告诉主程序:这个中断被触发了
我没有认真看这个单片机的数据手册,不知道有没有堆栈满复位功能,如果有,那就使能这个功能,你程序运行后不断复位的,就说明你的代码不行
作者: hym8085hym    时间: 2022-7-7 10:19
Y_G_G 发表于 2022-7-2 15:56
PIC16F676只有64个字节的RAM,比传统8051的128个字节还少
而且,PIC16F676只有8级的硬件堆栈,不知道你对硬件 ...

我之前是用汇编的。想学习C语言,实际上这个程序我定义的RAM不多,提示是不够用。就是不明白C语言的程序是怎么影响到RAM.按理定义是不影响RAM数量的呀
作者: wufa1986    时间: 2022-7-7 10:38
PIC应该不会,只有一些低端单片机才会使用精简C
作者: Y_G_G    时间: 2022-7-7 10:40
hym8085hym 发表于 2022-7-7 10:19
我之前是用汇编的。想学习C语言,实际上这个程序我定义的RAM不多,提示是不够用。就是不明白C语言的程序 ...

你用汇编,就更应该知道RAM和堆栈了,特别是PIC这种使用硬件堆栈的单片机
8级硬件堆栈在汇编上还行,但到了C,函数调用得多了就不知道到底用了几层了,很容易就溢出了
RAM更不用说了,像STC的8051一般都有扩展的SRAM,大多情况下还是够用的
PIC16F676就真真的只有64个字节了,没用过这个单片机,实在不了解64个字节的RAM到底能干多少活
作者: datouyuan    时间: 2022-7-7 10:43
hym8085hym 发表于 2022-7-7 10:19
我之前是用汇编的。想学习C语言,实际上这个程序我定义的RAM不多,提示是不够用。就是不明白C语言的程序 ...
这代码太多问题了。
1.不要大量使用volatile 绝对定位变量。
2.能用自动变量就不要用全局变量。
3.中断服务中使用函数。
4.多处代码逻辑混乱。
5.picc的特有语法使用错误。你这代码功能我猜测是2位数码管显示,只需要标准C语言就能完成,完全不需要用到picc的特有语法。虽然你没定义几个变量,因语法出错,编译提示定义的变量超出了极限。

楼主应要花几天学习下C语言基础。


你在另一个帖子里有完整代码,错误太多。

按理定义是不影响RAM数量,但你错误的代码会。

作者: hym8085hym    时间: 2022-7-7 11:07
Y_G_G 发表于 2022-7-7 10:40
你用汇编,就更应该知道RAM和堆栈了,特别是PIC这种使用硬件堆栈的单片机
8级硬件堆栈在汇编上还行,但到了 ...

之前用汇编,所以内存我控制的很严格;中断里面用到的RAM是不能被优化,所以需要固定地址;我发现又奇怪的是:固定地址编译能通过,如果没固定地址,就提示内存不够,程序都一样的。以下的定义都是用在中断里面的;
能通过的定义:
unsigned char volatile LSEC @ 0X24;
unsigned char volatile HSEC @ 0X25;
unsigned char volatile DIP0 @ 0X26;
unsigned char volatile DIP1 @ 0X27;
unsigned char volatile WEI @ 0X30;
如果以下定义:
unsigned char volatile LSEC ;
unsigned char volatile HSEC ;
unsigned char volatile DIP0 @ 0X26;
unsigned char volatile DIP1 @ 0X27;
unsigned char volatile WEI @ 0X30;
就提示出错:could not find space (1 byte) for variable _HSEC
作者: Y_G_G    时间: 2022-7-7 12:00
hym8085hym 发表于 2022-7-7 11:07
之前用汇编,所以内存我控制的很严格;中断里面用到的RAM是不能被优化,所以需要固定地址;我发现又奇怪 ...

我用的是XC8编译器,没有用过PICC
这个单片机只有8级硬件堆栈,中断的话,PC程序计数器用两个,那就只剩下6级堆栈了
在中断中基本就不能再使用其它函数了,只能做清除标志位之类的操作了
至于,volatile变量,没有那个必要,这种事情留给编译器去做,你没有充分理解硬件和代码如何执行的情况下,盲目的用volatile,只会弄巧成拙
作者: hym8085hym    时间: 2022-7-7 12:30
Y_G_G 发表于 2022-7-7 12:00
我用的是XC8编译器,没有用过PICC
这个单片机只有8级硬件堆栈,中断的话,PC程序计数器用两个,那就只剩下6 ...

我后续用你的编译器试试。谢谢您的回复。
作者: zhxiufan    时间: 2022-7-7 13:30
if(YEAR>=2020)是没有问题的,问题可能出在你的ADCY这个位变量上。
作者: Y_G_G    时间: 2022-7-7 20:04
hym8085hym 发表于 2022-7-7 12:30
我后续用你的编译器试试。谢谢您的回复。

没叫你用XC8呀
我只是我说不没有用过PICC而已
我用XC8是因为买的书上面用的是XC8,所以,就跟着学了
你要学的是C语言方面编程
你倒是可以看一下CCS编译器,这个函数就很多了,像什么PWM,延时,读写SD卡都有的
作者: datouyuan    时间: 2022-7-8 10:49
hym8085hym 发表于 2022-7-7 12:30
我后续用你的编译器试试。谢谢您的回复。

楼主还是在怀疑编译器。
都已经多次指出是楼主代码问题,和编译器无关。

另外楼主懂汇编,应该对比分析编译出来的汇编代码,也可以优化自己的C代码。
作者: MCU_FANS    时间: 2022-7-9 10:15
hym8085hym 发表于 2022-7-7 11:07
之前用汇编,所以内存我控制的很严格;中断里面用到的RAM是不能被优化,所以需要固定地址;我发现又奇怪 ...

你把volatile修饰和强制@地址去掉,让编译器自由分配地址,估计就好了。

另外:新手不要轻易怀疑编译器问题,尤其是一个经过十多年考验的已经相当成熟的编译器。多从自己身上找问题,可以减少不必要的时间浪费。
作者: hym8085hym    时间: 2022-7-9 10:48
datouyuan 发表于 2022-7-8 10:49
楼主还是在怀疑编译器。
都已经多次指出是楼主代码问题,和编译器无关。

奇怪的是:和汇编一样固定地址就编译没问题,编译提示内存用的不多。不固定地址编译就提示内存不够;想不明白啊
作者: liu1337    时间: 2022-7-9 11:20
定义的unsighed int 最大就是255吧,你超过了当然要出错了。如果担心这个问题直接定义Long int

作者: Hephaestus    时间: 2022-7-9 13:48
liu1337 发表于 2022-7-9 11:20
定义的unsighed int 最大就是255吧,你超过了当然要出错了。如果担心这个问题直接定义Long int

懂就回答不懂就算了,你的回复错漏连篇就没有对的地方。

8楼已经贴出来unsigned int是16位,最大是65535。

c语言的优点是你就算是超过范围也不可能在编译阶段报错,楼主的问题你再看一遍。
作者: Y_G_G    时间: 2022-7-9 19:02
这只是一个很简单的问题呀,为什么就折腾了十来天呢?
就那么几十行代码,只要这穿牛角尖,几天就能解决问题
1,不要在中断中有函数,中断只做中断标志位的清除
2,不要给变量自己加上volatile,标准C写就行
3,能用局部变量就不要用全局变量,全局变量在整个程序运行中是一直占用RAM的,局部变量就不一样了
作者: dwb123    时间: 2022-7-9 23:54
本帖最后由 dwb123 于 2022-7-10 16:50 编辑

0-255是8位宽,256就不是了
作者: dwb123    时间: 2022-7-9 23:57
0-255是8位大于255不就是9位了
作者: 不一定会    时间: 2022-7-12 11:40
255 的二进制是1111 1111 ,再加1是啥?




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1