C之指針(二十四)

        在 C 語言中用的最多的就是指針了,指針一樣也是 C 語言的精華所在了。咱們今天就來看看指針究竟是什麼,它是如何使用的。面試

        咱們先來回想下變量,在程序中的變量只是一段存儲空間的別名,那麼是否是必需要經過這個別名才能使用這段存儲空間呢?答案確定不是的,咱們還能夠經過指針來使用這段存儲空間。在指針聲明時,* 號表示所聲明的變量爲指針。在指針使用時,* 號表示取指針所指向的內存空間中的值。咱們經過下面這幅圖能夠更加直觀的看出他們的關係ide

圖片.png

        經過這個圖片咱們是否是更加直觀的看出它們的關係呢。上面即表示的是變量 p 保存着變量 i 的內存地址,即 p <--> &i;    *p <--> i函數

        下來咱們經過示例代碼進行分析說明,代碼以下學習

#include <stdio.h>

int main()
{
    int i = 0;
    int* pI;
    char* pC;
    float* pF;
    
    pI = &i;
    
    *pI = 10;
    
    printf("%p, %p, %d\n", pI, &i, i);
    printf("%d, %d, %p\n", sizeof(int*), sizeof(pI), &pI);
    printf("%d, %d, %p\n", sizeof(char*), sizeof(pC), &pC);
    printf("%d, %d, %p\n", sizeof(float*), sizeof(pF), &pF);
    
    return 0;
}

        咱們在678行分別定義了 int* char* float* 類型的指針,在第10行經過指針 pI 指向了 i 的地址,再經過第12行的取指針的內容並賦值來達到改變 i 的值。那麼咱們接下來打印下指針 pI 的地址,i  的地址還有 i 的值分別是什麼。還有看下三種不一樣類型的指針所佔的內存大小和地址各是什麼,編譯結果以下spa

圖片.png

        那麼咱們看到指針 pI 和 i 的地址相同,而且 i 的值已經經過指針成功改變爲10。接着咱們看到不論是什麼類型的指針所佔的內存大小都是4,並非咱們以前所認爲的 int 爲4,char 爲1,float 爲4啦,它們的地址連續着。說明指針在內存中並無類型之分,所存儲的內存都是在同一個段上。指針

        咱們接下來再來看個傳值調用和傳址調用。那麼在程序中,指針也是變量,所以能夠聲明指針參數。當一個函數體內部須要改變實參的值,則須要使用指針參數。函數調用時實參值將複製到形參,指針適用於複雜數據類型做爲參數的函數中。咱們下來利用示例代碼進行說明傳值調用和傳址調用的區別,代碼以下blog

#include <stdio.h>

int swap(int a, int b)
{
    int c = a;
    
    a = b;
    
    b = c;
}

int main()
{
    int aa = 1;
    int bb = 2;
    
    printf("aa = %d, bb = %d\n", aa, bb);
    
    swap(aa, bb);
    
    printf("aa = %d, bb = %d\n", aa, bb);
    
    return 0;
}

        咱們想固然是 swap 函數能完成兩個數交換的功能,咱們來編譯下,看看是否能交換呢?圖片

圖片.png

        結果是這樣的,臥槽,是咱們搞錯了嘛。看來看去以爲程序就該這麼寫啊,咱們再來仔細分析下。咱們在第19行只是將變量 aa 和 bb 的值複製給了 swap 函數的實參 a 和 b。在 swap 函數內部確實完成 a 和 b 的值交換,但只是 a 和 b 的值交換了而已。換句話說,這時他兩跟變量 aa 和 bb 沒啥關係,咱們這種就屬於傳值調用。咱們再將 swap 函數改爲下面這樣呢?看看結果如何內存

int swap(int* a, int* b)
{
    int c = *a;
    
    *a = *b;
    
    *b = c;
}

        再將 main 函數中第19行改爲 swap(&aa, &bb); 咱們來看看編譯結果如何it

圖片.png

        咱們看到加了個 * 號,居然神奇般改變了 aa 和 bb 的值。感受很神奇啊,咱們仔細分析下,這就是屬於利用指針指向變量 aa 和 bb 的地址,而後再經過 * 取地址處的內容再賦值改變。這樣就是咱們所說的傳址調用啦。

        咱們下來再來看看一個筆試面試中常常會問到的問題:a> const int* p;b> int const* p;c> int* const p;d> const int* const p 四種有什麼區別。咱們來一一分析:a> p 可變但它指向的內容不可變;b> p 可變但它指向的內容不可變;c> p 不可變但它所指向的內容是可變的;d> p 和它所指向的內容都是不可變的。咱們對待這種問題有個口訣就是:左數右指(這是唐長老總結出來的)。什麼意思呢?就是當 const 出如今 * 號左邊時指針指向的數據爲常量,當 const 出如今 *  號右邊時指針自己爲常量。這樣是否是就很好記了呢?反正博主是記住了哈。

        咱們下來再來個示例代碼對其進行說明,代碼以下

#include <stdio.h>

int main()
{
    int i = 0;
    
    const int* p1 = &i;
    int const* p2 = &i;
    int* const p3 = &i;
    const int* const p4 = &i;
    
    *p1 = 1;    // compile error
    p1 = NULL;  // ok
    
    *p2 = 2;    // compile error
    p2 = NULL;  // ok
    
    *p3 = 3;    // ok
    p3 = NULL;  // compile error
    
    *p4 = 4;    // compile error
    p4 = NULL;  // compile error
    
    return 0;
}

        咱們看到第12行明顯會出錯,由於 const 出如今 * 號的左邊,左數右指嘛,就是它所指向的內容是不可變的。第15行也是一樣的錯誤。第19行則是由於 p3 是 const 出如今 * 號的右邊,因此它自己不可變。p4 先後都有 const,因此第2一、22行均會出錯。咱們來看看分析是否正確呢

圖片.png

        咱們看到結果與咱們分析的是一致的,咱們之後遇到這種筆試面試題豈不是送分題啦?哈哈,開個玩笑了,其實仍是很簡單的只需記住口訣就好。咱們看看指針是不是那樣傳說中的難呢?其實也不難的。經過對指針的學習,咱們總結以下:一、指針是 C 語言中一種特別的變量;二、指針所保存的值是內存的地址;三、能夠經過指針修改內存中的任意地址內容。


        歡迎你們一塊兒來學習 C 語言,能夠加我QQ:243343083

相關文章
相關標籤/搜索