C51指针问题请教

qingyin   2010-4-22 08:57 楼主
我在学习指针过程碰到一个问题,请教大家:
   下面程序,单片机上电运行,第一次调用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); //延时一会
}}


回复评论 (25)

可以单步执行吗?按你说的情况,感觉好像readbyte()函数不成功的样子
单步执行一下,观察readbyte()的运行状况看看
点赞  2010-4-22 09:17
readbyte(); ????
点赞  2010-4-22 09:43
readbyte()是没有问题的,上面我也说了,*p换成全局指针变量和普通变理都是正确的
点赞  2010-4-22 09:49
unsigned char *p,i;
  for(i=0;i<8;i++)   
  {
  *p=readbyte(); //读取一个字节

P没有指定空间。。。

程序乱写到别的地方了

点赞  2010-4-22 10:04
C51的话,如果在函数中设置变量,而不加以初始化,且进行了多次调用时,该变量的值可能会延续之前调用函数时遗留的结果,也就是说,该变量所占用的RAM被释放时,并没有清零(我以前遇到过这种情况,用的是keil C51 v2.38)。

另外,最好readbytes() 和 lcd_dis也贴出来,不然仅以目前提供的信息,很难分析出是为什么
点赞  2010-4-22 10:06
看错了,还真是LS哥们说的READBYTE()的问题
点赞  2010-4-22 10:08
如果是READBYTE()的问题,换成全局的指针变量或普通变量怎么会好了呢,问题 就在在readRom()里定义了局部的指针变量才出现问题的,所以说肯定是指针的使用问题,我非常感谢热心帮忙的每一位朋友,但是麻烦认真的看一下我的问题,我之所以不把READBYTE()和 lcd_dis()贴出来,就是因为我不想把你们的思路引到这两个函数上去,而且包括了很多其它的函数,还有硬件时序,因为这两个函数都没有问题,把上面的*p用一般变量完全正常。
点赞  2010-4-22 10:38

9楼 max 

unsigned char *p,i;                      //这里,定义了指针,但没有赋值
  for(i=0;i<8;i++)   
  {
  *p=readbyte(); //读取一个字节             //这里,使用了指针,但依然没有赋值,仅仅是对指针指向的内存进行了数据操作
  lcd_dis(*p); //显示到LCD                //这里,仍然没有涉及到指针本身的值,仅仅是读取了指针指向的内存的值

这里完全是把指针当一般的Uchar来用了,理论上来说这也没什么,只是多了一个值的传递罢了。唯一的风险就是在其他的程序运行中,恰好影响到了我们未知的P的本身的值或其所指向的内存,从而造成其他影响。但是如果在其他的函数中没有点名提到P或固定位置的RAM的话,编译器是不会让上面的事情发生的。所以我们才会说把其他的函数也贴来看看。

PS:C51的RAM很小的,而且在编译时还会涉及的诸多设置的问题,所以不能提供完整的信息的话,想找问题是很难的
点赞  2010-4-22 11:12
谢谢各位,为什么把这个指针放到前面定义就正确了吗,就是全局的
点赞  2010-4-22 11:21
全局指针变量的话,其本身值是固定的,是不会被其他用途占用的,但仍然有其指向的内存被篡改的可能
点赞  2010-4-22 11:28
下面是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);
}
点赞  2010-4-22 11:30
readbyte(void)应该没有问题,除了在定义时少了个Uchar,不过影响应该不大
那么lcd_dis(*p)呢
点赞  2010-4-22 11:44
还真是你指针没有分配空间的问题

把指针换成数组就好了

p[1];
点赞  2010-4-22 12:05

pTAGlhb51



gX6GIbENL
点赞  2010-4-22 12:25
指针没初始化就使用了。
点赞  2010-4-22 12:36
指针没有初始化,或者说是指针没有空间分配的问题,那我定义成全局的怎么没有这个问题呢?
点赞  2010-4-22 15:28
还有问一下,在C51中如何初始化针,或分配空间?
点赞  2010-4-22 15:44

  1. readRom()
  2. {
  3. unsigned char *p,i;
  4.   for(i=0;i<8;i++)   
  5.   {
  6.   *p=readbyte(); //读取一个字节
  7.   lcd_dis(*p); //显示到LCD
  8.   
  9.   }
  10. }

这里的指针根本就是浪费(在c51里一个普通指针占用三个字节的ram),而且还用错了,错在没有分配空间就直接使用。直接定义一个unsigned char的临时变量就可以完成了,或者连变量都不需要直接调用lcd_dis(readbyte())。
指针的使用是c语言中的精华,但也最难掌握。指针使用前必须有合法的内存地址。在本例中,指针p根本就没有指向合法的地址,因为是个局部变量,所以会指向随机分配一的个地址,如果拿这个地址来进行操作的话,程序崩溃那是最好的情况。

“指针没有初始化,或者说是指针没有空间分配的问题,那我定义成全局的怎么没有这个问题呢?”
全局变量在编译的时候会出自动初始化为0,也就是unsigned char* p = 0;注意,0地址是一个合法的地址。如果此时0地址恰好没有被占用,那么碰巧可以使用。因为0地址在c语言中是一个特殊的地址,是不应该用来存放实际内容的,仅仅为了比较判断或初始化之用。使用0地址,这绝对是个隐患。所以,并不是因为换成了全局指针就没问题,而且碰巧没问题,仅此而已。指针使用之前必须指向合法的地址。
点赞  2010-4-22 15:50
引用: 引用 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里很少用到动态分配内存的操作,所以基本不用考虑。


点赞  2010-4-22 15:55
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复