《c和指標》之總結 四

2022-09-01 18:42:11 字數 3819 閱讀 2410

6、指標

計算機記憶體中的每個位置都由乙個位址標識。通常,鄰近的記憶體位置合成一組,這樣就允許儲存更大範圍的值。指標就是它的值表示記憶體位址變數。

無論是程式設計師還是計算機都無法通過值的位模式來判斷它的型別。型別是通過值的使用方法隱式地確定的。編譯器能夠保證值的宣告和值的使用之間的關係是適當的,從而幫助我們確定值的型別。

指標變數的值並非它所指向的記憶體位置所儲存的值。我們必須使用間接訪問來獲得它所指向位置儲存的值。對乙個「指向整型的指標」施加間接訪問操作的結果將是乙個整型值。

宣告乙個指標變數並不會自動分配任何記憶體。在對指標執行間接訪問前,指標必須進行初始化:或者使他指向現有的記憶體,或者給它分配動態記憶體。對未初始化的指標變數執行間接訪問操作是非法的,而且這種錯誤常常難以檢測。其結果常常是乙個不相關的值被修改。這種錯誤是很難被除錯發現的。

null指標就是不指向任何東西的指標。它可以賦值給乙個指標,用於表示那個指標並不指向任何值嗎。對null指標執行間接訪問操作的後果因編譯器而異,兩個常見的後果分別是返回記憶體位置零的值以及終止程式。

和任何其他變數一樣,指標變數也可以作為左值使用。對指標執行間接訪問操作所產生的值也是個左值,因為這種表示式標識了乙個特定的記憶體位置。

除了null指標之外,再也沒有任何內建的記法來表示指標常量,因為程式設計師通常無法**編譯器會把變數放在記憶體中的什麼位置。在極少見的情況下,我們偶爾需要使用指標常量,這時我們可以通過把乙個整型值強制轉換為指標型別來建立它。

在指標值上可以執行一些有限的算是運算。你可以把乙個整型值加到乙個指標上,也可以從乙個指標減去乙個整型值。在這兩種情況下,這個整型值會進行調整,原值將乘以指標目標型別的長度。這樣,對乙個指標加1將使它指向下乙個變數,至於該變數在記憶體中佔幾個位元組的大小則與此無關。

然而,指標運算只有作用於陣列中其結果才是可以**的。對任何並非指向陣列元素的指標執行算術運算是非法的(但常常很難被檢測到)。如果乙個指標減去乙個整數後,運算結果產生的指標所指向的位置在陣列第乙個元素之前,那麼它也是非法的。加法運算稍有不同,如果結果指標指向陣列最後乙個元素後面的那個記憶體位置仍是合法(但不能對這個指標執行間接訪問操作),不過再往後就不合法了。

如果連個指標都指向同乙個陣列中的元素,那麼它們之間可以相減。指標減法的結果經過調整(除以陣列元素型別的長度),表示兩個指標在陣列中相隔多少個元素。如果兩個指標並不是指向同乙個陣列的元素,那麼他們之間進行相減就是錯誤的。

任何指標之間都可以進行比較,測試他們相等或不相等。如果兩個指標都指向同乙個陣列中的元素,那麼他們之間還可以執行< 、<=、 >、 >=等關係,用於判斷他們在陣列中的相對位置。對兩個不相關的指標執行關係運算,其結果是未定義的。

如果指標並不指向任何有意義的東西,就把它設定為null。

7、函式

函式中對於沒有引數的函式,它的原型在引數列表中有個乙個關鍵字void 。常見的原型使用方法是把原型放在乙個單獨的檔案中,當其他原始檔需要這個原型時,就用#include 指令把這個檔案包含進來。這個技巧可以使原型必需的拷貝份數降低,有助於提高程式的可維護性。

return 語句用於指定從乙個函式返回的值。如果return語句沒有包含返回值,或者函式不包含任何return 語句,那麼函式就沒有返回值。在許多其他語言中,這類函式被稱為過程。在ansi c中沒有返回值的函式的返回型別應該宣告為void。

當乙個函式被呼叫時,編譯器如果無法看到它的任何宣告,那麼它就假定函式返回乙個整數值。對於那些返回值不是整型的函式,在呼叫之前對它們進行宣告是非常重要的,這可以避免由於不可**的型別轉換而導致的錯誤。對於那些沒有原型的函式,傳遞給函式的實參進行預設引數提公升:char和short型別的實參被轉換為int 型別,float型別的實參被轉換為double型別。

函式的引數是通過傳值的方式進行傳遞的,它實際所傳遞的事實參的乙份拷貝。因此,函式可以修改它的形參(也就是實參的拷貝),而不會修改呼叫程式實際傳遞的引數。陣列名也是通過傳值方式傳遞的,但它傳給函式的是乙個指向該陣列的指標的拷貝。在函式中,如果在陣列形參中使用了下標引用操作,就會引發間接訪問操作,它實際所訪問的是呼叫程式的陣列元素。因此,在函式中修改引數陣列的元素實際上修改的是呼叫程式的陣列。這個行為稱為傳址呼叫。如果你希望在傳遞標量引數時也具有傳址呼叫的語義,你可以向函式傳遞指向引數的指標,並在函式中使用間接訪問來訪問或修改這些值。

