詳細解讀指標和陣列的關係
阿新 • • 發佈:2019-02-13
陣列和指標是C語言中兩個很重要的知識點,也是兩個難點。對於很多C/C++的開發者來說,雖然經常會看到和使用它們,但是會對這二者的關係有些搞不清楚。
如果說讓我來形容它們關係的話,我可以說:它們之間在本質上是沒有任何關係的!
打一個形象的比喻來說,我覺得它們就像是在一個部門工作的兩個很要好的同事,而且兩個同事長得還很像而已。所以我們經常會弄混它們。
為了便於我們理解這兩個“同事”之間的關係,我們還是用程式來說明:
#include <stdio.h>
//主函式
int main()
{
//定義一個數組
int a[5] = { 1, 2, 3, 4, 5 };
//定義一些指標
int* p1 = a;
int* p2 = a + 1;
int* p3 = a + 2;
int* p4 = a + 3;
int* p5 = a + 4;
//定義一些變數
int i1 = *p1;
int i2 = *p2;
int i3 = *p3;
int i4 = *p4;
int i5 = *p5;
int i6 = *a;
int i7 = *(a + 1);
int i8 = *(a + 2);
int i9 = *(a + 3);
int i10 = *(a + 4);
//返回
return 0;
}
編譯結果如下(編譯環境是Visual Studio 2013):
可以看到,裡面是沒有任何內容的,當然這是肯定的,因為程式裡面沒有呼叫printf函式列印任何內容,因為這次我們需要通過Visual Studio 2013的監視視窗來檢視它們的
值和指標(因為不同的人使用printf列印的風格不盡相同,便於統一,通過檢視值和指標
的方法是最直接和方便的)。
我們可以使用Visual Studio 2013的除錯功能(F10鍵),並逐行執行完成後,我們來檢視一下監視視窗的內容:
雖然這段程式看起來不復雜,不過我們還是可以總結出很多東西的。
1.我們可以看到,陣列a的地址是0x0088f920,指標p1的值也是0x0088f920,而i1和i6的值也是陣列a的第一個元素值(1),我們可以總結出第一條規律:陣列名就是陣列第
一個元素的指標,通過陣列名,我們就可以獲取陣列第一個元素的值(*a),以及第一個元素的指標(a) 。
2.變數i2的值是陣列a的第二個元素(2),i2 = *p2,而p2 = a + 1,這樣我們就可以知道:如果a是陣列名的話,那麼a + 1就是獲取陣列的第二個元素的指標;通過i3到i5的
值,我們可以繼續得到一個更廣泛的結論:如果如果a是陣列名的話,那麼a + n就是獲取陣列的第n個元素的指標。指標的加操作並不是地址值加1,而是加sizeof(<變數型別>),
對於這個例子的int型別而言,sizeof(int)等於4,所以我們看到a(0x0088f920)和a + 1(0x0088f924),a + 1(0x0088f924)和a + 2(0x0088f928),a + 2(0x0088f928)和a + 3
(0x0088f92c),a + 3(0x0088f92c)和a + 4(0x0088f930)的地址差都是4 。
3.變數i7的值也是陣列a的第二個元素(2),不過它的得到方法是*(a + 1),這相當於將變數i2得到的方法簡化了(先得到a + 1的地址,再取得a + 1地址裡面的值),這說明:如果如果a是陣列名的話,*(a + n)就是陣列第n個元素的值。
當然,我們還可以得到更多的結論,這裡只是總結了三個最重要的結論。
總之,陣列和指標就是兩個關係很好的“同事”,它們沒有什麼“血緣“和“親戚“關係,只是經常在一起共同工作和相互協作罷了。
如果說讓我來形容它們關係的話,我可以說:它們之間在本質上是沒有任何關係的!
打一個形象的比喻來說,我覺得它們就像是在一個部門工作的兩個很要好的同事,而且兩個同事長得還很像而已。所以我們經常會弄混它們。
為了便於我們理解這兩個“同事”之間的關係,我們還是用程式來說明:
#include <stdio.h>
//主函式
int main()
{
//定義一個數組
int a[5] = { 1, 2, 3, 4, 5 };
//定義一些指標
int* p1 = a;
int* p2 = a + 1;
int* p3 = a + 2;
int* p4 = a + 3;
int* p5 = a + 4;
//定義一些變數
int i1 = *p1;
int i2 = *p2;
int i3 = *p3;
int i4 = *p4;
int i5 = *p5;
int i6 = *a;
int i7 = *(a + 1);
int i8 = *(a + 2);
int i9 = *(a + 3);
int i10 = *(a + 4);
//返回
return 0;
}
編譯結果如下(編譯環境是Visual Studio 2013):
可以看到,裡面是沒有任何內容的,當然這是肯定的,因為程式裡面沒有呼叫printf函式列印任何內容,因為這次我們需要通過Visual Studio 2013的監視視窗來檢視它們的
值和指標(因為不同的人使用printf列印的風格不盡相同,便於統一,通過檢視值和指標
的方法是最直接和方便的)。
我們可以使用Visual Studio 2013的除錯功能(F10鍵),並逐行執行完成後,我們來檢視一下監視視窗的內容:
雖然這段程式看起來不復雜,不過我們還是可以總結出很多東西的。
1.我們可以看到,陣列a的地址是0x0088f920,指標p1的值也是0x0088f920,而i1和i6的值也是陣列a的第一個元素值(1),我們可以總結出第一條規律:陣列名就是陣列第
一個元素的指標,通過陣列名,我們就可以獲取陣列第一個元素的值(*a),以及第一個元素的指標(a)
2.變數i2的值是陣列a的第二個元素(2),i2 = *p2,而p2 = a + 1,這樣我們就可以知道:如果a是陣列名的話,那麼a + 1就是獲取陣列的第二個元素的指標;通過i3到i5的
值,我們可以繼續得到一個更廣泛的結論:如果如果a是陣列名的話,那麼a + n就是獲取陣列的第n個元素的指標。指標的加操作並不是地址值加1,而是加sizeof(<變數型別>),
對於這個例子的int型別而言,sizeof(int)等於4,所以我們看到a(0x0088f920)和a + 1(0x0088f924),a + 1(0x0088f924)和a + 2(0x0088f928),a + 2(0x0088f928)和a + 3
(0x0088f92c),a + 3(0x0088f92c)和a + 4(0x0088f930)的地址差都是4
3.變數i7的值也是陣列a的第二個元素(2),不過它的得到方法是*(a + 1),這相當於將變數i2得到的方法簡化了(先得到a + 1的地址,再取得a + 1地址裡面的值),這說明:如果如果a是陣列名的話,*(a + n)就是陣列第n個元素的值。
當然,我們還可以得到更多的結論,這裡只是總結了三個最重要的結論。
總之,陣列和指標就是兩個關係很好的“同事”,它們沒有什麼“血緣“和“親戚“關係,只是經常在一起共同工作和相互協作罷了。