當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 混說(shuō)Linux
[導(dǎo)讀]指針使得 C 語(yǔ)言能夠更高效地實(shí)現(xiàn)對(duì)計(jì)算機(jī)底層硬件的操作,而計(jì)算機(jī)硬件的操作很大程度上依賴地址,指針便提供了一種對(duì)地址操作的方法,在一定意義上,指針是c語(yǔ)言的精髓,所以一定要耐心看完。指針對(duì)于很多c語(yǔ)言初學(xué)者來(lái)說(shuō)可能難以理解,一不小心可能被指針的指向關(guān)系繞進(jìn)去,在這里就對(duì)指針做一些總結(jié),寫一下自己的理解。

指針使得 C 語(yǔ)言能夠更高效地實(shí)現(xiàn)對(duì)計(jì)算機(jī)底層硬件的操作,而計(jì)算機(jī)硬件的操作很大程度上依賴地址,指針便提供了一種對(duì)地址操作的方法,在一定意義上,指針是c語(yǔ)言的精髓,所以一定要耐心看完。指針對(duì)于很多c語(yǔ)言初學(xué)者來(lái)說(shuō)可能難以理解,一不小心可能被指針的指向關(guān)系繞進(jìn)去,在這里就對(duì)指針做一些總結(jié),寫一下自己的理解。

一. 指針的介紹


在程序中,我們聲明一個(gè)變量(int a = 1),將數(shù)據(jù)1存到變量a中,計(jì)算機(jī)內(nèi)部會(huì)將這個(gè)數(shù)據(jù)存到內(nèi)存(RAM)中,那么,數(shù)據(jù)存到某個(gè)地方,就會(huì)涉及地址。就像你買的快遞,快遞到了就要存到某個(gè)驛站里面放著,你的快遞就是一個(gè)數(shù)據(jù),驛站就是一個(gè)變量,這個(gè)驛站就要有地址,不然全國(guó)這么多驛站你怎么知道你的快遞在哪個(gè)驛站。


到這里,地址的概念應(yīng)該有了吧。


現(xiàn)在想想地址(比如0x0000 0001)不也是一個(gè)數(shù)據(jù)嗎,那么不也可以用一個(gè)變量存地址這個(gè)數(shù)據(jù)?是的,可以,這個(gè)變量就是指針,指針?biāo)褪谴鎯?chǔ)另一個(gè)變量的內(nèi)存地址的一種數(shù)據(jù)類型,即指針的內(nèi)容就是另一個(gè)變量的內(nèi)存地址。





指針本身也是一個(gè)變量,所以指針變量也有自己的地址,只是它有點(diǎn)特殊,它存放的是另一個(gè)變量的地址而已,理解這句話就行。




前面講到過(guò)指針?biāo)且环N數(shù)據(jù)類型,為了方便,我們就規(guī)定在這種類型后面加*號(hào)表示該類型指針,有char型指針(char *)、double型指針(double *)和int型指針(int *)等等。


試著敲一下下面一段代碼,可以加深對(duì)指針的認(rèn)識(shí):

int a = 1; // 定義一個(gè)int型變量int *p = &a; // 定義一個(gè)int型指針p,&a表示對(duì)a取地址,指針p的內(nèi)容是a的地址// int  *p;   p = &a;    // 第二行也可以這樣寫,意思一樣printf("%p\n", &a); // 打印a的地址printf("%p\n", p); // 打印指針p指向的地址// %p是打印地址(指針地址),是十六進(jìn)制的形式


C/C++ 中規(guī)定了 * 操作符來(lái)從對(duì)應(yīng)指針類型存放的地址中拿出相應(yīng)數(shù)據(jù),再定義一個(gè)變量int b = *p,指針p存了a的地址,*p就是拿出a的值,b的值就變成了1,*操作也被稱為解引用。



二. 指針的相關(guān)操作(運(yùn)算)


算數(shù)運(yùn)算:+、-、++、--、

指針的運(yùn)算是特別容易搞錯(cuò)的,千萬(wàn)不能以為和普通類型(比如int型數(shù)據(jù))的運(yùn)算一樣。


指針的加減運(yùn)算:


  1. 指針+1/指針-1,加/減的是整個(gè)指針類型的長(zhǎng)度,與其說(shuō)指針的加減法,我認(rèn)為不如說(shuō)成指針的偏移更合適,接下來(lái)看為什么是偏移,舉個(gè)非常明顯的例子:

char a[5] = {1, 2, 3, 4, 5}; // 定義一個(gè)char型數(shù)組,這里的a實(shí)質(zhì)上是一個(gè)指針,指向這個(gè)數(shù)組的首元素a[0]的指針char *p = a;printf("%d\n", *p); // 輸出1 --> a[0]printf("%d\n", *(p + 1)); // 輸出2 --> a[1]......


