我们都知道C语言中函数传参有两种方式:传值和传址
传值:
实参把值传给形参,但没有传地址,即对实参的修改无效;生成临时变量
核心原理:函数会对形参和中间变量重新分配空间
Void Swap(int pLeft, int pRight)
{
int a=10,b=20;
Swap(a,b);
}
优点:安全(函数的副作用不会影响外部实参),局部变量值的交换对主函数的变量无影响。
缺点:不能通过修改形参来改变外部实参
传地址:
实参把自己的内存地址传给了形参,这样对实参的修改就有效了;同样也生成临时变量-该临时变量为外部实参地址
Void Swap(int* pLeft, int* pRight)
{
int tmp=*pLeft;
*pLeft=*pRight;
*pRight=tmp;
}
优点:节省空间,效率高,改变形参可以修改外部实参
缺点:指针不安全,代码难度提高,可能在不用修改外部实参时反而将其修改了
传地址有以下3种方法:
(1)全局变量(把参数定义为全局变量,一次性分配空间,传地址,函数调用时无需访问直接使用)
(2)指针是传值的,但指针的间接引用是传地址的
(3)数组是传地址的,因为数组对内存要求比较苛刻,系统对数组不再分配空间,而是传地址
实例分析:
例1:
void swap(int x,int y)
{
int tmp=x;
x = y;
y = tmp;
}
int main(void)
{
int a = 3;
int b = 4;
swap(a,b);
}
传值时,在主函数中调用swap()无法改变a,b的值,因为传给swap()的参数实际上是a,b变量的一份拷贝_a,_b,他们和a,b的地址并不一样,当调用完swap后,它所占的内存空间会被释放,所以a,b的值并没有被改变。
例2:
void swap(int* x,int* y)
{
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
}
int main(void)
{
int a = 3;
int b = 4;
swap(&a,&b);
}
传址时,通过调用swap()可以改变a,b的值,因为此时传递的是a,b的地址,在swap()中改变*x,*y的值就相当于在改变a,b的值,因为他们的地址是一样的,即使调用完swap后,它所占的内存空间会被释放,但a,b的值已被改变。
例3:
void getMemory(char* p,int num)
{
p = (char*)malloc(num);
}
int main(void)
{
char* str = NULL;
getMemory(str,10);
strcpy(str,"hello");
printf("%s\n",str);
return 0;
}
运行会报段错误,它和传址调用有区别:getMemory()函数是想改变指针变量str本身的值,而不是改变*str的值,虽然在getMemory()函数中p的值会被改变,但当它调用完后,p会被释放,所以str的值还是为空,要想改变str的值,应该传&str。
通过例子可以看出,不管是传址还是传值都是传的变量的一份拷贝,要想改变变量本身的值,就应该传该变量本身的地址。