关于C中函数传参的一点理解

一般来说c传值分为传值与传指针,Java里没有指针,因此只有传值,但是Java里传值分为简单变量传值和引用型变量传值,从本质上来说这两者没啥区别。

下面主要说的是传参时对原变量的影响:

最初练习创建单链表时可能会有这样一种写法:

void Creat_link_list(int n,struct node *head){
   
}


n是单链表节点的个数,head被初始化为null,调用该函数后可能会有人直接对head进行各种操作,比如遍历,排序。但此时head依然为null,函数内的一列操作只是head副本的操作,当函数调用结束后这个副本也就被系统释放了,对此这里一般有两种改法:

(1):

struct node *Creat_link_list(int n,struct node *head){
   ..........
   ..........
   return head;
}

可以直接将函数里的head返回,这是一种非常重要的方法,特别是在递归代码中,这种写法很常见
(2):

void Creat_link_list(int n,struct node * &head){
   
}

采用引用传参,c++里采用的一种传参方式,形参与实参共用一个内存单元,对形参进行操作,实参自然也受到影响,一般来说这是一种很好也可以用来偷懒的方法(o(╯□╰)o)。

接下来大家可以看看严书里关于二叉排序树的删除操作:

特别是删除的关健操作:

void Delete(BiNode *&p){
  if(p->rchild==NULL){
   struct BiNode *q;
   q=p;
   p=p->lchild;
   free(q);
  }
  else if(p->lchild==NULL)
  {
   struct BiNode *q;
   q=p;
   p=p->rchild;
   free(q);
  }
  else{
  struct BiNode *q,*s;
  q=p;
  s=p->lchild;
  while(s->rchild){
   q=s;
   s=s->rchild;
  }
  p->data=s->data;
  if(q!=p)
  q->rchild=s->lchild;
  else
  q->lchild=s->lchild;
  free(s);
  }
}

 删除核心代码:

   q=p;
   p=p->rchild;
   free(q);

这与平时对单链表的删除操作明显有区别,没有找到前驱节点,而直接将指向当前节点的指针指向下一个节点,这种写法一般来说是错误的,但因为这里采用的引用传参,保证了删除操作的正确性。

比如删除单链表中所有偶数节点的操作:

void Delete_even(struct node *&head){
  struct node *q,*tmp;
   tmp=head;
  while(tmp->next){
   if(tmp->next->res%2==0)
   {
    q=tmp->next;
    tmp->next=q->next;
    free(q);
   }
   else 
   tmp=tmp->next;
  }
}

依然是先找先找前驱节点。

这里给出一种不找到前驱节点的方法,依然是采用引用传参和递归。

void DeleteNode(struct node* &p){
   struct node *q;
   q=p;
   p=p->next;
   free(q);
}

void DeleteBFS(struct node * &p,int key){
   if(p->data==key){
     DeleteNode(p);
    return ;
   }
   else
    DeleteBFS(p->next,key);
}

总的来说,遇到指针时,一般来说需要考虑的问题就是改变指针的指向或者是改变指针所指向的内容(o(╯□╰)o)。

posted @ 2016-08-12 09:27  哦摩西罗伊  阅读(382)  评论(0编辑  收藏  举报