看輸出的結(jié)果就很容易看出規(guī)律,p指針指向a[0],特別注意p+1指針變成指向a[1],所以*(p+1)  = a[1] = 2,而不是*(p+1)  = a[0] + 1 = 2,當(dāng)然這里兩個(gè)答案湊巧一樣,但是把數(shù)組的內(nèi)容換一下就不會(huì)是一樣了,如果是改成(*p) + 1,那么就是(*p) + 1 = a[0] + 1 = 2,同理可以改成p+2、p+3......


還有試著定義其它類型的數(shù)組(比如int型:int a[5] = {1, 2, 3, 4, 5};),看看是不是這個(gè)規(guī)律,就可以知道指針加減的是這個(gè)指針類型的長(zhǎng)度,也就是指針的偏移,還可以嘗試定義結(jié)構(gòu)體數(shù)組,將會(huì)有更深的理解。


減法就不用多說(shuō)了,理解了指針p+1/p-1,那么指針p++/p--其實(shí)是一樣的,都是偏移。



三. 多級(jí)指針





說(shuō)起多級(jí)指針這個(gè)東西,曾經(jīng)大一學(xué)c語(yǔ)言的時(shí)候,學(xué)到二級(jí)指針都已經(jīng)把我給繞暈了,如果當(dāng)時(shí)你給我寫個(gè)int ********p出來(lái),我估計(jì)直接崩潰到放棄。




我們先來(lái)說(shuō)說(shuō)二級(jí)指針吧!前面有講到,指針也是一種數(shù)據(jù)類型,是一種變量,也有自己的地址,所以既然有地址,而指針就是存放另一個(gè)變量的地址的呀,那為什么不能再用一個(gè)指針存放這個(gè)指針的地址呢,對(duì)吧!所以就有了二級(jí)指針,就是指向指針的指針。


ok!來(lái)點(diǎn)生活上的東西,快遞柜大家都用過(guò)吧,快遞小哥給你發(fā)一個(gè)取件碼你就能拿到快遞。



這里的每一個(gè)柜子就是一塊內(nèi)存,取件碼就是地址,柜子里的快遞就是存儲(chǔ)在內(nèi)存的內(nèi)容/數(shù)據(jù)。


假如快遞小哥把你的快遞放到"058柜子",給你發(fā)取件碼,那么你輸入取件碼就可以取到快遞。

如果快遞小哥逗你一下,故意給你發(fā)"057柜子"的取件碼,然后在"057柜子"放一張紙條,上面寫:快遞在058柜子,這時(shí)候你肯定是按照紙條從"058柜子"里就可以拿到快遞。


這里的"057柜子"就是指針,指針里面存放另一個(gè)變量(058柜子)的地址。

如果快遞小哥給你發(fā)"056柜子"的取件碼,在"056柜子"里放一張紙條寫:快遞在"057柜子"里,又在"057柜子"里放一張紙條寫:快遞在"058柜子"里。


這里的"056柜子"就是二級(jí)指針,"057柜子"就是指針,"058柜子"就是指針存放的另一個(gè)變量。

現(xiàn)在明白了二級(jí)指針吧,那么,N級(jí)指針也就那樣,也就是指向指針的指針的指針的指針的指針........,是不是非常簡(jiǎn)單!

int a = 1;int *p = &a;int **pp = &p; // 二級(jí)指針pp存放指針p的地址,即二級(jí)指針pp指向指針pint ***ppp = &pp; // 三級(jí)指針ppp存放二級(jí)指針pp的地址,即三級(jí)指針ppp指向二級(jí)指針pp......


總之,如果一個(gè)內(nèi)存如果存放的是另一個(gè)變量的地址,那么就叫指針。一塊內(nèi)存要么存放實(shí)際內(nèi)容/數(shù)據(jù),要么存放的是另一個(gè)變量的地址,確實(shí)是剛剛所說(shuō)的非常簡(jiǎn)單。





【總結(jié)兩點(diǎn)】:

1. 指針本身也是一個(gè)變量,也有自己的地址,需要內(nèi)存存儲(chǔ)。

2. 指針存放的是所指向的變量的地址,這個(gè)所指向的變量也可以是一個(gè)指針。


特別注意】:面試可能被問(wèn)到指針的大小

1. 指針的大小跟指針是什么類型的沒(méi)有任何關(guān)系。

 2. 在32為系統(tǒng)系統(tǒng)中,所有的指針大小都是4個(gè)字節(jié),原因是32系統(tǒng)上所有變量的地址都是32位的,而指針用來(lái)存地址的。




最后,大家要明白一個(gè)概念,其實(shí)并沒(méi)有什么多級(jí)指針這種東西,多級(jí)指針就是個(gè)指針,稱為多級(jí)指針是為了我們方便表達(dá)而取的邏輯名稱。



四. 多維數(shù)組





二維數(shù)組其實(shí)和二級(jí)指針有著相似的理解方法:

比如a[3][2],把它理解成一個(gè)一維數(shù)組來(lái)看待,這個(gè)一維數(shù)組里面有三個(gè)元素,只是這個(gè)一維數(shù)組有點(diǎn)特殊,它的每個(gè)元素又是一個(gè)一維數(shù)組而已。




懂了上面這段話,二維數(shù)組就很好理解。

