C語言中的「不透明」指針是什麼,它有什麼用呢?

2020-12-06 IT劉小虎

雖說指針是C語言中比較複雜的語法,但是確實非常好用,因此我寫過不少文章討論C語言中的指針,相信對初學者理解指針有一定的幫助。

事實上,的確有讀者私信我說看了這些文章,「總算不再畏懼指針了」。不過他同時也問了一個問題:C語言有「不透明指針(opaque pointer)」嗎?要是有的話,什麼樣的指針才是不透明指針呢,有什麼用呢?

C語言的「不透明指針」有什麼用?

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語言代碼

我只想在我自己的源文件(.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等嵌入式開發,喜歡我的文章就關注一波吧,可以看到最新更新和之前的文章哦。

未經許可,禁止轉載。

相關焦點

  • C語言陷阱與技巧31節,都說void*指針是「萬能指針」,它萬能在哪
    在C語言程序開發中,一些比較成熟的庫函數常常會被使用。畢竟,如果手邊就有不錯的「輪子」可以用,沒有程式設計師願意再花費精力憑空造一個輪子出來。對於 void 型指針,之前的分析似乎就不再適用了。因為 void 類型是一個特殊的類型,常被稱作「空類型」,C語言中沒有 void 類型的變量,所以在遇到 void 指針時,編譯器根本不知道如何解釋接下來的內存,甚至編譯器都不知道接下來多少內存屬於它。
  • 奇怪的C語言代碼,在變量前加上(void)是什麼操作?有什麼用?
    C語言的語法極其簡潔,即使是初次接觸程式語言的初學者也能很快學完它的語法。不過,C語言也是一門「靈活得過了頭」的程式語言,對於很多初學者來說,編寫C語言程序就好像拿著一堆最基本的磚塊,要修建一座大廈一樣,茫然找不到方向。
  • 定義只有一個數組成員的C語言結構體有什麼用?
    在C語言程序開發中,有經驗的程式設計師有時會定義只有一個數組成員的結構體,雖然語法簡單,但是卻常常讓初學者感到迷惑:這麼做有什麼好處嗎?struct ABC {unsigned long array[MAX];} abc;
  • C語言的指針,簡介
    指針,是一個表示變量或函數的地址的無符號整數。指針的字節數,與CPU的位數有關,32位機是4位元組,64位機是8位元組。與高級語言的long類型的大小是一致的。C語言的結構體的地址,也是結構體的第一個成員變量的地址。當然,類型是不一樣的,數值一樣。C語言一般把管理結構的結構體變量,嵌入到它要管的數據結構裡,而且一般會放在第一個位置。
  • 第四篇:C語言中指針與字符串核心知識點梳理
    前面在講變量的時候,其中有一個特點就是變量的內存地址,即:變量在內存中實際的保存位置。這個內存地址如何獲取?它又有什麼意義?這就涉及到本文要講到的第一個核心概念:指針。重點包括:指針處理一維數組、動態內存分配等。C語言的基本數據類型中有一個char的關鍵詞,可以存儲單個的字符。那麼,像漢字以及由多個字符組成的內容,又該如何存儲呢?
  • C 語言這麼厲害,它自身是用什麼語言寫的?
    作者 | 劉欣這是來自我的星球的一個提問:「C語言本身用什麼語言寫的?」換個角度來問,其實是:C語言在運行之前,得編譯才行,那C語言的編譯器從哪裡來?用什麼語言來寫的?如果是用C語言本身來寫的,到底是先有蛋還是先有雞?
  • C語言,局部變量的指針,棧幀
    C/C++不能返回局部變量的指針,是一條重要的語法規則。至於為什麼,則不是那麼顯眼。局部變量,是分配在棧上的變量,隨著函數調用的返回而失效。函數調用結束之後,局部變量的指針,也就是野指針了,不能在函數外繼續使用。
  • 青少年信息學競賽Pascal語言:指針(十)
    合肥奧數網訊:合肥市青少年信息學競賽Pascal語言:指針   指針   指針是通過地址來訪問變量的一種特殊的數據類型,屬於動態的數據結構,它可以在需要時產生,用完後則又可以取消或回收,以減少佔用的內存空間。指針變量與其他類型的變量不同,它佔有的不是數據,而是地址。
  • C語言|文件指針、fopen()、fscanf()、fclose()
    這是一個簡單的文件系統fscanf()函數的功能是把磁碟文件數據讀出保存到變量(內存)每一個文件都有自己的FILE結構和文件緩衝區exit(0)是系統標準函數,作用是關閉所有打開的文件,並終止程序的執行。
  • C語言編程:以實例教你學指向函數的指針
    指針是C語言的精髓,對於初學者來講,指針是C語言語法學習中比較難的知識點,而這裡面指向函數的指針更是不太容易理解。下面給大家講下怎樣學習理解C語言中指向函數的指針及編程方法和使用例子。注意:這是一篇關於C語言編程的基礎語法內容,C語言大神請繞過。
  • C語言相關文件的基本知識
    用過計算機的人,對文件都不陌生,大多數人都接觸過,今天我們來講講關於C語言相關文件的基本知識。首先,我們先來了解了解什麼是文件。文件有不同的類型,在程序的設計中,主要有兩種文件; 1.程序文件;包括源程序文件(後綴為.c),目標文件(後綴為.obj),可執行文件(後綴為.exe)等,這類文件的內容是程序代碼。
  • 深入理解C語言
    我相信你對a的輸出相當有把握,就分別是4,5,6,因為那個靜態變量。對於c呢,你應該也比較肯定,那是一堆亂數。但是你可能不知道b的輸出會是什麼?答案是1,2,3。為什麼和c不一樣呢?因為,如果要初始化,每次調用函數裡,編譯器都要初始化函數棧空間,這太費性能了。但是c的編譯器會初始化靜態變量為0,因為這只是在啟動程序時的動作。
  • C語言中的main函數參數,你了解嗎?
    小豆丁:今天我才發現,C語言中main函數還有參數,可是我不知道這個參數表示的是什麼含義,也不知道怎麼用。老張:就這點問題?小豆丁:嗯吶,我沒研究明白,好沮喪...老張:這個問題不難,別放棄哈,我教你!
  • 「C語言從入門到入土」必備C語言基礎筆記整理
    一、C語言1、什麼是C語言?C語言是人寫機器看的一種語言。C語言是高級語言中的低級語言。C語言貼近硬體。C語言的入門學習比較簡單。彙編語言——>B語言——>C語言2、C語言的特性首先C語言就是你的女朋友。無論你讓它幹什麼,它絕對不會自己找到方法。
  • ARM中ADS環境下C語言和彙編語言混合編程及示例
    稍大規模的嵌入式程序設計中,大部分的代碼都是用C來編寫的,主要是因為C語言具有較強的結構性,便於人的理解,並且具有大量的庫支持。但對於一寫硬體上的操作,很多地方還是要用到彙編語言,例如硬體系統的初始化中的CPU 狀態的設定,中斷的使能,主頻的設定,RAM控制參數等。
  • 「懸空指針」和「野指針」究竟是什麼意思?
    本文轉載自【微信公眾號:strongerHuang,ID:strongerHuang】經微信公眾號授權轉載,如需轉載與原文作者聯繫提起C語言大部分開發者很自然就會想到指針二字,沒錯,作為C的核心和靈魂,它的地位咱們就不再贅述了,現在我們想跟大家講的是指針中的兩個特有名詞:「懸空指針
  • C語言之const和volatile"究極"學習
    一、const的用法:1、const只讀變量:const修飾的變量是只讀的,本質上還是變量const修飾的局部變量在棧上分配空間const修飾的全局變量在全局數據區分配空間const只在編譯期有用,在運行期沒有用註:const修飾的變量不是真的常量,它只是告訴編譯器該變量不能出現在賦值符號的左邊
  • c語言中malloc申請的空間和直接定義變量申請的空間有什麼區別?
    有很大區別。根據以前的編程經驗,要點有三點:一是空間分配的連續性;二是動態內存申請;三是防止程序執行中出現異常錯誤。以下分別說明。直接定義變量與malloc定義變量的編程含義;malloc事先分配好了內存空間。
  • C語言中的main()函數可以有好幾種類型,為何都能做入口函數呢?
    為什麼在C語言程序中,可以有不同類型當然,在一些比較舊的教材或者C語言代碼中,讀者可能還見過 void 返回值類型,甚至沒有寫返回值類型的 main() 函數原型:void main();而C語言沒有重載語法,為什麼在C語言程序中,可以有不同類型的 main() 函數呢?為什麼在C語言程序中,可以有不同類型的 main() 函數呢?C語言程序支持多種類型 main() 函數,其實和支持可變參數函數是類似的。
  • C語言與C++、C Sharp究竟是什麼關係?(附福利)
    簡單來說,C++就像是C語言的親弟弟,而C Sharp(C#)就是他們二者的遠房親戚(其實它更像是Java的表兄弟)。這三門語言都是十分優秀的程式語言,也都有很高的運行效率。這三種程式語言的應用範圍很廣闊,接下來技術學派就分別介紹一下三種語言的來歷以及應用領域。C語言C語言誕生在大名鼎鼎的美國貝爾實驗室,它的前身是B語言。