我在学习指针过程碰到一个问题,请教大家:
下面程序,单片机上电运行,第一次调用readRom()函数正常,第二次调用读取的数就不对了,也就是说while(1) 里第二个循环就不对了,第一个循环是正确的,第三次以后每次读出数字跟第二次是一样的,如果把指针*p换为全局的,也就是程序最前面定义,就正确了,把*p换成普通变量,也没问题的,请问这是为什么?
.....
.....
[code]
readRom()
{
unsigned char *p,i;
for(i=0;i<8;i++)
{
*p=readbyte(); //读取一个字节
lcd_dis(*p); //显示到LCD
}
}
main()
{
while(1)
{
readRom();
delayms(200); //延时一会
}}
可以单步执行吗?按你说的情况,感觉好像readbyte()函数不成功的样子
单步执行一下,观察readbyte()的运行状况看看
readbyte()是没有问题的,上面我也说了,*p换成全局指针变量和普通变理都是正确的
unsigned char *p,i;
for(i=0;i<8;i++)
{
*p=readbyte(); //读取一个字节
P没有指定空间。。。
程序乱写到别的地方了
C51的话,如果在函数中设置变量,而不加以初始化,且进行了多次调用时,该变量的值可能会延续之前调用函数时遗留的结果,也就是说,该变量所占用的RAM被释放时,并没有清零(我以前遇到过这种情况,用的是keil C51 v2.38)。
另外,最好readbytes() 和 lcd_dis也贴出来,不然仅以目前提供的信息,很难分析出是为什么
看错了,还真是LS哥们说的READBYTE()的问题
如果是READBYTE()的问题,换成全局的指针变量或普通变量怎么会好了呢,问题 就在在readRom()里定义了局部的指针变量才出现问题的,所以说肯定是指针的使用问题,我非常感谢热心帮忙的每一位朋友,但是麻烦认真的看一下我的问题,我之所以不把READBYTE()和 lcd_dis()贴出来,就是因为我不想把你们的思路引到这两个函数上去,而且包括了很多其它的函数,还有硬件时序,因为这两个函数都没有问题,把上面的*p用一般变量完全正常。
unsigned char *p,i; //这里,定义了指针,但没有赋值
for(i=0;i<8;i++)
{
*p=readbyte(); //读取一个字节 //这里,使用了指针,但依然没有赋值,仅仅是对指针指向的内存进行了数据操作
lcd_dis(*p); //显示到LCD //这里,仍然没有涉及到指针本身的值,仅仅是读取了指针指向的内存的值
这里完全是把指针当一般的Uchar来用了,理论上来说这也没什么,只是多了一个值的传递罢了。唯一的风险就是在其他的程序运行中,恰好影响到了我们未知的P的本身的值或其所指向的内存,从而造成其他影响。但是如果在其他的函数中没有点名提到P或固定位置的RAM的话,编译器是不会让上面的事情发生的。所以我们才会说把其他的函数也贴来看看。
PS:C51的RAM很小的,而且在编译时还会涉及的诸多设置的问题,所以不能提供完整的信息的话,想找问题是很难的
谢谢各位,为什么把这个指针放到前面定义就正确了吗,就是全局的
全局指针变量的话,其本身值是固定的,是不会被其他用途占用的,但仍然有其指向的内存被篡改的可能
下面是readbyte的程序
readbyte(void) //读一个字节
{
unsigned char i=0;
unsigned char dat=0;
for (i=8;i>0;i--)
{
DQ=1;
delay(1);
DQ=0;
dat>>=1;
DQ=1;
if(DQ) dat|=0x80;
delay(4);
}
return(dat);
}
readbyte(void)应该没有问题,除了在定义时少了个Uchar,不过影响应该不大
那么lcd_dis(*p)呢
还真是你指针没有分配空间的问题
把指针换成数组就好了
p[1];
pTAGlhb51
gX6GIbENL
指针没有初始化,或者说是指针没有空间分配的问题,那我定义成全局的怎么没有这个问题呢?
- readRom()
- {
- unsigned char *p,i;
- for(i=0;i<8;i++)
- {
- *p=readbyte(); //读取一个字节
- lcd_dis(*p); //显示到LCD
-
- }
- }
这里的指针根本就是浪费(在c51里一个普通指针占用三个字节的ram),而且还用错了,错在没有分配空间就直接使用。直接定义一个unsigned char的临时变量就可以完成了,或者连变量都不需要直接调用lcd_dis(readbyte())。
指针的使用是c语言中的精华,但也最难掌握。指针使用前必须有合法的内存地址。在本例中,指针p根本就没有指向合法的地址,因为是个局部变量,所以会指向随机分配一的个地址,如果拿这个地址来进行操作的话,程序崩溃那是最好的情况。
“指针没有初始化,或者说是指针没有空间分配的问题,那我定义成全局的怎么没有这个问题呢?”
全局变量在编译的时候会出自动初始化为0,也就是unsigned char* p = 0;注意,0地址是一个合法的地址。如果此时0地址恰好没有被占用,那么碰巧可以使用。因为0地址在c语言中是一个特殊的地址,是不应该用来存放实际内容的,仅仅为了比较判断或初始化之用。使用0地址,这绝对是个隐患。所以,并不是因为换成了全局指针就没问题,而且碰巧没问题,仅此而已。指针使用之前必须指向合法的地址。
引用: 引用 17 楼 zhq0306 的回复:
还有问一下,在C51中如何初始化针,或分配空间?
unsigned char a = 5;
unsigned char* p = &a;
这是一种初始化地方法,是严格意义上的初始化(即变量定义的时候同时赋值)。
也可以
unsigned char a = 5;
unsigned char* p = 0;
p = &a;
这种方式严格来算应该是赋值操作,并非初始化。真正的初始化是unsigned char* p = 0这句。
这是静态分配空间的例子,当然也可以动态分配空间然后初始化,但是c51里很少用到动态分配内存的操作,所以基本不用考虑。