C语言传值操作
C语言中的函数参数传递都是传值操作,所以要使被调用函数改变调用函数的属性内容,则需要传递所需修改属性的指针——属性地址。
例1:
void GetMemory(char *p) { p = (char *)malloc(100); } void Test(void) { char *str = NULL; GetMemory(str); strcpy(str, "hello world"); printf(str); }
请问运行Test 函数会有什么样的结果?
答: 因为GetMemory函数接收的是str指针的拷贝 ,所以,当其退出时,str的拷贝p在栈中的内容会被释放,并且以上操作对Test 函数中的str没有影响, str一直都是 NULL , strcpy(str, "hello world"); 将使 程序崩溃。
例2:
Void GetMemory2(char **p, int num) { *p = (char *)malloc(num); } void Test(void) { char *str = NULL; GetMemory(&str, 100); strcpy(str, "hello"); printf(str); }
请问运行Test 函数会有什么样的结果?
答: ( 1 )能够输出hello; (2 )内存泄漏
原因:以上两个对照说明形参只能传递地址不能传递值。
例3:
char *GetMemory(void) { char p[] = "hello world"; //此行将p[]改成*p就对了,此时p[]存在 return p; //于栈里边,*p的话字符串存于常量区 } void Test(void) { char *str = NULL; str = GetMemory(); printf(str); }
请问运行Test 函数会有什么样的结果?
请问运行Test 函数会有什么样的结果?
答: 可能是乱码。 因为GetMemory 返回的是指向“栈内存”的指针,该指针的地址不是 NULL ,但其原现的内容已经被清除,新内容不可知。
例4:
void Test(void) { char *str = (char *) malloc(100); strcpy(str, “hello”); free(str); if(str != NULL) { strcpy(str, “world”); printf(str); } }
答:篡改动态内存区的内容,后果难以预料,非常危险。
因为free(str); 之后,str 成为野指针,
if(str != NULL) 语句不起作用。谨记malloc之后一定记得free,free之后将指针NULL一下,以免形成野指针。
以下摘自其他地方:
例5:
void GetMemory(char **p,int num) { /*p,指向指针的指针,*p,p指向的指针(即str),**p,最终的对象,str指向的单元*/ *p=(char *)malloc(num); //申请空间首地址付给传入的被p指向的指针,即str } int main() { char *str=NULL; GetMemory(&str,100); //传入指针变量本身的地址 strcpy(str,"hello"); free(str); if(str!=NULL) { strcpy(str,"world"); } printf("\n str is %s",str); 软件开发网 www.mscto.com getchar(); }
问输出结果是什么?
答案:输出str is world。
free 只是释放的str指向的内存空间,它本身的值还是存在的.所以free之后,有一个好的习惯就是将str=NULL.此时str指向空间的内存已被回收,如果输出语句之前还存在分配空间的操作的话,这段存储空间是可能被重新分配给其他变量的,尽管这段程序确实是存在大大的问题(上面各位已经说得很清楚了),但是通常会打印出world来。这是因为,进程中的内存管理一般不是由操作系统完成的,而是由库函数自己完成的。当你malloc一块内存的时候,管理库向操作系统申请一块空间(可能会比你申请的大一些),然后在这块空间中记录一些管理信息(一般是在你申请的内存 前面一点),并将可用内存的地址返回。但是释放内存的时候,管理库通常都不会将内存还给操作系统,因此你是可以继续访问这块地址的。
free 只是释放的str指向的内存空间,它本身的值还是存在的.所以free之后,有一个好的习惯就是将str=NULL.此时str指向空间的内存已被回收,如果输出语句之前还存在分配空间的操作的话,这段存储空间是可能被重新分配给其他变量的,尽管这段程序确实是存在大大的问题(上面各位已经说得很清楚了),但是通常会打印出world来。这是因为,进程中的内存管理一般不是由操作系统完成的,而是由库函数自己完成的。当你malloc一块内存的时候,管理库向操作系统申请一块空间(可能会比你申请的大一些),然后在这块空间中记录一些管理信息(一般是在你申请的内存 前面一点),并将可用内存的地址返回。但是释放内存的时候,管理库通常都不会将内存还给操作系统,因此你是可以继续访问这块地址的。