从一个简单的例子深入看待c语言指针

来源:互联网 发布:人体 3d 软件 编辑:程序博客网 时间:2024/06/05 06:36

   今天我在写二叉树程序时遇到一个让我郁闷整晚的例子,现在终于想通了,特撰此博文,告诫自己及广大同道今后勿犯此错误!

我写了一个将字符串中括号去除的程序:(转载请注明出处:Grim_Rapier:http://blog.csdn.net/pq159753159/article/details/17342999)

#include<stdio.h>
char *RidBracket(char*);
void main()
{
 char *sOldBiTree="qwe(123)";
 char *sBiTree=RidBracket(sOldBiTree);
 puts(sBiTree);
}
char *RidBracket(char *pStr)
{
 char *pRslt=pStr;
 int i=0,j=0;
 for(i=0;pStr[i]!=0;i++)
  if(pStr[i]!='(' && pStr[i]!=')')
   pRslt[j++]=pStr[i];
 pRslt[j]=0;
 return pRslt;
}

此程序乍一看很精简也很正常,但运行后便会出现“非法访问内存的错误”。我仔细推敲,甚至将其反汇编后检查它的汇编代码,仍不理解错在何处?

细心的读者会发现我在RidBracket函数体内的第一句话是:直接将原字符串地址赋给新指针。本来打算利用此语句既实现分配空间,又确保不浪费

太多空间的效果,没想到适得其反。赋值后,两个指针同时指向同一空间,但程序第一次运行到 pRslt[j++]=pStr[i];就异常中止了。但错误之根本并不在于此!

    后来,我又经过反复测试并研究其汇编代码,终于找到了问题的关键(虽然当时熬到凌晨,困,但兴奋)。为深刻阐述,再举个更简单的例子:

    考虑这两段程序:

1.

#include<stdio.h>
void main()
{
 char p[9]="12345";
 p[2]='2';
 puts(p);
}

2.

#include<stdio.h>
void main()
{
 char *p="12345";
 p[2]='2';
 puts(p);
}
都能编译通过,但只有程序1能正确运行,原因何在?

先看其汇编代码:

1.

       char p[9]="12345";
0040D9E8   mov         eax,[string "1234" (00422f98)]
0040D9ED   mov         dword ptr [ebp-0Ch],eax
0040D9F0   mov         cx,word ptr [string "1234"+4 (00422f9c)]
0040D9F7   mov         word ptr [ebp-8],cx
0040D9FB   xor         edx,edx
0040D9FD   mov         word ptr [ebp-6],dx
0040DA01   mov         byte ptr [ebp-4],dl

2.

      char *p="12345";
0040D9E8   mov         dword ptr [ebp-4],offset string "1234" (00422f98)

char *p="12345";的汇编比较简单,而问题的关键就在于此!

  我简单翻译一下它们的含义:

汇编1:在主调函数的栈空间上腾出9字节空间(确切为12byte)存储字符串“1234”;

汇编2:直接将内存00422f98处定义的字符串“1234”的地址即00422f98本身保存在主调函数空间内

当我们访问字符串时,两种方法都可以将其打印输出;对于主调函数空间中存储的数据可以读写;对于堆中(即其它内存块)中的数据,由于是在程序申请的执行空间中定义的
故只能读不能覆盖,如果重写之,则等于改写了原程序,破坏了原程序的状态(也可以解释为改写了程序栈空间外的内存,这是操作系统所不允许的)。

因此,由于程序1是在主调函数中的栈空间操作数据,程序2试图改写堆中的数据,只有程序1能正确运行。

再看本文开头的程序main函数的第一句是:char *sOldBiTree="qwe(123)";而被调函数RidBracket试图对"qwe(123)"的地址进行写操作,这是不允许的。

此类错误一般极难发现,因此,在今后的编程中,应尽量采用char p[9]="12345";的方式定义字符串!

(转载请注明出处:Grim_Rapier:http://blog.csdn.net/pq159753159/article/details/17342999)

0 0
原创粉丝点击