App下載

從零開始學(xué)習(xí)C語言丨淺談指針類型

三玹 2022-10-31 14:42:29 瀏覽數(shù) (1969)
反饋
原文: https://mp.weixin.qq.com/s?__biz=Mzg3OTc3MjcyOQ==&mid=2247483771&idx=1&sn=6ac2a45bcc2b4da37eda0b5e04619351&chksm=cf7e142df8099d3b8918c4dbf7bfe0328683ea20aab2d146f9a8afae5f1d18d1cf30208b3d06&scene=178&cur_album_id=2588823761982849025#rd

  本文發(fā)布于微信公眾號:三玹
昨天不知道是怎么回事,大抵上是腦子突然抽了,竟選了C語言中公認難啃的硬骨頭——指針。
一晚上,看了許多關(guān)于指針的內(nèi)容,好像懂了,但是到了今天,想要輸出文章的時候又總覺得不得要領(lǐng),于是又花了一些時間進行研究。


內(nèi)存
沒有內(nèi)存,指針就沒有意義。因此,在學(xué)習(xí)指針之間,對內(nèi)存有一定的了解,是有助于指針的學(xué)習(xí)。
學(xué)習(xí)過計算機原理的朋友應(yīng)該都知道,計算機主要由硬件和軟件組成的。硬件的五個主要組成的部分:控制器、運算器、存儲器、輸入設(shè)備、輸出設(shè)備。而內(nèi)存,是屬于存儲器部分,顧名思義是用來存儲的一個硬件。
內(nèi)存不僅是用來存儲信息的,同時也承擔(dān)了構(gòu)建CPU和外部存儲器之間溝通橋梁的作用。這是因為外存相對于內(nèi)存,外存的讀寫速度會比較慢,而CPU的速度又是極快的,如果直接從硬盤拿數(shù)據(jù),就很浪費CPU高速的運算能力。
前面在學(xué)習(xí)變量的時候,我們可以知道,每創(chuàng)建一個變量,都會在內(nèi)存開辟一個空間,空間大小根據(jù)變量聲明的類型決定。例如一個字符char類型,所占空間大小為 1 Byte;一個整型int類型,所占空間大小為 4 Byte。
每個空間都有一個自己的編號,系統(tǒng)可以根據(jù)編號快速定位,從而拿到想要的數(shù)據(jù)。如果沒有這個編號,計算機要怎么拿到相應(yīng)的數(shù)據(jù)?想象一下,一個外賣員送外賣,如果不知道你是第幾層第幾戶,那么就要一層一層,一家一戶地敲開門確認。那就相當(dāng)麻煩。
這個編號,就是內(nèi)存地址,也就是接下來我們要說的指針。
指針
之前說過,如果沒有變量名,就要記住內(nèi)存地址,而內(nèi)存地址都是十六進制的一組數(shù)字,看起來非常抽象。對程序員來說,寫代碼沒有變量是一件極其痛苦的事情。
但現(xiàn)在我們想知道這個變量對應(yīng)的內(nèi)存地址是什么,那該怎么找呢?
C語言中提供了尋址運算符,&。在變量名前面加上這個尋址運算符,就可以找到了變量對應(yīng)的內(nèi)存地址。
#include<stdio.h>
int main(){
  int a;
  printf("%p", &a);
  return 0;
}
運行結(jié)果:0061FF1C
由此可見,內(nèi)存地址也是一個數(shù)據(jù)。既然作為一個數(shù)據(jù),那么就可以使用變量將其存儲起來。而作為一個變量,是需要聲明其是屬于什么類型的變量。因此,就有了指針變量和指針類型。
聲明一個指針變量的格式:
type* var;
type 即指針要指向的變量的數(shù)據(jù)類型,如int、double、char,或者后面會講到的void類型、構(gòu)造類型等;var 即指針的變量名。
指針類型和其他類型最大的區(qū)別就是,不同類型的指針所占用的空間大小都是一樣的(32位CPU是 4 Byte,64位CPU是 8 Byte)。
既然所有類型的指針所占空間都是一樣的,那為什么還要區(qū)分指針的類型呢?
這是因為指針變量存儲的只是指向的變量的內(nèi)存地址,如果沒有區(qū)分類型,當(dāng)需要從內(nèi)存中取值的時候,系統(tǒng)就不知道你要從當(dāng)前指向的地址取幾個字節(jié)。如果字節(jié)數(shù)沒取好,那么取得的數(shù)據(jù)就會產(chǎn)生錯誤。
下面模擬一下如果沒有類型,任意取值的結(jié)果:
#include<stdio.h>
int main(){
    int a = 123456789;

    char *p1 = (char*)&a;
    printf("只取1個字節(jié)的值:%d\n", *p1);

    short *p2 = (short*)&a;
    printf("只取2個字節(jié)的值:%d\n", *p2);

    int *p3 = &a;
    printf("取了4個字節(jié)的值:%d", *p3);

    return 0;
}
運行結(jié)果:
只取1個字節(jié)的值:21只取2個字節(jié)的值:-13035取了4個字節(jié)的值:123456789
指定了指針的類型,很大程度上給程序員解決了很多不必要的麻煩和問題。
指針類型除了可以根據(jù)指向的變量的類型進行分類,還有一種按級別分類,而這種分類我更愿意稱之為終極之無敵套娃。
先來看一個比喻:
有一天,一個快遞員跟你說,你買的快遞已經(jīng)送達了,請注意簽收,然后發(fā)給你一個取件碼。于是,你拿著取件碼,來到快遞架,打開柜子,發(fā)現(xiàn)里面只有一張紙條,上面寫著:你的快遞放在了第3排第5個。
你找到了紙條上的位置,打開一看,又是一張紙條,上面寫著:你的快遞放在了第8排第4個。緊接著你有按照上面說的找到了相應(yīng)位置,打開柜子,總算是拿到了快遞了。
這個比喻說的就是一個二級指針。
快遞架相當(dāng)于是內(nèi)存,每一個快遞柜子都是存儲單元。紙條上面的信息,即指向的內(nèi)存地址??爝f物件是想要數(shù)據(jù)。而你,就是計算機系統(tǒng)。
由此可知,一級指針,存放著普通變量的內(nèi)存地址。
二級指針,存放著一級指針的變量的內(nèi)存地址。
三級指針……
要這么多的套娃級別的指針是為了什么呢?
這就和數(shù)據(jù)結(jié)構(gòu)的知識有關(guān)聯(lián)了,這部分就到后面有用到了再詳細展開。這會兒學(xué)習(xí)這些,純屬是為了自己找麻煩。
最后
本篇文章就講到了這里,關(guān)于指針的內(nèi)容也僅僅是淺嘗而止。下一篇文章就回歸輕松一點的知識點,運算符。
最后,感謝各位朋友們的支持。如果有什么疑惑的地方或者文中謬誤之處,可以在評論指出一起討論學(xué)習(xí)。
C

0 人點贊