值傳遞/指針傳遞

在這篇博客裏面,我主要講一下值傳遞,參數傳遞
一步一步深刻剖析,所有由代碼來講話
#include <stdio.h>
#include <stdlib.h>

//這裏爲形參從新分配一個存儲單元
//因此形參的改變不影響實參
//因此獲得的打印值是a1=0,a2=0
void swap1(int x,int y)
{
            x=1;
            y=1;
}

//一級指針x指向的是a的地址
//*x就是a的地址中存的值,也就是a的值,
//因此改變*x就是改變a的值
void swap2(int *x,int *y)
{
            *x=2;
            *y=2;
}

//這裏直接就是x和a指向同一片內存區,
//x只不過是a的別名,因此改x就是改a
//可是這個在c裏面是編譯通不過的,由於c裏面尚未引用
//惋惜,我以爲引用真是個好東西
void swap3(int &x,int &y)
{
             x=3;
             y=3;
}

int main()
{
         int a=0,b=0;
    
         swap1(a,b);
         printf( "a1=%d,b1=%d\n",a,b);
//這裏必定要注意,若是傳的參數是a,b,編譯也不會出錯,由於a,b和地址同樣,都是int類型
//只是把a,b的值當地址傳,傳的地址是不對的,會出現segmentation fault
         swap2(&a,&b);
         printf( "a2=%d,b2=%d\n",a,b);
    
         swap3(a,b);
         printf( "a2=%d,b2=%d\n",a,b);
}

在進一步,傳指針的時候怎麼辦?
#include <stdio.h>
#include <stdlib.h>

//這裏新建一個指針,由於函數調用的緣由,初始化指向 NULL
//可是在函數裏面,指針指向了新的地址&temp
//可是,和實參a沒有什麼關係
//因此a的地址依舊爲 NULL(0),
//問這個地址中的值,固然會出現segmentation fault
void func1(int *x)
{
            int temp=11;
            printf( "&temp=0x%x\n",&temp);
            x=&temp;
}

//執行函數調用爲int **x=&a
//x爲二級指針,所指向的地址爲&a,也就是存一級指針的那個地址
//*x爲一級指針,爲*(&a)=a;所指向的地址爲存int類型值的那個地址
//a本來是指向 NULL的,可是這裏*x=a把它強制指向了另一個地址&temp
//這樣實參a的地址的獲得了改變,但是值不是22
//由於temp這裏是棧,函數過了,站也就銷燬了,因此值就靠不住了
//怎麼辦?
//temp移到全局區域去,這樣就是堆了,要不malloc,也是堆
void func2(int **x)
{
            int temp=22;
            printf( "&temp=0x%x\n",&temp);
            (*x)=&temp;
    
}

//這個函數就是用malloc來實現堆的
//給*x=a從新malloc一片存儲區,而後指定這個地址上存33這個數
void func3(int **x)
{
            *x=(int *)malloc(4);
            **x=33;
}
int main()
{
         int *a;
         a= NULL;
/*    
         func1(a);
         printf( "0x%x\n",a);
         printf( "%d\n",*a);
*/
/*
         func2(&a);
         printf( "0x%x\n",a);
         printf( "%d\n",*a);
*/
///*
         func3(&a);
         printf( "0x%x\n",a);
         printf( "%d\n",*a);
//*/
}
最後,我舉一個單鏈表的操做的實例,覺得我以爲它也是涉及二級指針中一個蠻不錯的例子,並且我在網上都沒有找到在個人電腦上立馬編譯經過,能夠執行年該的單鏈表的例子,就從網上下了一個,而後改了下
#include<stdio.h>
#include<stdlib.h>

#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define LIST_INIT_SIZE 100 //線性表存儲空間初始分配量
#define LISTINCREMENT 10     //線性表存儲空間的分配增量

typedef int Status;
typedef int ElemType;
typedef struct LNode
{
      ElemType    data;
      struct LNode    * next;
}LNode,*LinkList;

Status printf_L(LinkList L)
{
       //輸出單鏈表L中的元素
       LinkList p=L;
       while(p-> next)
       {
            p=p-> next;
            printf( "%d,",p->data);
       }
       printf( "\n");
       return OK;
}//printf_L
void CreateList_L(LinkList *L)
{
        //單鏈表初始化
        //逆位序輸入n個元素的值,創建帶表頭結點的單鏈線性表L
        int i,n;
        (*L)=(LinkList)malloc(sizeof (LNode));
        (*L)-> next= NULL;                    //創建一個帶頭結點的單鏈表
        printf( "n=");
        scanf( "%d",&n);
        printf( "\ndata=");
         for(i=n;i>0;--i)
        {
              LinkList p=(LinkList)malloc(sizeof(LNode));    //生成新結點                                                        
              scanf( "%d",&(p->data));                       //輸入元素值
              p-> next=(*L)-> next;                            //插入到表頭
              (*L)-> next=p;
         }
}//CreateList_L

Status ListInsert_L(LinkList *L,int i,ElemType e)
{
          //在帶頭結點的單鏈線性表L中第i個位置以前插入元素e
          LinkList p=(*L);
          int j=0;
           while(p&&j<i-1)
          {
               //尋找第i-1個結點
               p=p-> next;
               ++j;
           }
            if(!p||j>i-1)
                 return ERROR;                   //i小於1或者大於表長+1
           LinkList s;
           s = (LinkList)malloc( sizeof (LNode)); //生成新結點
           s->data=e;
           s-> next=p-> next;
           p-> next=s;
           return OK;
}//ListInsert_L

Status ListDelete_L(LinkList *L,int i,ElemType *e)
{
          //在帶頭結點的單鏈線性表L中,刪除第i個元素,並由e返回其值
          LinkList p=(*L);
          int j=0;
           while (p-> next&&j<i-1)
          {
               //尋找第i-1個結點,並令p指向其前驅
               p=p-> next;
               ++j;
          }
           if(!(p-> next)||j>i-1) return ERROR; //刪除位置不合理
          LinkList q=p-> next;                      //刪除並釋放結點
          p-> next=q-> next;
          (*e)=q->data;
          free(q);
          return OK;
}//ListDelete_L

int main()
{
         LinkList La,Lb;
         int e;
         //建立一個鏈表,而且插入
         CreateList_L(&La);
         printf( "\nLa=");
         printf_L(La);

         ListInsert_L(&La,3,7);//往第三個結點處插入7
         printf( "\nInsetLa=");
         printf_L(La);
         printf( "\n");

         //建立一個鏈表,而且刪除  
         CreateList_L(&Lb);
         printf( "\nLb=");
         printf_L(Lb);
         ListDelete_L(&Lb,4,&e);//刪除第四個結點,並獲得第四個結點的值
         printf( "\nDeleteLb=");          printf_L(Lb);          return 0; }
相關文章
相關標籤/搜索