前面我們已經(jīng)知道一維數(shù)組a[3]中,a實(shí)質(zhì)上是一個(gè)指針,指向這個(gè)數(shù)組首元素a[0]:
int a[3] = {1, 2, 3};// a[0]  -->  *aprintf("%d\n", *a); // 打印 1  -->  a[0] 的值// a[1]  -->  *(a + 1)printf("%d\n", *(a + 1)); // 打印 2  -->  a[1] 的值// a[2]  -->  *(a + 2)printf("%d\n", *(a + 2)); // 打印 3  -->  a[2] 的值

那么,二維數(shù)組a[3][2]當(dāng)成一維數(shù)組看是不是可以得出:
int a[3][2] = {{1, 2}, {3, 4}, {5, 6}};// a[0][0]  -->  (*a)[0]printf("%d\n", (*a)[0]); // 打印 1  -->  a[0][0] 的值// a[1][0]  -->  (*(a + 1))[0]printf("%d\n", (*(a + 1))[0]); // 打印 3  -->  a[1][0] 的值// a[2][0]  -->  (*(a + 2))[0]printf("%d\n", (*(a + 2))[0]); // 打印 5  -->  a[2][0] 的值// a[2][1]  -->  (*(a + 2))[1]printf("%d\n", (*(a + 2))[1]); // 打印 6  -->  a[2][1] 的值// ..... 二維數(shù)組其它元素類似都可以輸出

結(jié)論一:a[m][n]  等價(jià)于 (*(a + m)[n]  -->就是一個(gè)數(shù)組指針(后面會(huì)提到)

基于前面兩種指針和數(shù)組的變換,可以繼續(xù)得出:
int a[3][2] = {{1, 2}, {3, 4}, {5, 6}};// a[0][0]  -->  (*a)[0]  -->  *(*a + 0)  -->  把 *a 當(dāng)成整體printf("%d\n", *(*a)); // 打印 1  -->  a[0][0] 的值// a[1][0]  -->  (*(a + 1))[0]  -->  *(*(a + 1) + 0)printf("%d\n", *(*(a + 1))); // 打印 3  -->  a[1][0] 的值// a[2][0]  -->  (*(a + 2))[0]  -->  *(*(a + 2) + 0)printf("%d\n", *(*(a + 2))); // 打印 5  -->  a[2][0] 的值// a[2][1]  -->  (*(a + 2))[1]  -->  *(*(a + 2) + 1)printf("%d\n", *(*(a + 2) + 1)); // 打印 6  -->  a[2][1] 的值// ..... 二維數(shù)組其它元素類似都可以輸出

結(jié)論二:a[m][n] 等價(jià)于   *(*(a + m) + n)


五. 數(shù)組指針與指針數(shù)組


1. 數(shù)組指針:指針在后,說(shuō)明它就是個(gè)指針,所以數(shù)組指針指向的是數(shù)組,相當(dāng)于一次聲明了一個(gè)指針。從前面就已經(jīng)知道,二維數(shù)組a[3][2]中,a實(shí)質(zhì)上就是一個(gè)數(shù)組指針。




公式:

指向的那個(gè)數(shù)組的元素類型  (*指針名字)[指向的數(shù)組的元素個(gè)數(shù)]




2. 指針數(shù)組:數(shù)組在后,說(shuō)明它就是個(gè)數(shù)組。字符數(shù)組是什么?就是存放字符的數(shù)組,那么指針數(shù)組就是存放指針類型的數(shù)組,相當(dāng)于一次聲明了多個(gè)指針。




公式:

數(shù)組元素的類型  數(shù)組名字[數(shù)組元素個(gè)數(shù)]




char *a[3] = {"red", "green", "blue"};char **pp = a; //定義二級(jí)指針pp, a本質(zhì)上相當(dāng)于二級(jí)指針printf("%s\n", pp[0]); // 打印 redprintf("%s\n", pp[1]); // 打印 greenprintf("%s\n", pp[2]); // 打印 blue

直觀上區(qū)分?jǐn)?shù)組指針和指針數(shù)組的方法:
由于數(shù)組指針的 [] 比 * 的優(yōu)先級(jí),所以數(shù)組指針的指針加括號(hào),所以看看指針有沒(méi)有用圓括號(hào)括起來(lái),就可以區(qū)分開(kāi)。


六. 其它


關(guān)于指針想寫的內(nèi)容還有很多,其實(shí)這只是開(kāi)了個(gè)頭,比如:野指針、函數(shù)指針、函數(shù)參數(shù)傳遞方式、const 修飾指針、動(dòng)態(tài)內(nèi)存分配: malloc 和 free、堆, 棧、內(nèi)存泄露......,以后慢慢補(bǔ)齊。

指針在鏈表使用的比較多,多寫一些鏈表的操作會(huì)對(duì)指針理解很有幫助,鏈表節(jié)點(diǎn)的增加、刪除、修改、查找,單向鏈表、雙向鏈表、雙向循環(huán)鏈表、內(nèi)核鏈表等等。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