C语言传值操作

来源:互联网 发布:jdbc连接oracl数据库 编辑:程序博客网 时间:2024/06/01 07:27


    C语言中的函数参数传递都是传值操作,所以要使被调用函数改变调用函数的属性内容,则需要传递所需修改属性的指针——属性地址。

   例1:

C代码
  1. void GetMemory(char *p)  
  2. {  
  3.     p = (char *)malloc(100);  
  4. }  
  5.   
  6. void Test(void)  
  7. {  
  8.     char *str = NULL;  
  9.     GetMemory(str);   
  10.     strcpy(str, "hello world");  
  11.     printf(str);  
  12. }  

 

    请问运行Test函数会有什么样的结果?

    答:因为GetMemory函数接收的是str指针的拷贝,所以,当其退出时,str的拷贝p在栈中的内容会被释放,并且以上操作对Test函数中的str没有影响,str一直都是 NULLstrcpy(str, "hello world");将使程序崩溃。

 
   例2:
C代码
  1. Void GetMemory2(char **p, int num)  
  2. {  
  3.     *p = (char *)malloc(num);  
  4. }  
  5.   
  6. void Test(void)  
  7. {  
  8.     char *str = NULL;  
  9.     GetMemory(&str, 100);  
  10.     strcpy(str, "hello");    
  11.     printf(str);     
  12. }  
 

    请问运行Test函数会有什么样的结果?

    答:1)能够输出hello;2)内存泄漏

     原因:以上两个对照说明形参只能传递地址不能传递值。

  例3:

C代码
  1. char *GetMemory(void)  
  2. {    
  3.     char p[] = "hello world";  //此行将p[]改成*p就对了,此时p[]存在  
  4.     return p;                         //于栈里边,*p的话字符串存于常量区  
  5. }  
  6.   
  7. void Test(void)  
  8. {  
  9.     char *str = NULL;  
  10.     str = GetMemory();  
  11.     printf(str);  
  12. }  

 

请问运行Test函数会有什么样的结果?

 

    请问运行Test函数会有什么样的结果?

    答:可能是乱码。因为GetMemory返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但其原现的内容已经被清除,新内容不可知。

  例4:

C代码
  1. void Test(void)  
  2. {  
  3.     char *str = (char *) malloc(100);  
  4.     strcpy(str, “hello”);  
  5.     free(str);  
  6.     if(str != NULL)  
  7.     {  
  8.       strcpy(str, “world”);  
  9.       printf(str);  
  10.      }  
  11. }  
 

   答:篡改动态内存区的内容,后果难以预料,非常危险。

   因为free(str);之后,str成为野指针,

   if(str != NULL)语句不起作用。谨记malloc之后一定记得free,free之后将指针NULL一下,以免形成野指针。
 
  以下摘自其他地方:
 例5:
C代码
  1. void GetMemory(char **p,int num)  
  2. {   
  3.     /*p,指向指针的指针,*p,p指向的指针(即str),**p,最终的对象,str指向的单元*/  
  4.   *p=(char *)malloc(num);    
  5.     //申请空间首地址付给传入的被p指向的指针,即str  
  6. }    
  7.     
  8. int main()  
  9. {  
  10.          char *str=NULL;  
  11.    GetMemory(&str,100);   //传入指针变量本身的地址  
  12.    strcpy(str,"hello");  
  13.    free(str);  
  14.    if(str!=NULL)  
  15.    {  
  16.       strcpy(str,"world");  
  17.    }         
  18.    printf("/n str is %s",str); 软件开发网 www.mscto.com  
  19.    getchar();  
  20. }    
 
  问输出结果是什么?
  
   答案:输出str is world。
  free 只是释放的str指向的内存空间,它本身的值还是存在的.所以free之后,有一个好的习惯就是将str=NULL.此时str指向空间的内存已被回收,如果输出语句之前还存在分配空间的操作的话,这段存储空间是可能被重新分配给其他变量的,尽管这段程序确实是存在大大的问题(上面各位已经说得很清楚了),但是通常会打印出world来。这是因为,进程中的内存管理一般不是由操作系统完成的,而是由库函数自己完成的。当你malloc一块内存的时候,管理库向操作系统申请一块空间(可能会比你申请的大一些),然后在这块空间中记录一些管理信息(一般是在你申请的内存前面一点),并将可用内存的地址返回。但是释放内存的时候,管理库通常都不会将内存还给操作系统,因此你是可以继续访问这块地址的。

 

转载自:[http://lhg803.javaeye.com/blog/417858]

原创粉丝点击