C-请大神详细讲解一下指针参数是如何传递内存的?
viod GetMemory(char *p,int num)
{
p=(char *)malloc(sizeof(char)*num);
}
void Test(void)
{
char *str=NULL;
GetMemory(str,100);//str仍为NULL
strcpy(str,"hello");//运行出错
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
其实即使是指针,也只是一个值。
那么这样理解,无论函数参数是什么类型,都是按照传递一份拷贝进去的,就算是指针也是一样。本例中,GetMemory(str,100)这句话,实际上传递的也是str指针的值null进去。所以其实GetMemory(char *p, int num)中的p指针实际上是一个临时变量,只是存储了和str一样的值而已。所以在函数中改变的指针p的值只是改变了函数参数中临时变量的值,与str实际上是一点关系都没有,str还是null。
那么传指针究竟是什么作用呢?虽然指针的值也是一份拷贝进去的,但是由于拷贝的值的特殊性,因为指针的值实际上就是一个地址,那么在调用函数的内部,可以通过传递进来的临时指针变量的值引用指针所指向的内存空间,从而改变所指向空间的值。
所以,传递指针参数,不能改变指针所指向的地址,只能改变指针所指向地址的空间的值。
本质来讲,指针也是一个变量,都会占用内存单元,只是在处理指针变量的时候需要多做一次间址操作。
我对你的程序做些小修改:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void GetMemory(char *p,int num)
{
p=(char *)malloc(sizeof(char)*num);
printf("p=0x%xn", p);
}
int main()
{
char *str=NULL;
printf("str=0x%xn", str);
GetMemory(str,100);//str仍为NULL
printf("str=0x%xn", str);
strcpy(str,"hello");//运行出错
return 0;
}
输出如下:
str=0x0
p=0x544ed8
str=0x0
指针str和p的内容(即指向的内存单元)完全不是一回事,而且程序运行出错是因为str指向的地址是0X0,导致指针越界,程序无法继续执行(linux下出现段错误的提示)。
通过传递指针的地址,可以完成这一任务,如下程序所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void GetMemory(char **p,int num)
{
*p=(char *)malloc(sizeof(char)*num);
printf("p=0x%x; *p=0x%xn", p, *p);
}
int main()
{
char *str=NULL;
printf("&str=0x%x; str=0x%xn", &str, str);
GetMemory(&str,100);
printf("&str=0x%x; str=0x%xn", &str, str);
strcpy(str,"hello");//运行正常
return 0;
}
程序输出如下:
&str=0x1ffa98; str=0x0
p=0x1ffa98; *p=0x4e4ed8
&str=0x1ffa98; str=0x4e4ed8
这样程序就可以达到要求了。
没有“指针参数是如何传递内存的”这一说法吧。
在C语言中,参数的传递时按值传递的。也就是说,无论什么时候,都是传对象的值。在函数中,复制了一份实参值的副本给了形参。通过指针我们能以间接地方式去操作指针所指向的内存块。
viod GetMemory(char p,int num)
{
p=(char *)malloc(sizeof(char)num);
}
p在内存中的位置与str的位置是不同的,它们不是同一内存空间,只是把str的值复制给了p,改变p的值并不影响str的值。假设str的值是0x200002,那么p的值也是0x200002。他们指向同一个内存块。
p=(char )malloc(sizeof(char)num);
这里只是改变了p本身的值,让它指向一个动态分配的内存块。但是str的值并没有改变。
即把p的值改为0x000008,str的值还是0x000000。
void change(char p, char val)
{
p[0] = val;
}
change(str, 'a');
这里是改变了p指向内存块的值,也就相当于改变了str指向的内存块的值。因为它们指向同一块内存。
指针参数和普通类型的参数传值方式没有区别。都是按值传递,只是指针运算和普通类型的运算方式不同而已。假设int p; 那么p+1的意思是,p + sizeof(int),如果p的值是0x000002,那么p+1的值在32位系统下是 0x000006。
传递指针参数,不能改变指针所指向的地址,只能改变指针所指向地址的空间的值。
在函数中改变的指针p的值只是改变了函数参数中临时变量的值,与str实际上是一点关系都没有,str还是null。
要改变指针所指向的地使用指针的指针才行,也就是二级指针,如下代码所示:
viod GetMemory(char **p,int num)
{
*p=(char *)malloc(sizeof(char)*num);
}
你这里要使用指针的指针才行,也就是二级指针:
viod GetMemory(char **p,int num)
{
*p=(char *)malloc(sizeof(char)*num);
}
void Test(void)
{
char *str=NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
}
也就是char* str=NULL,其实是定义str为一个指针变量,变量的值是一个地址A(一般为四个字节长度的数据,这里是0),该地址A指向的内存单元保存的值为char类型,然后我们将str指针变量所在的内存单元的地址B即 &str 传递给了P,当用* p引用的时候就是将malloc得到的地址C赋值到地址B所在内存单元,这样指针变量str的值即* p就变成了地址C,就不是地址A(NULL)了。这样在Test函数中str就相当于* P即地址C,* str就相当于** p即引用地址C所在内存的值。