问题
在C语言函数参数设置过程中,有些时候总是不能达到预期的效果。书上总是对这个C语言参数传递描述:传值方式、传到调用函数的是副本,然后就是常规的swap函数说明这个问题,但是还是不能以swap描述所有的问题,看了这个例子总是给人一种感觉:考虑到要在函数内部改变数据,在调用函数里边也真正改变了数据就用指针,这个感觉还是有漏洞,需要完善一下这个规则。
C语言参数传递:传值方式
有传值方式,还有传引用方式,传引用方式就是实参和形参是同一个变量(地址都一样,使用使用同一个内存),这个主要在C++里边。对于传值方式,就是在一个函数里边,通过形参传进来的是这个变量的一个副本,大小或者值是一样的,但是不是一样的存储地址:简单理解一下---传进去的值是一样的,但是样品,函数调用结束后,传进去的那个值没变。
值没变?那swap(&a,&b)怎么实现的呢:
似乎总是没有认真想想传值方式,传进去的是地址&a,调用结束以后a的地址当然没变了,变的是a里边存储的值。
另外还有一种情况:
/*
* 使用链表表示多项式
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct list_poly *list_point;
typedef struct list_poly{
float coef;
int expon;
list_point link;
}list_poly;
void add(list_point *front,list_point *rear,float coef,int expon);
void adderror(list_point front,list_point rear,float coef,int expon);
//list_point front=NULL;
//list_point rear=NULL;
int main(int argc,char *argv[])
{
list_point front=(list_point)malloc(sizeof(list_poly));
list_point rear=NULL;
front->coef = 9.9;
front->expon = 7;
front->link = NULL;
rear = front;
adderror(front,rear,5.1,5);
adderror(front,rear,4.7,3);
adderror(front,rear,2.5,2);
adderror(front,rear,1.3,1);
for(;front;front=front->link){
printf("coef = %3.1f,expon = %3d",front->coef,front->expon);
printf("\n");
}
printf("\n");
printf("coef = %3.1f,expon = %3d",rear->coef,rear->expon);
printf("\n");
return 0;
}
void adderror(list_point front,list_point rear,float coef,int expon)
{
list_point new = (list_point)malloc(sizeof(list_poly));
new->coef = coef;
new->expon = expon;
new->link = NULL;
if(front){
rear->link = new;
rear = new;
//printf("coef = %3.1f,expon = %3d",(*rear)->coef,(*rear)->expon);
//printf("\n");
}
else{
front = new;
rear = new;
//printf("front2 = %d\n",*front);
}
}
上面就是一个简单例子----改变传指针就行的观点。
一个简单的使用链表表示多项式的例子,需要往链表后边陆续加上多项式的每一项。但是结果总是没有加到后边。
解释一下上面的程序:list_point 是一个类指针,后面的两个front和rear都是一个结构图指针(刚开始是NULL),front始终指向的链表的开始,而rear始终指向的链表的尾,插入一个多项式成员,rear往后移一个。
但是上面没有达到预期的效果-------想了想,我是传的指针呀,函数的形参也声明的是指针呀,这个情况就像下面这个:
swap(int a,int b)
{
int t;
t = a;
a = b;
b = t;
}
调用结束以后,a、b都还是原来的值,嗯嗯,与传值方式的性质:不改变传进去的值相符合。不同的是我这可传的指针呀!!!按原来的传指针就行的观念是对的呀
那上面链表的程序问题出哪了,我们传进去的是一个指针,调用结束以后指针没变,嗯嗯,这里是对的,但是我们在adderror函数里边有:
rear = new;
这就有问题了,我们试图改变我们传进去的指针,函数里边是改变了,出来句恢复原样了。
这个函数应该改成:
//在函数声明和函数实体处改成:
void add(list_point *front,list_point *rear);
//在调用时,改成
add(&front,&rear,5.1,5)
按上面的核心思想:我们虽然声明的是一个指针,但是我们希望在程序里边移动这个指针,因此需要传入指针的指针。
总结:
在变量---变量的指针---变量的指针的指针,这个等级上理解,传入的值不变,想改变这个值,就需要传这个值的指针。