C之指針(二十四)
我們先來回想下變量,在程序中的變量只是一段存儲空間的別名,那麽是不是必須要通過這個別名才能使用這段存儲空間呢?答案肯定不是的,我們還可以通過指針來使用這段存儲空間。在指針聲明時,* 號表示所聲明的變量為指針。在指針使用時,* 號表示取指針所指向的內存空間中的值。我們通過下面這幅圖可以更加直觀的看出他們的關系
通過這個圖片我們是不是更加直觀的看出它們的關系呢。上面即表示的是變量 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 的值分別是什麽。還有看下三種不同類型的指針所占的內存大小和地址各是什麽,編譯結果如下
那麽我們看到指針 pI 和 i 的地址相同,並且 i 的值已經通過指針成功改變為10。接著我們看到不管是什麽類型的指針所占的內存大小都是4,並不是我們之前所認為的 int 為4,char 為1,float 為4啦,它們的地址連續著。說明指針在內存中並沒有類型之分,所存儲的內存都是在同一個段上。
我們接下來再來看個傳值調用和傳址調用。那麽在程序中,指針也是變量,因此可以聲明指針參數。當一個函數體內部需要改變實參的值,則需要使用指針參數。函數調用時實參值將復制到形參,指針適用於復雜數據類型作為參數的函數中。我們下來利用示例代碼進行說明傳值調用和傳址調用的區別,代碼如下
#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 函數能完成兩個數交換的功能,我們來編譯下,看看是否能交換呢?
結果是這樣的,臥槽,是我們搞錯了嘛。看來看去覺得程序就該這麽寫啊,我們再來仔細分析下。我們在第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); 我們來看看編譯結果如何
我們看到加了個 * 號,竟然神奇般改變了 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,所以第21、22行均會出錯。我們來看看分析是否正確呢
我們看到結果與我們分析的是一致的,我們以後遇到這種筆試面試題豈不是送分題啦?哈哈,開個玩笑了,其實還是很簡單的只需記住口訣就好。我們看看指針是否是那樣傳說中的難呢?其實也不難的。通過對指針的學習,我們總結如下:1、指針是 C 語言中一種特別的變量;2、指針所保存的值是內存的地址;3、可以通過指針修改內存中的任意地址內容。
歡迎大家一起來學習 C 語言,可以加我QQ:243343083。
C之指針(二十四)