搞清楚陣列和指標

2021-08-11 20:46:26 字數 2769 閱讀 7425

首先來看看幾個例子

int *p[a]; //指標陣列

int (*p)[b]; //陣列指標

int *function(int a);// 指標函式

int (*p) (int a); //函式指標

int (*p[a])(int a); //函式指標陣列

在敘述陣列和指標的關係之前,先琢磨一下上面的五行**,看你是否能一眼就看出來它們的確切含義。首先很關鍵的一點就是,我們要知道「 * 」和「[ ]」的優先順序,也就是它們的結合順序,優先順序大於*,故陣列指標宣告時要加()。

第乙個表示式int *p[a],很明顯「[ ]」比「 * 」的優先順序要高,如果沒有括號,則p優先結合[a],這就說明此表示式為乙個陣列,*則自動和int結合,為乙個int型指標。那麼第乙個表示式就表示在乙個陣列p中存放著a個int型指標變數,也就是說這是乙個指標的陣列,簡稱指標陣列。

第二個表示式int (*p)[b],()存在,則優先順序最高,說明p為乙個指標,是什麼型別的指標呢?不要著急,接著看。剩下的int和[b]自動結合,很容易理解int[b]這是乙個整型陣列,那麼(*p)就可以當做乙個整體看成是這個陣列的名稱。這下就可以看出p是乙個指向整型陣列的指標變數,也就是說這個表示式是乙個陣列的指標,簡稱陣列指標。

第四個表示式int (*p) (int a),和上述第二個表示式類似,只是後面的陣列大小部分換成了函式的引數。(int a)表示函式的引數,前面的int表示函式的返回值為乙個整型值,*和p結合表示p是乙個指標,那麼這個指標是什麼型別的呢,也就是說指向什麼東西呢?這是乙個p指標,指向乙個引數為int a、返回值為int型的函式。對的,你沒看錯這個函式沒有函式名(函式名表示的是函式的入口位址,類似於函式的指標),但它有乙個p指標。所以這個表示式是乙個指向函式的指標,簡稱函式指標。

第五個表示式int (*p[a])(int a),看見它先不要害怕。來,一步步分析,和第四個表示式很相似,表示式後面帶括號證明這個表示式裡面有函式成份。(int a )表示函式的引數,表示式中第乙個int表示函式的返回值為整型。再來看看(*p[a]),和前面的分析方法相同,[ ]優先順序高先結合,表示這是乙個p陣列,陣列裡面存放的什麼東西呢?[a]和p結合,*和剩餘部分結合,表示函式的指標,那麼p陣列裡面存放的就是函式的指標。注意存放的是乙個引數為整型、返回值為整型的函式的指標。所以第五個表示式表示,乙個p陣列裡面存放著一組引數為int型、返回值為int型的函式的指標,簡稱函式指標陣列。

讀以上五個名詞的時候注意把握乙個要點,那個單詞在最後,說明本質就是什麼,陣列指標也就是陣列的指標,表明本質是指標;函式指標陣列也就是函式的指標的陣列,本質表明是乙個陣列。

來個稍微複雜的:指向指標函式的函式指標陣列,簡稱指標函式函式指標陣列

int *(*funcp[n])(int )

好了,搞明白以上幾個定義,接下來我們說說陣列和指標的關係。都知道陣列名在一般情況下可以理解為乙個指標。例如int arry[n]表示乙個整形陣列,int *p表示乙個整形指標。則這個arry是可以直接賦給p的,如下圖:

注意在這裡把陣列名賦給指標變數的時候對陣列名用不用取位址符&都是可以的。以後就可以採用*(p+1)的方式來訪問陣列arry了。用指標變數直接指向陣列元素,不必每次都計算位址,可以大大提高執行效率。

上面是一維陣列和指標的關係,接下來看看二維陣列和指標的關係(這裡的指標包含一級指標和二級指標,我們分別講解)。二維陣列在記憶體裡面其實也是按照一維陣列的方式順序存放的,可以想象為第二行的首接第一行的尾放置。首先要知道二維陣列的陣列名是個什麼玩意,二維陣列的陣列名其實就是二維陣列的首位址,只不過這個首位址是個行位址。也就是說二維陣列的陣列名如果當成是和一維陣列名一樣的等級時,那麼這個陣列裡面的每個元素則是一列元素罷了。定義二維陣列為int a[3][4],那麼a[0],a[1],a[2],可以理解為一位陣列名,代表的是這個二維陣列中每一行元素的首位址,即a[0]就代表的是&a[0][0],a[1]就代表的是&a[1][0]。那麼自然地&a[0][1]就可以用a[0]+1來表示。因此我們可以得出a[1]等價於*(a + 1),&a[0][1]等價於a[0] +1 和*(a + 0) + 1,那麼*(a[i]+j)和*(*(a+i) + j)就表示二維陣列元素a[i][j]的值。

首先要說明一點,a+1是二維陣列a中序號為1的行的首位址,而*(a+1)為序號為1的行的首元素的位址,可以看成*(a+1)+0來理解。而並不是a+1單元中的內容,因為a+1並不是乙個變數的位址,而是一行元素的首位址。*(a+1)就是a[1],而a[1]是一維陣列的陣列名,也是位址,指向a[1][0]。因此a[1]和*(a+1)都是二維陣列中位址的表示方法。在這裡,我們可以把*看做乙個降維符號,而不是取值符號。可以看到在指向行的指標前面加乙個*就把指標轉化為了指向列的指標。反之在指向列元素的指標前面加&就變成了行指標。

在這裡要特別注意,初學者會有乙個誤區,認為一級指標int*p對應一維陣列int a[2],即 p = a;二級指標int**pp對應二維陣列int a[2][3],即pp = a;其實非也。二維陣列的對應是陣列指標,而不是二級指標。不能用二級指標直接指向二維陣列。第一點是不可以,第二點是不需要。如果需要指標每次移動的單位為二維陣列中的一行記憶體,則需定義乙個陣列指標,這個陣列指標指向的陣列大小即就是二維陣列的第二個下標,也就是每行元素的長度列。

搞清楚LzoCodec和LzopCodec

使用lzo過程會發現它有兩種壓縮編碼可以使用,即lzocodec和lzopcodec,下面說說它們區別 lzocodec比lzopcodec更快,lzopcodec為了相容lzop程式新增了如bytes signature,header等資訊 如果使用 lzocodec作為reduce輸出,則輸出擴...

徹底搞清楚SSL TLS

ssl secure sockets layer 最初由netscape定義,分別有sslv2和sslv3兩個版本 sslv1未曾對外發布 在sslv3之後ssl重新命名為tls。tls transport layer security 版本從tlsv1.0開始,tlsv1.0是在sslv3的基礎上...

搞清楚你的 Rails Version

目前使用 rails 的網站,version 分成好幾派。rails 0.x 的就是幾年前就開始在使用 rails 的始祖,據我所知國內也是有網站還再用 0.x 他們之所以死撐不換的原因只有乙個,就是怕公升級上去原本的 code 根本不相容。1.0 的時候我沒趕上,那可能要問一些長輩才知道 1.0 ...