C、C++爲什麼有指針這種數據類型?

C語言引入指針這個語法(C++保留了這一語法),肯定有其合理性和必要性的考量。雖然增加了語言的複雜性,但能更靈活地操作數據結構,也能直接操作內存。

1 首先要理解幾個概念

1.1 存儲程序的概念。數據要存得進去,取得出來,還要考慮空間的效率和時間的效率。

1.2 數據存儲涉及到一個地址的概念,但如果將真正的地址呈現在你面前,類似於一個身份證號碼的純數字的東西,不方便記憶,也不夠直觀,所以在編程語言中弄出了變量、常量、字面量這些概念,都用一個有一定含義的標識符(如變量名)來表示,變量名與地址的映射由編譯器或解釋器配合操作系統來處理。這樣數據由標識符而不是具體地址呈現出來也就讓程序更易於編寫、閱讀和調試。由此,變量也就有了左值和右值的概念,左值對應變量的地址,賦值表達式的左值只能是變量;右值對應變量的具體的實際的值,相應的,在賦值表達式中可以用變量去引用實際值。

C/C++這樣的語言比較接近早期抽象計算機數據的思維方式,指針其實就是我們抽象數據並且這個數據是聚合但是實際內存離散的膠合層產物。後來出的語言通過其他的方式來抽象數據表示,將指針這個概念隱藏了,顯得友好了,但是其實他還在那。

1.3 複雜的程序必須涉及到複雜的數據結構,也就是一定要考慮批量的數據處理。那數據元素的關係需要考慮。而存儲到內存中,其實內存空間的地址是存在線性關係的,但變量名去把這個線性關係給弄沒了。

例如,一塊內存連續存了10個數據,這10個數據在內存地址上肯定存在線性關係,你如果知道了第一個數據的變量名,如果才能通過線性關係存取其他9個變量的數據呢?

這其實就是數組的概念,數組下標就是對內存地址線性關係的映射。

在C、C++中,就引入了指針的概念來映射內存中的地址並表示這個地址的線性關係。

其它語言也通過其它的方式(如引用)來達成類似的操作

1.4 另外還有一個問題,如果你想在程序運行時操作內存,由操作系統提供一塊內存後返回的只是一個地址,而通常普通變量只能存儲一個具體值,要存儲地址就需要用到專門的存儲地址的變量,那就是指針變量。

2 指針的作用

1.1 間接訪問

存儲區的數據通常是通過變量(或常量)進行訪問,有了指針,就多了一個訪問的方式,變量訪問通常稱為直接訪問,指針訪問也就稱為間接訪問。

利用指針變量間接訪問某一單元或一片連續的存儲區(如數組、結體體、類對象),在特定情形下,有一定優勢。

正確靈活地運用指針,可以提高程序代碼的質量。因為其能像彙編語言一樣處理內在地址,可以有效地表示和引用各種數據結構,如方便地使用數組和字符串,結構體結合自引用的指針構造鏈表等。

1.2 用作函數參數和函數返回值

函數調用時,函數參數會分配內存空間並賦值,如果參數是指針則賦的不是具體值,還是地址值,對指針的操作則是對指針指向的變量的操作。這就是值傳遞和指針傳遞的概念,可以通過指針傳遞來修改其它函數中定義的非全局數據。當然,如果你因為安全性的考慮,不想去修改其它函數中定義的非全局數據,可以在形參前冠一個const,作為常量的一個限定。

指針傳遞其實質還是在函數內部還是一個局部變量,但因為它是一個指針,它可以指向其它函數中數據,所以操作的對象因為指針的指向而發生了改變。

另外,函數指針用作函數參數時,可以由一個函數根據具體情況調用不同的函數。

另外,函數通常只能返回一個值,當然如果返回結構體和數組也可以返回多個值。有了指針,也可以通過返回數組指針或結構體指針來返回多個值

1. 3 靈活引用數組

如C語言中的字符串用字符數組來定義,兩個字符數組不能直接賦值,但利用字符數組指針則可以。

另外,利用指針來操作數據在特定情形下有其方便性。

數組名就是指針,但是它是一個常量指針,對應數組第一個元素的地址,數組名可以直接賦值給指針。

1.4 動態分配內存

利用指針在程序運行時動態分配內存是指針最重要的一個功能。

我們先來考慮一個問題,如果你想定義一個數組來保存一個班級的姓名,那你定義這個數組是容納多個個元素呢?如果這個元素數量在程序運行時再確定是一個最佳的方式。如果你聲明一個普通數組,必須在運行前(編譯時確定,其實是在定義數組時即具體確定)確定數組的大小,這是靜態數組、靜態綁定的概念。利用指針可以在運行時(編譯完後、程序運行時由程序與用戶交互或根據某個中間結果來視情況確定)再來確定這個數組的大小,具體的操作就是申請一塊根據運行時的具體情況確定大小(某個類型的元素數量)的內存,返回一個內存地址,把這個地址賦給一個指針,利用這個指針來操作這個數組(對應的內存),這是動態數組、動態綁定的概念。通常動態內存分配是分配內存中堆的數據。

在C語言中,通過malloc()、free()等函數來申請內存並返回內存地址或釋放內存。

在C++語言中,還可以通過new、delete兩個運算符來申請內存並返回內存地址或釋放內存。

-End-


分享到:


相關文章: