现在的位置: 首页 > 综合 > 正文

12-3-23关于一级指针,二级指针

2018年01月10日 ⁄ 综合 ⁄ 共 1436字 ⁄ 字号 评论关闭
void  myMalloc(char  *s)  //我想在函数中分配内存,再返回  
{  
     s=(char  *)  malloc(100);  
}  
 
void  main()  
{  
     char  *p=NULL;  
     myMalloc(p);    //这里的p实际还是NULL,p的值没有改变,为什么?  
     if(p)  free(p);  
}  
程序2:void  myMalloc(char  **s)  
{  
     *s=(char  *)  malloc(100);  
}  
 
void  main()  
{  
     char  *p=NULL;  
     myMalloc(&p);    //这里的p可以得到正确的值了  
     if(p)  free(p);  

}  

下面我们来深度分析一下:

关于程序1,myMalloc(char *s),当我们在main()中调用该函数时候,编译器会为函数的每个参数制作临时副本(引用除外),因此指针s的副本为_s,编译器则让

_s=s,如果函数体改变了_s所指向的内容,则s所指向的内容也随之改变,这也是指针可以做参数的原因,但是在本例中,_s申请了新的内存,则_s指向了新内存,

换言之,_s本身的指向地址变了,此时s跟_s所指向的是不同的内存地址,这样s所指向的内容一直没变,每调用该函数一次,会再堆上申请一块内存,长期这样会

导致内存泄露,后果是很严重的。

那么myMalloc(char **s)为什么又是可行的呢,道理是一样的,这是一个二级指针,编译器同样会复制该二级指针_s,由上面的分析过程,一级指针所指向的地址变了,

但是我们二级指针_s与s所指向的一级指针都没发生变化,变的是一级指针指向的内存,这样_s,s都可以通过该一级指针找到那块内存。这样可以达到我们的要求

补充一句,如果真想利用一级指针申请动态内存,可以改动该函数的返回值,即可。

下面我们再来看一个返回栈指针的例子。:

程序3:char  *GetString(void)  
{  
           char  p[]  =  "hello  world";  
           return  p;            //  编译器将提出警告  
}  
void  Test4(void)  
{  
char  *str  =  NULL;  
str  =  GetString();            //  str  的内容是垃圾  
cout<<  str  <<  endl;  
}  
程序4:char  *GetString2(void)  
{  
           char  *p  =  "hello  world";  
           return  p;  
}  
void  Test5(void)  
{  
           char  *str  =  NULL;  
           str  =  GetString2();  
           cout<<  str  <<  endl;  
}  

程序3返回的是栈内存的指针,一旦函数执行完毕,该指针也就是漂浮指针了。但是为什么程序4能够达到我们的要求,因为char *p="hello world",这里是在静态存储区域

申请的一块内存,在程序运行的过程中,一直存在,但是有个缺陷就是他是个只读的区域块。

抱歉!评论已关闭.