打印

指针为什么不能正确指向

[复制链接]
1532|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
renyaq|  楼主 | 2011-11-21 12:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
如下面的代码所示,一组为Line及其相关的标量,另一组Array及其相关的变量,两组变量的用法几乎完全相同.
//数据表
unsigned char code Line[]={略.............};//起始地址0x0026;
unsigned char code Array[]={略...........};//起始地址0x0058;

//指针声明
unsigned char *pLine, *pBufferLine, *pBegin, *pEnd;
unsigned char *pArray, *pBufferArray;

结果程序中:
pLine=Line; //结果正确,调试窗口显示pLine为 C:0x0026;*pline也是正确值.
pArray=Array; //结果错误,调试窗口显示pArray为 I:0x58;*pArray为错误值.

当我用pLine来指向Array:
pLine=Array; //结果正确,调试窗口显示pLine为 C:0x0058;*pline也是正确值.

当我将pArray的声明移到pLine的声明语句里时.
pLine=Array;//结果错误,pLine为 I:0x58;*pLine为错误值.
pLine=pLine;//结果正确,pLine为 C:0x0058;*pLine为正确值.

旧的程序,没有Array相关的变量,已经用了一年了.是没有问题的.
约2星期前,添加了一些数据表和指针,结果出现了类似上述的问题.没找到原因,我怀疑是程序写乱了.
于是,重新再复制一个工程,换一种算法,但修改程序依然要添加数据表和相关指针.结果依然是新添加的指针不能正确指向.

请问:
1.哪出错了?是我出错还是keil7出错?
2.调试的Variable窗口里,指针变量值前的那个I: 或 C: 是什么意思?
沙发
juventus9554| | 2011-11-21 12:14 | 只看该作者
初学者最容易犯的错误……
新建工程默认优化级别是8,你把它改成0就可以了。
其实归根到底还是自己代码编写不规范的问题.

使用特权

评论回复
板凳
llljh| | 2011-11-21 12:18 | 只看该作者
可能是有指针越界的现象发生,改写了pArray这个指针的内容,keil里面定义一个字符型指针,如果不定义指向的区域,那么这个指针是占3个字节的空间,比如 pArray = Array; pArray的值应该是0xFF0058, 前面那个0xff代表它指向code区。如果程序中有其它指针进行了越界的操作,把存储pArray的0xFF0058改成了0x000058,那么pArray就成了指向数据区的指针了。
调试窗口里的I:和C:应该是代表idata和code的意思。

使用特权

评论回复
地板
renyaq|  楼主 | 2011-11-21 12:27 | 只看该作者
好像是溢出的问题,我程序里实际上是声明为idata的.当我再声明多一个指针时,编译就提示溢出了.
而将它声明为xdata变量时,就指向X:000058.*pArray的结果依然是错误的.

后来省略一部分功能,删掉了一批变量,但没删除idata的变量,结果依然错误.
最后再将idata关键字删掉,就能正常指向了.

使用特权

评论回复
5
renyaq|  楼主 | 2011-11-21 12:31 | 只看该作者
估计与溢出有关.实际程序里是声明为idata变量的,再增加一个指针就提示溢出了.
声明为xdata结果依然错误,显示值为 X:000058.

后删掉部分功能,删掉部分变量,结果依然错误.
最后将idata关键字删掉,其指向就正确了.

使用特权

评论回复
6
supernan| | 2011-11-21 12:35 | 只看该作者
我还碰到更晕的,一个几年前的程序,当时的环境是Keil C51 V7.50。近段时间想作点改动,修改之前,在Keil C51 V8.0x编译,运行结果竟然不对了。
具体原因暂时还没细查。

使用特权

评论回复
7
juventus9554| | 2011-11-21 12:43 | 只看该作者
你应该把实际的程序贴出来。让大家蒙了半天你来一句“实际的程序是这样这样的”……
而且更重要的是让我们看看你声明的idata写在了哪里。
unsigned char idata *pArray;
还是
idata unsigned char *pArray;
这可是很容易出问题的地方。

使用特权

评论回复
8
renyaq|  楼主 | 2011-11-21 12:46 | 只看该作者
忘记了是声明为idata.
代码为"unsigned char idata *pArray;",为局部变量,不过也曾经试过不带idata声明,也试过声明为xdata,但结
果都是错的.
代码已经反复检查过几十次了,我觉得写错代码的可能性非常小,而且代码都是复制自一段旧代码,而这段旧代码
已经用了一年多了.复制过来只改了变量名.代码的声明和使用,都与旧代码是一模一样的.但一个可以用,另一个
却不能用.
我估计还是与寄存器空间有关,编译结果提示data=172.*(小数点数忘记了), code=约50k.

使用特权

评论回复
9
dingy| | 2011-11-21 12:51 | 只看该作者
楼主用指向idata区的指针去指向code区的内容?不会吧,这样不出错才怪。

使用特权

评论回复
10
renyaq|  楼主 | 2011-11-21 13:02 | 只看该作者
需要指定寄存器区域吗?

可同一声明语句"unsigned char idata *pArray, *pBufferArray;"的后一个pBufferArray的指向是正确的哦.而且*pBuffer也是正确的.

当 pArray=pBufferArray; 语句之后, pArray只能得到pBufferArray的低8位,这时刻:
pBufferArray为C:0x0058,*pBufferArray为正确值.
而pArray为I:0x58, *pArray为错误值.

使用特权

评论回复
11
dingy| | 2011-11-21 13:17 | 只看该作者
unsigned char idata *pArray, *pBufferArray;的后一个之所以正确,是因为后面的那个*pBufferArray并没有受idata这个修饰的限制,你可以查查汇编码,指针pBufferArray还是占三个字节空间的,而pArray只占一个字节。如果改成
unsigned char idata *pArray, idata *pBufferArray;
那这两个指针就都不会指向C:0058了。
如果想指向code区的Array,可以这么定义:
unsigned char code *pArray, code *pBufferArray;
如果想让指针指向code区的Array,而指针本身存储在idata区,可以这么定义:
unsigned char code * idata pArray, code * idata pBufferArray;

使用特权

评论回复
12
llljh| | 2011-11-21 13:29 | 只看该作者
开玩笑,根本没错。aa地址0x1a, bb地址0x1b。你看看aa, bb 里是什么?不正是0x55, 0xAA吗?

使用特权

评论回复
13
renyaq|  楼主 | 2011-11-21 13:35 | 只看该作者
原来我一直都是错误地使用idata关键字的

使用特权

评论回复
14
renyaq|  楼主 | 2011-11-21 13:38 | 只看该作者
赶紧结贴

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

700

主题

10138

帖子

4

粉丝