1.看到這個題目大家應該知道了,數組和指針它倆不是一回事兒,它倆是有區別的!
我原來看數組的時候,一直都是用數組名表示數組內容的首地址,但是當我認真在網上看了數組和指針之后,發現數組和指針不等價!
舉個例子,相信大家見過這種寫法:
int arr[] = { 1,2,3,4,5}; int *b = arr;
我們一般的認識是 arr是一個指針,指向數組的首地址,然后它把這個地址的值賦給了指針變量b。
但是這種理解是有一點的不准確,嚴格來說應該是 arr被轉換為了一個指針。
再舉個例子:
#include <stdio.h> #include <string.h> int main(){ int a[6] = {1,2,3,4,5,6}; int *b = a; int len_a = sizeof(a) / sizeof(int); int len_b = sizeof(b) / sizeof(int); printf("len_a = %d\n",len_a); printf("len_b = %d",len_b); return 0; }
如果,咱們說如果哦,如果數組和指針等價,那么這兩個結果應該是一樣的,但是我們來看一下運行結果:
這特么是什么玩意,這個 2 是哪來的。
我們來看一下C語言中文網上的描述:
數組是一系列數據的集合,沒有開始和結束標志,b 僅僅是一個指向 int 類型的指針,編譯器不知道它指向的是一個整數還是一堆整數,對 b使用 sizeof 求得的是指針變量本身的長度。也就是說,編譯器並沒有把 b 和數組關聯起來,b僅僅是一個指針變量,不管它指向哪里,sizeof 求得的永遠是它本身所占用的字節數。
站在編譯器的角度講,變量名、數組名都是一種符號,它們最終都要和數據綁定起來。變量名用來指代一份數據,數組名用來指代一組數據(數據集合),它們都是有類型的,以便推斷出所指代的數據的長度。
對,數組也有類型,這是很多讀者沒有意識到的,大部分C語言書籍對這一點也含糊其辭!我們可以將 int、float、char 等理解為基本類型,將數組理解為由基本類型派生得到的稍微復雜一些的類型。sizeof 就是根據符號的類型來計算長度的。
對於數組 a,它的類型是int [6]
,表示這是一個擁有 6 個 int 數據的集合,1 個 int 的長度為 4,6 個 int 的長度為 4×6 = 24,sizeof 很容易求得。
對於指針變量 b,它的類型是int *
,在 32 位環境下長度為 4,在 64 位環境下長度為 8。(這就是為什么會輸出 2 了!)
歸根結底,a 和 b 這兩個符號的類型不同,指代的數據也不同,它們不是一碼事,sizeof 是根據符號類型來求長度的,a 和 b 的類型不同,求得的長度自然也不一樣。
總結:我們定義的數組 a 它是以個實實在在的數組類型的數據,它有自己的類型和長度,在內存中有自己的空間,而 指針變量b 它只是一個指針變量啊,一個指向int * 類型的變量!
那就有一個問題來了,既然數組a是一個數組類型的數據,那為什么 數組名a 可以代表數組的首地址呢?這就又涉及到一個知識點了---------------與普通變量名相比,數組名既有一般性也有特殊性:一般性表現在數組名也用來指代特定的內存塊,也有類型和長度;特殊性表現在數組名有時候會轉換為一個指針,而不是它所指代的數據本身的值。
特么的問題又來了,數組名什么時候會轉換為指針呢?
C語言標准規定,當數組名作為數組定義的標識符(也就是定義或聲明數組時)、sizeof 或 & 的操作數時,它才表示整個數組本身,在其他的表達式中,數組名會被轉換為指向第 0 個元素的指針(地址)。
舉例吧!
#include <stdio.h> #include <string.h> int main(){ int a[6] = {0,1,2,3,4,5}; // a表示數組本身 int len_a = sizeof(a) / sizeof(int); // a表示數組本身 int *b = &a[1]; // a 表示數組本身 int *p_a = a; // a 轉換為首地址 return 0; }
我感覺這個看的有點點小懂了!