雖說指針是C語言中比較複雜的語法,但是確實非常好用,因此我寫過不少文章討論C語言中的指針,相信對初學者理解指針有一定的幫助。
事實上,的確有讀者私信我說看了這些文章,「總算不再畏懼指針了」。不過他同時也問了一個問題:C語言有「不透明指針(opaque pointer)」嗎?要是有的話,什麼樣的指針才是不透明指針呢,有什麼用呢?
C語言的「不透明指針」
坦誠地說,我比較討厭向初學者說一些非常「專業」的名詞,這不利於理解概念的本質,也容易讓一些初學者產生畏懼的心理。「不透明指針」就是其中之一,其實它並不是多難的概念,甚至都不是什麼新概念,只是一些基本知識的用法而已,只不過取了個非常裝x的名字。
從字面意思來看,「不透明」意味著看不到內部,因此「不透明指針」即看不到內部定義的指針。這樣說有些抽象,我們來看個例子:
typedef struct pmpi_s *pmpi;
上面這行C語言代碼使用 typedef 關鍵字定義了一個結構體指針類型 pmpi,結構體由 pmpi_s 指定。雖然還沒有具體定義結構體 pmpi_s,但是已經可以使用 pmpi 定義變量了,例如下面這行C語言代碼:
pmpi p = NULL;
這裡的指針 p 就是一個「不透明指針」,因為我們暫時看不到它到底指向什麼樣的內容,就像一個「不透明」的盒子一樣。
到這裡,相信讀者已經明白什麼是C語言中的「不透明指針」了,而且也能看出,所謂的「不透明指針」其實並不是什麼新概念,它不過是為了便於描述特定類型指針,方便同行之間交流取的名字而已。
C語言的「不透明指針」有什麼用呢?
一般來說,稍大的C語言項目都不是一個人開發的,在多人協作開發中,少不了要調用別人編寫的庫函數,或者要把自己編寫的庫函數提供給別人使用。
即使是初學者也應該明白,要調用C語言函數,首先需要知道它的原型,因此通常情況下,庫一般都會提供頭文件,頭文件裡包含庫裡實現的函數原型或者數據結構的定義。例如我們常用的 <stdio.h>就是標準 io 庫的頭文件,裡面包含標準庫函數(例如 printf)的原型。
可是,有時我並不希望將我編寫的庫所有細節公開給外界調用者。例如在原始碼中,有這樣的定義,相關C語言代碼如下,請看:
我只想在我自己的源文件(.c 文件)裡使用結構體 pmpi_s,而不希望外界調用者知道它的結構,從而輕易地修改相關數據。通常情況下,只要不把這個定義寫在對外公開的頭文件裡就可以了。但是,如果 handle_s() 也是需要公開的庫函數其中一個,那麼我將不得不提供 pmpi 結構體的定義,這樣看來,似乎不能兩全了?
當然不是,此時C語言的「不透明指針」就派上用場了,在頭文件裡放入結構體 pmpi 的不透明指針:
// fun.h 文件
typedef struct pmpi_s *pmpi;
void handle_s(pmpi p);
這樣一來,如果我的同事需要調用我編寫庫函數時,只需要包含 "fun.h" 就可以了,他能夠使用 handle_s() 函數,但是他不知道 pmpi_s 的具體結構,因為這是我想隱藏的內容。
小結
C語言的語法其實很精簡,一些看似複雜的概念(例如「不透明指針」)其實只是對基本概念的引用而已,透明指針可以隱藏庫的一些細節,一是為了安全,二是為了便於以後擴展——無論我在我的庫內如何修改 pmpi_s 結構體,也不會影響到外界的調用者。
其實就本文的例子,我們完全可以使用「萬能指針(void * 指針)」隱藏相關細節,這一點我之前的文章討論過,不再贅述了。
歡迎在評論區一起討論,質疑。文章都是手打原創,每天最淺顯的介紹C語言、linux等嵌入式開發,喜歡我的文章就關注一波吧,可以看到最新更新和之前的文章哦。
未經許可,禁止轉載。