1. 程式人生 > >【C語言】兩個變數值的交換——指標

【C語言】兩個變數值的交換——指標

     C語言中交換兩個變數的值可以在主函式中直接實現,也可以通過子函式來實現。下面我們介紹用子函式實現的情況。
    1.將兩個變數的值作為實參直接傳遞,在子函式內部定義一個普通變數來對兩個形參進行交換,並分別在子函式和主函式中列印。
#include <stdio.h>  

void Swap(int a,int b)
{
    int tmp = a;
    a = b;
    b = tmp;
    printf("a=%d,b=%d\n",a,b);
}  
  
int main()
{
    int a = 5;
    int b = 10;
    printf("a=%d,b=%d\n",a,b);
    Swap(a,b);
    printf("a=%d,b=%d\n",a,b);

    return 0;
}
      下面是程式的執行結果:     從程式的執行結果我們可以看出,在子函式內部兩個形參是交換成功了的,但是在主函式中卻沒有。那是為什麼呢?我們進入函式內部來看下。     下面是主函式中a和b的地址及值:      下面是子函式中a和b的地址及值:       可以看出主函式和子函式中a和b的地址不相同,即說明了兩個函式中的變數不是同一個,僅僅是同名而已。這說明了兩個形參已交換成功,但並未傳遞給實參,兩個實參的值並未發生改變。      2.第一種方法中兩個實參並未發生改變,因為其地址並未傳遞給形參。接下來我們把實參的地址傳遞給形參,並且定義一個指標變數來對兩個形參進行交換,並分別在子函式和主函式中列印。
#include <stdio.h>  

void Swap(int *p1,int *p2)
{
    int *tmp = p1;
    p1 = p2;
    p2 = tmp;
    printf("a=%d,b=%d\n",*p1,*p2);
}

int main()
{
    int a = 5;
    int b = 10;
    printf("a=%d,b=%d\n",a,b);
    Swap(&a,&b);
    printf("a=%d,b=%d\n",a,b);

    return 0;
}  
     下面是程式的執行結果:
     可以看出結果還是同樣錯誤。我們進行測試。     下面是主函式中a和b的地址及值:    下面是子函式中a,b,p1,p2的地址及值:    下面是返回到主函式中四個變數的地址及值:      以上測試結果可以說明主函式在給子函式傳參時,傳的是主函式中的兩個變數的地址,但是在子函式中只是把形參p1和p2所指向的變數的地址進行交換,開始p1指向a,p2指向b,交換之後,p1指向b,p2指向a,沒有實質性的將實參a,b的值交換。然後返回到主函式中,a和b依然是原來的值,沒有交換。     3.下面在子函式中將實參值進行交換。
#include <stdio.h>  

void Swap(int *p1,int *p2)  
{  
    int *tmp;  
    *tmp = *p1;  
    *p1 = *p2;  
    *p2 = *tmp; 
    printf("a=%d,b=%d\n",*p1,*p2);  
}  
  
int main()  
{  
    int a = 5;  
    int b = 10;  
    printf("a=%d,b=%d\n",a,b);  
    Swap(&a,&b);  
    printf("a=%d,b=%d\n",a,b); 

    return 0;  
}
    以上方法看似沒有錯誤,但是在執行時程式卻會崩潰:    上邊顯示,變數tmp正在被使用卻沒有被初始化。這種沒有被初始化的指標稱為野指標,也叫懸掛指標。野指標是沒有訪問許可權的地址(指標)。沒有訪問許可權,形參不能正常交換,所以程式崩潰。    4.下面才是正確的寫法。
#include <stdio.h>  

void Swap(int *p1,int *p2)  
{  
    int tmp;  
    tmp = *p1;  
    *p1 = *p2;  
    *p2 = tmp;  
    printf("a=%d,b=%d\n",*p1,*p2);  
}  
  
int main()  
{  
    int a = 5;  
    int b = 10;  
    printf("a=%d,b=%d\n",a,b);  
    Swap(&a,&b);  
    printf("a=%d,b=%d\n",a,b);  

    return 0;  
}  

    由此可以總結出學習指標的一個重要知識點:一個函式的改變要影響另一個函式,兩個條件:1.傳指標;2.解引用。