要理解你这个问题,你必须首先明白传值和传指针的区别。
给一个函数传值,实参会把具体的值传给函数的形参,函数拿到这个值以后会产生一个临时变量(这个临时变量你是看不到的),你的整个函数的 *** 作就是在 *** 作这个临时变量,所以你在函数内部给,形参赋值并不能改变实参的值。
给一个函数传指针,实参会把外部存储值的地址给形参,注意这是地址,证明外部已经申明了存储该实参值的内存,不然不会存在存储某值的地址,所以内部不再需要分配空间;当然有的时候我们的实参只申明了一个指针,并没有申请地址,这个时候编译是没有问题的,但是在运行的时候我们会把实参指向的内容的地址传给形参,而此时实参并没有申请空间,这个时候就会出现一个错误。
所以,当我们传递给函数一个指针的时候,我们的目的是要 *** 作某一块内存,既然要 *** 作某一块内存,那么这块内存首先必须存在,既然已经存在在函数内部在分配空间就没有必要,即使分配了也没有任何意思,如果不释放还会出现内存泄露情况
形参:全称为"形式参数"是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传如的参数
实参:全称为"实际参数"是在调用时传递个该函数的参数
形参和实参的类型必须要一致,或者要符合隐含转换规则,
当形参和实参不是指针类型时,在该函数运行时,形参和实
参是不同的变量,他们在内存中位于不同的位置,形参将实
参的内容复制一份,在该函数运行结束的时候形参被释放,
而实参内容不会改变
而如果函数的参数是指针类型变量,在调用该函数的过程
中,传个函数的是实参的地址,在函数体内部使用的也是
实参的地址,即使用的就是实参本身所以在函数体内部
可以改变实参的值
给你一个很简单的例子:
int f(int b) /b为形参/
{ return b;}
main()
{int a=1; <br>printf("%d",f(a));/a为实参/ <br>}
字符指针,可以指向1个字符的地址。
字符串:表示为一个连续内存的多个字符地址
所以1个字符的地址也表示了以这个字符地址开头的任意长度的字符串。(前提要申请内存空间)
所以这里a既表示了其指向的字符地址 也表示了以a指向地址开头的字符串
相当于字符数组。所以会有上面代码的写法。
情况1 需要读入的数据是比较大的数据,使用指针作为参数可以节省堆栈
比如 定义1个结构体
typedef struct test
{
char buffer1[10000];
char buffer2[10000];
//后面还有一大堆成员
}test_ts;
void Func1(test_ts t1)
{
//函数体是对t1成员进行Read处理
}
void Func2(test_ts t1)
{
//函数体是对t1成员进行Read处理
}
上面2个函数功能其实一样,但函数Func2参数只是一个指针占的空间就4 Byte,
Func1参数是一个结构体,占的空间就看成员多少,但例子的使用的堆栈最少20000Byte了。
情况2 需要对数据进行改写
一般对应的数据是数组或结构体数据。
比如memset函数函数,用于把传入指针的数据写入对应的数据。
具体函数体内容不贴了,baidu查下吧。
例如还是这个结构体test_ts
test_ts t2;
如果需要将t2的每个成员初始化成0,可以把每个成员挨个赋值成0。
但如果用下面这样代码
memset(&t2,0,sizeof(t2));
一行搞定
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)