抽象資料型別,或稱黑盒,由介面和實現兩部分組成。介面是公開的,它說明客戶如何使用adt所提供的功能。實現是私有的,是實際執行任務的部分。將實現部分宣告為私有可以防止客戶程式所依賴於模組的實現細節。這樣,當需要的時候,我們可以對實現進行修改,這樣做並不會影響客戶程式的**。

有些函式的引數列表包含可變的參數量和型別,他們可以使用stdarg.h標頭檔案所定義的巨集來實現。引數列表的可變部分位於乙個或多個普通引數(命名引數)的後面,它在函式原型中以乙個省略號表示。命名引數必須以某種形式提示可變部分實際所傳遞的引數數量,而且如果預先知道的話,也可以提供引數的型別資訊。當引數列表中的可變部分的引數實際傳遞給函式時,他們將經歷預設引數提公升。可變部分的引數只能從第1個到最後1個依次進行訪問。

8、陣列

在絕大多數表示式中,陣列名的值是指向陣列第1個元素的指標。這個規則只有兩個例外。sizeof 返回整個陣列所占用的位元組而不是乙個指標所占用的位元組。單目操作符&返回乙個指向陣列的指標,而不是乙個指向陣列第1個元素的指標的指標。

除了優先順序不同以外,下標表示式array【value】和間接表示式*(array + (value))是一樣的。因此,下標不僅可以用於陣列名,也可以用於指標表示式中。不過這樣一來,編譯器就很難檢查下標的有效性。指標表示式可能比下標表示式效率更高,但下標表示式絕不可能比指標表示式效率更高。但是,以犧牲程式的可維護性為代價獲得程式的執行時效率的提高可不是個好主意。

指標和陣列並不相等。陣列的屬性和指標的屬性大相徑庭。當我們宣告乙個陣列時,它同時也分配了一些記憶體空間,用於容納陣列元素。但是,當我們宣告乙個指標時,它只分配了用於容納指標本身的空間。

當陣列名作為函式引數傳遞時,實際傳遞給函式的是乙個指向陣列第1個元素的指標。函式所接收到的引數實際上是原引數的乙份拷貝,所以函式可以對其進行操縱而不會影響實際的引數。但是,對指標引數執行間接訪問操作允許函式修改原先的陣列元素。陣列形參既可以宣告為陣列,也可以宣告為指標。這兩種宣告形式只有當他們作為函式的形參時才是相等的。

陣列也可以用初始值列表進行初始化,初始值列表就是由一對花括號包圍的一組值。靜態變數(包括陣列)在程式載入到記憶體時得到初始值。自動變數(包括陣列)每次當執行流進入它們宣告所在的**時都要使用隱式的賦值語句重新進行初始化。如果初始值列表包含的值的個數少於陣列元素的個數,陣列最後幾個元素就用預設值進行初始化。如果乙個被初始化的陣列長度在宣告中未給出,編譯器將使這個陣列的長度設定為剛好能容納初始值列表中所有值的長度。字元陣列也可以用一種很想字串常量的快速方法進行初始化。

多維陣列實際上是一維陣列的一種特型,就是它的每個元素本身也是乙個陣列。多維陣列中的元素根據行主序進行儲存,也就是最右邊的下標率先變化。多維陣列名的值是乙個指向它第1個元素的指標,也就是乙個指向陣列的指標。對該指標進行運算將根據它所指向陣列的長度對運算元進行調整。多維陣列的下標引用也是指標表示式。當乙個多維陣列名作為引數傳給乙個函式時,它所對應的函式形參的宣告中必須顯式指明第2維(和接下去所有維)的長度。由於多維陣列實際上是複雜元素的一維陣列,乙個多維陣列的初始化列表就包含了這些複雜元素的值。這些值的每乙個都可能包含巢狀的初始值列表,由陣列各維的長度決定,只有第1維的長度會被自動計算出來。

我們還可以建立指標陣列。字串的列表可以以矩陣的形式儲存,也可以以指向字串常量的指標陣列形式儲存。在矩陣中,每行必須與最長字串的長度一樣長,但它不需要任何指標。指標陣列本身要占用空間,但每個指標所指向的字串所占用的記憶體空間就是字串本身的長度。

只要有可能,函式的指標形參都應該宣告為const。在有些環境中,使用register關鍵字提高程式的執行時效率。

C和指標之IO總結

io操作就是簡單的從程式移進或移出位元組的事情,這種位元組流便稱為流 1 文字流 文字流是指在流中流動的資料是以字元形式出現 2 二進位製流 二進位製流是指流動的是二進位制數字序列,若流只有字元,則用乙個位元組的二進位制ascii碼表示,若是數字,則用對應的二進位制數表示。在流入流出時,對 n符號不...

《c和指標》之總結 三

5 操作符和表示式 操作符優先順序 操作符 描述 用法示例 結果型別 結合型 是否控制求值順序 聚組 表示式 與表示式同 n a否 函式呼叫 rexp rexp,rexp l r否 下標引用 rexp rexp lexp l r否 訪問結構體成員 lexp.member name lexp l r否...

《c和指標》之總結 二

3 資料 具有external鏈結屬性的實體在其他語言的術語裡稱為全域性 global 實體,所有原始檔中的所有函式均可以訪問他。只要變數並非宣告於 塊或函式定義內部,它在預設情況下的鏈結屬性即為external。如果乙個變數宣告於 塊內部,在它前面新增extern關鍵字將使它所引用的是全域性變數而...