彻底攻克C语言指针
前面我們講解了指針數(shù)組、二維數(shù)組指針、函數(shù)指針等幾種較為復(fù)雜的指針,它們的定義形式分別是:
我相信大部分初學(xué)者對(duì)上面幾種形式的指針都非常迷惑,不知道該從哪里入手去理解,為什么 p1、p2 是數(shù)組,而 p3 卻是指針呢,它們僅僅是一個(gè)括號(hào)的區(qū)別。
指針是C語言中最強(qiáng)大最靈活的一部分,也是最難以理解的一部分,它是學(xué)習(xí)C語言的重點(diǎn),沒有學(xué)會(huì)指針就無從談學(xué)會(huì)C語言。如果大家覺得上面幾種形式的指針還能勉強(qiáng)接受,那么下面兩個(gè)指針是不是讓人抓狂呢?
只要找到了竅門,再復(fù)雜的指針也是可以理解的,這節(jié)我們就來戳破這層窗戶紙!
C語言標(biāo)準(zhǔn)規(guī)定,對(duì)于一個(gè)符號(hào)的定義,編譯器總是從它的名字開始讀取,然后按照優(yōu)先級(jí)順序依次解析。對(duì),從名字開始,不是從開頭也不是從末尾,這是理解復(fù)雜指針的關(guān)鍵!
對(duì)于初學(xué)者,有幾種運(yùn)算符的優(yōu)先級(jí)非常容易混淆,它們的優(yōu)先級(jí)從高到低依次是:
- 定義中被括號(hào)( )括起來的那部分。
- 后綴操作符:括號(hào)( )表示這是一個(gè)函數(shù),方括號(hào)[ ]表示這是一個(gè)數(shù)組。
- 前綴操作符:星號(hào)*表示“指向xxx的指針”。
學(xué)會(huì)了“絕殺招式”,接下來我們就由淺入深,逐個(gè)擊破上面的指針定義。
1)?int *p1[6];
從 p1 開始理解,它的左邊是 *,右邊是 [ ],[ ] 的優(yōu)先級(jí)高于 *,所以編譯器先解析p1[6],p1 首先是一個(gè)擁有 6 個(gè)元素的數(shù)組,然后再解析int *,它用來說明數(shù)組元素的類型。從整體上講,p1 是一個(gè)擁有 6 個(gè) int * 元素的數(shù)組,也即指針數(shù)組。
2)?int (*p3)[6];
從 p3 開始理解,( ) 的優(yōu)先級(jí)最高,編譯器先解析(*p3),p3 首先是一個(gè)指針,剩下的int [6]是 p3 指向的數(shù)據(jù)的類型,它是一個(gè)擁有 6 個(gè)元素的一維數(shù)組。從整體上講,p3 是一個(gè)指向擁有 6 個(gè) int 元素?cái)?shù)組的指針,也即二維數(shù)組指針。
為了能夠通過指針來遍歷數(shù)組元素,在定義數(shù)組指針時(shí)需要進(jìn)行降維處理,例如三維數(shù)組指針實(shí)際指向的數(shù)據(jù)類型是二維數(shù)組,二維數(shù)組指針實(shí)際指向的數(shù)據(jù)類型是一維數(shù)組,一維數(shù)組指針實(shí)際指向的是一個(gè)基本類型;在表達(dá)式中,數(shù)組名也會(huì)進(jìn)行同樣的轉(zhuǎn)換(下降一維)。3) int (*p4)(int, int);
從 p4 開始理解,( ) 的優(yōu)先級(jí)最高,編譯器先解析(*p4),p4 首先是一個(gè)指針,它后邊的 ( ) 說明 p4 指向的是一個(gè)函數(shù),括號(hào)中的int, int是參數(shù)列表,開頭的int用來說明函數(shù)的返回值類型。整體來看,p4 是一個(gè)指向原型為int func(int, int);的函數(shù)的指針。
4) char *(* c[10])(int **p);
這個(gè)定義有兩個(gè)名字,分別是 c 和 p,乍看起來 p 是指針變量的名字,不過很遺憾這是錯(cuò)誤的。如果 p 是指針變量名,c[10]這種寫法就又定義了一個(gè)新的名字,這讓人匪夷所思。
以 c 作為變量的名字,先來看括號(hào)內(nèi)部(綠色粗體):
char *?(* c[10])?(int **p);
[ ] 的優(yōu)先級(jí)高于 *,編譯器先解析c[10],c 首先是一個(gè)數(shù)組,它前面的*表明每個(gè)數(shù)組元素都是一個(gè)指針,只是還不知道指向什么類型的數(shù)據(jù)。整體上來看,(* c[10])說明 c 是一個(gè)指針數(shù)組,只是指針指向的數(shù)據(jù)類型尚未確定。
跳出括號(hào),根據(jù)優(yōu)先級(jí)規(guī)則(() 的優(yōu)先級(jí)高于 *)應(yīng)該先看右邊(紅色粗體):
char *?(* c[10])?(int **p);
( )說明是一個(gè)函數(shù),int **p是函數(shù)參數(shù)。
再看左邊(橘黃色粗體):
char *?(* c[10])?(int **p);
char *是函數(shù)的返回值類型。
從整體上看,我們可以將定義分成兩部分:
char *?(* c[10])?(int **p);
綠色粗體表明 c 是一個(gè)指針數(shù)組,紅色粗體表明指針指向的數(shù)據(jù)類型,合起來就是:c 是一個(gè)擁有 10 個(gè)元素的指針數(shù)組,每個(gè)指針指向一個(gè)原型為char *func(int **p);的函數(shù)。
5) int (*(*(*pfunc)(int *))[5])(int *);
從 pfunc 開始理解,先看括號(hào)內(nèi)部(綠色粗體):
int (*(*(*pfunc)(int *))[5])(int *);
pfunc 是一個(gè)指針。
跳出括號(hào),看它的兩邊(紅色粗體):
int (*(*(*pfunc)(int *))[5])(int *);
根據(jù)優(yōu)先級(jí)規(guī)則應(yīng)該先看右邊的(int *),它表明這是一個(gè)函數(shù),int *是參數(shù)列表。再看左邊的*,它表明函數(shù)的返回值是一個(gè)指針,只是指針指向的數(shù)據(jù)類型尚未確定。
將上面的兩部分合成一個(gè)整體,如下面的藍(lán)色粗體所示,它表明 pfunc 是一個(gè)指向函數(shù)的指針,現(xiàn)在函數(shù)的參數(shù)列表確定了,也知道返回值是一個(gè)指針了(只是不知道它指向什么類型的數(shù)據(jù))。
int (*?(*(*pfunc)(int *))?[5])(int *);
藍(lán)色粗體以外的部分,就用來說明函數(shù)返回什么類型的指針。
我們接著分析,再向外跳一層括號(hào)(紅色粗體):
int (*?(*(*pfunc)(int *))?[5])(int *);
[ ] 的優(yōu)先級(jí)高于 *,先看右邊,[5] 表示這是一個(gè)數(shù)組,再看左邊,* 表示數(shù)組的每個(gè)元素都是指針。也就是說,* [5] 是一個(gè)指針數(shù)組,函數(shù)返回的指針就指向這樣一個(gè)數(shù)組。
那么,指針數(shù)組中的指針又指向什么類型的數(shù)據(jù)呢?再向外跳一層括號(hào)(橘黃色粗體):
int?(*?(*(*pfunc)(int *))?[5])?(int *);
先看橘黃色部分的右邊,它是一個(gè)函數(shù),再看左邊,它是函數(shù)的返回值類型。也就是說,指針數(shù)組中的指針指向原型為int func(int *);的函數(shù)。
將上面的三部分合起來就是:pfunc 是一個(gè)函數(shù)指針(藍(lán)色部分),該函數(shù)的返回值是一個(gè)指針,它指向一個(gè)指針數(shù)組(紅色部分),指針數(shù)組中的指針指向原型為int func(int *);的函數(shù)(橘黃色部分)。
轉(zhuǎn)載于:https://www.cnblogs.com/ZYDZ/p/9496080.html
總結(jié)
- 上一篇: ubuntu scp命令或者用root连
- 下一篇: h5滚动隐藏滚动条_这 10 个值得开启