C語言--指針

指針在C語言中的地位很高。記得上大學那會,不是能夠很好的理解指針這個東西,經常一節課下來聽懂的並沒有多少,當然,主要原因是沒好好聽課尷尬。這幾年中對於編程語言的理解更加的進步,漸漸的,也就能夠明白原來指針是這樣的。

指針---就是內存地址。也是一個變量,只是這個變量中保存的數據是其他變量的地址而已。這裏說了指針也是一個變量,那麼指針的聲明應該是和變量的聲明一樣嘍。是的,但也有一點不一樣。

變量的聲明是:type var_name;

指針的聲明是:type *var_name;

type代表變量的數據類型,var_name是變量名,才從上面的對比中可以發現,指針在聲明時,在變量名之前加了一個 * ,這個可以算是指針的標識了。

關於指針變量的類型,必須是有效的C語言數據類型。這個類型指的是指針這個變量所指向的變量的類型。這句話的意思是,無論你聲明一個int類型的指針還是聲明一個char類型的指針,指針對象的類型是一樣的,不同的是指針所指向的那個變量的類型一個是int類型,一個是char類型。下面,聲明幾個指針:

    int *ip;

    double *dp;

    float *fp;

    char *ch;

上面聲明瞭4個指針變量,這4個指針變量的類型是相同的,但是指向的變量的類型不同。

下面,來看看指針的使用。上面我們說到了一個符號: *   下面我們在來說一個符號: &  。

在C語言中,每一個變量都有地址,每一個變量的內存地址,都可以使用&訪問:

    int a = 10;

    printf("%x\n", &a);

打印結果:

5fbff7dc

Program ended with exit code: 0

這裏就是使用 & 去變量a的地址。下面我們來使用 * 這個符號來定義一個指針,用來保存變量a的地址。

    int *ip;

    int a = 10;

    ip = &a;

    printf("%x\n", &a);

    printf("%x\n", ip);

打印結果:

5fbff7f4

5fbff7f4

Program ended with exit code: 0

通過上面的結果我們可以看到,兩個打印結果相同,這裏就證實了,指針就是變量的內存地址。

上面代碼中:ip = &a;是給指針變量賦值的語句,是將變量a的內存地址賦值給指針變量ip。在實際的開發中,有時我在定義指針的時候,並不能知曉要賦何值給這個指針,那麼給指針變量賦一個NULL是一個很好的習慣,這樣的指針是一個空指針。空指針是一個定義在標準庫中的值爲0的常量。

指針的聲明和定義已經說了,下面來說下指針相關的操作和使用:

1、指針的運算。

指針的運算分爲算術運算和邏輯運算,算術運算的符號有:++,--,+,-。邏輯運算符號有:==,<,>,<=,>=。下面逐個說明。

還用上面我們聲明的指針ip,在上面ip的打印結果是5fbff7f4

我們在代碼中加入 ip++; 再打印ip的結果,

    int *ip;

    int a = 10;

    ip = &a;

    printf("%x\n", &a);

    printf("%x\n", ip);

    ip++;

    printf("%x\n", ip);

運行結果:

5fbff7f4

5fbff7f4

5fbff7f8

Program ended with exit code: 0

當我們對ip進行自增運算的時候,其結果比不是+1,而是+4,這是爲何?

我們知道,指針是變量的內存地址,在上面的打印結果也證實了這一點。這樣就很好理解了,我們知道,在內存管理中,int類型的數據在內存中佔有4個字節的內存,所以,ip++就不是簡單的+1,而是加了一個內存空間。ip++後,指向的是變量a的內存地址後面的那個地址了。同理,ip--也不是簡單的-1而是-4。

我們在用代碼來看看+,-運算:

    int *ip;

    int a = 10;

    ip = &a;

    printf("%x\n", &a);

    printf("%x\n", ip);

    ip++;

    printf("%x\n", ip);

    ip -= 2;

    printf("%x\n", ip);

    ip += 1;

    printf("%x\n", ip);

打印結果:

5fbff7f4

5fbff7f4

5fbff7f8

5fbff7f0

5fbff7f4

Program ended with exit code: 0

從打印結果來看,ip+2,也不是直接+2,而是加了兩個int類型的內存空間(也就是8個字節),ip-1也是減去了1個int類型的內存空間(4個字節)。

相對於算術運算,邏輯預算更簡單,指針也是變量,所以指針的邏輯運算和其他變量的邏輯運算相同。這裏就不多說了。



在指針的知識中,還有一個很重要的東西,指針數組。

在上一篇文章中,已經對數組的知識進行了簡單整理,知道了數組的用途很廣泛。可能有一種情況,我們想讓數組存儲的不是直接的變量,而是指向變量的指針,這就要用到指針數組。下面我們來看一個示例:

聲明一個指向int類型的指針數組:

    int a[3] = {10,20,30};

    int *array[3];

    for (int i = 0; i < 3; i++) {

        array[i] = &a[i];

    }

    for (int j = 0; j < 3; j++) {

        printf("a[%d]的地址:%x, 值:%d\n", j, array[j], *array[j]);

    }

打印結果:

a[0]的地址:5fbff7fc, 值:10

a[1]的地址:5fbff800, 值:20

a[2]的地址:5fbff804, 值:30

Program ended with exit code: 0

從代碼和結果來看,array數組就是一個指針數組,存儲了數組a中變量的內存地址。



下面,再來說說指向指針的指針-----二級指針。

指針中存在多級指針的概念,二級指針是最簡單的多級指針。先來看一張圖:


通過上面的圖,很容易發現二級指針,其實就是指向變量內存地址的指針。就如同上面圖裏的那樣,變量a是一個整型變量,值爲100,定義一個指針p指向a,那麼,p中保存的值就是a的內存地址,再用一個指針q指向指針p,q中保存的就是指針p的內存地址。這就是二級指針。

聲明二級指針要用兩個符號 * ,下面是一段二級指針的代碼:

    int a = 100;

    int *p = &a;

    int **q = &p;

    

    printf("a = %d,p = %x,q = %x\n", a, p, q);

    printf("a = %d\n", *p);

    printf("a = %d\n", **q);

    

    printf("p = %x\n", &a);

    printf("p = %x\n", *q);

    

    printf("q = %x\n", &p);

打印結果:

a = 100,p = 5fbff7fc,q = 5fbff7f0

a = 100

a = 100

p = 5fbff7fc

p = 5fbff7fc

q = 5fbff7f0

Program ended with exit code: 0

通過上面的代碼和打印結果,很明顯就可以看出二級指針,指針,變量三者之間的聯繫。這裏要注意一點不能使用&&a的方式來獲取a變量的二級指針。


還有一點關於指針的使用時將指針作爲函數的參數,或者作爲函數的返回值。指針也是變量,這樣的話,作爲函數的參數就很好理解了,只是在函數定義的時候,將形參定義爲指針即可。我們說的main函數就有一個指針數組作爲形參。還有將指針作爲函數的返回值,這個需要在函數聲明時,返回值類型是指針,如:int *getMax();這樣就可以返回一個指針了。另外需要注意一點,C語言中不允許,在函數外返回局部變量的地址,想要返回局部變量,可將局部變量修飾我static變量。








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章