《C和指標》隨記

2021-09-01 11:18:18 字數 4873 閱讀 3715

/* 前陣子花兩周時間又把《c和指標》過了一遍,陸陸續續做了些筆記,現總結如下。。。*/

1. eof是乙個int型數值。

2. 去除某段**,將其注釋掉不是乙個好選擇,更高效、安全的辦法是使用 #if    #endf

#if 0

statements

#endif

3. 在c語言中,陣列引數是以引用形式進行傳遞的,也就是傳址呼叫,而標量和常量則是按值傳遞的。在函式中對標量的任何修改都會在函式返回時丟失;而當被呼叫函式修改陣列引數的其中乙個元素時,呼叫函式所傳遞的陣列就會被實際地修改。

4. 字串常量「hello」在記憶體中佔據6個位元組,按順序分別是h、e、l、l、o和nul。

5. 由於scanf函式的實現原理,所有標量引數的前面必須加「&」。不過,陣列引數前面不用加「&」,但是,陣列引數中如果出現了下標引用,也就是說實際引數是陣列的某個特定元素,那麼它的前面也必須加「&」符號。   

6. 執行順序是 s1>s2>s4>s3。

for(s1;s2;s3)
1. 注意養成良好的程式設計習慣。

1. 當乙個字串常量出現在乙個表示式當中時,表示式所使用的值就是這些字元所儲存的位址,而不是這些字元本身。因此,可以把字串常量賦值給乙個「指向字元的指標」,後者指向這些字元所儲存的位址。

2. 如果內層**塊有乙個識別符號的名字與外層**塊的乙個識別符號同名,內層的那個識別符號就將隱藏外層的識別符號——外層的那個識別符號無法再內層**塊中通過名字訪問。

3. 屬於external鏈結屬性的識別符號不論宣告多少次、位於幾個原始檔,都表示同乙個實體。

4. 關鍵字external和static用於在宣告中修改識別符號的鏈結屬性。如果某個宣告在正常情況下具有external鏈結屬性,在它前面加上static關鍵字可以使它的鏈結屬性變為internal。

5. 在定義型別的新名字時,使用typedef而不是#define。

1. break和continue語句,任何一條如果出現於巢狀的迴圈內部,它只對最內層的迴圈起作用,。無法使用break或者continue語句影響外層迴圈的執行。

3. 為了**的健壯性,在switch語句中應當使用default語句。

1. 算數左移和邏輯左移是相同的,即都在右邊補0;它們只有在右移時不同,且只有當運算元是負數時才不同。

2. 不要混用整形和布林型值。

1. 不能簡單地通過檢查乙個值的位來判斷它的型別。為了判斷值的型別(以及它的值),必須觀察程式中這個值的使用方式。

2. null指標不指向任何東西。要使乙個指標變數為null,可以給它賦乙個零值。

3. 從定義上看,null指標並未指向任何東西,因此對乙個null指標進行解引用操作是非法的。在對指標進行解引用操作前,首先必須確保它並非null指標。

4. 指標變數可以作為左值,並不是因為他們是指標,而是因為他們是變數。

5. * 操作符具有從右向左的結合性。 

6. 如果將乙個字元指標加1,運算結果產生的指標將指向記憶體中的下乙個字元。

7. 指標的加法運算沒太大意思。而對於指標減法,只有當兩個指標都指向同乙個陣列中的元素時,才允許乙個指標減去另乙個指標。同乙個陣列中兩個減法的值是兩個指標在記憶體中的距離(以陣列元素的長度為單位,而不是以位元組為單位),因為減法運算的結果將除以陣列元素型別的長度。

8. 任何指標之間都可以進行比較,測試它們之間相等或不相等。

9. 宣告乙個指標變數並不會自動分配任何記憶體。在對指標進行間接訪問前,指標必須進行初始化,或者使它指向現有的記憶體,或者給它分配動態記憶體。

1. 在涉及到使用原型函式時,最好使用標頭檔案。

2. 當程式呼叫乙個無法見到原型的函式時,編譯器認為該函式返回乙個整型值。對於那些並不返回整形值的函式,這種認定可能會引起錯誤。所以,所有的函式都應該具有原型,尤其是安歇返回值不是整形的函式。

3. 當乙個陣列作為引數傳遞給函式時,陣列名的值實際上是乙個指標,傳遞給函式的就是這個指標的乙份拷貝。下標引用實際上是間接訪問的另一種形式。

4. 使用字首自增或者自減可以避免越出陣列邊界。

5. 通過對static關鍵字的合理使用可以限制對模組的訪問(多用於黑盒設計)。

6. c通過執行時堆疊支援遞迴函式的實現。

1. 陣列名是乙個指標常量,也就是陣列第乙個元素的位址。它的型別取決於陣列元素的型別:如果它們是int型別,那麼陣列名的型別就是「指向int的常量指標」;如果它們是其他型別,那麼陣列名的型別就是「指向其他型別的常量指標」。

2. 陣列名不作為指標常量表示的情況有兩種——就是當陣列名作為sizeof操作符或者單目操作符&的運算元時。sizeof返回整個陣列的長度(位元組數)。對陣列名取位址所產生的是乙個指向陣列的指標,而不是乙個指向某個指標常量的指標。

3. 關於陣列的指標與下標,通常來說,下標絕不會比指標更有效率,但指標有時會比下標更有效率。(p144有乙個簡要的對二者的說明)。不過,這兩個技巧要合理使用,不要為了效率上的細微差別而犧牲了可讀性。

4. 關於暫存器指標變數:我們可以對指標使用暫存器變數,這樣就不必複製指標值。但是,它們必須被宣告為區域性變數。

暫存器存在於cpu內部,運算速度非常快,因為記憶體中的資料必須載入暫存器才能計算。如果直接定義乙個變數為暫存器變數,則少了載入等過程。對於頻繁使用的變數可以把它放在暫存器中提速。

5. 宣告乙個陣列時,編譯器將根據宣告所指定的元素數量為陣列保留記憶體空間,然後再建立陣列名,它的值是乙個常量,指向這段空間的起始位置。宣告乙個指標變數時,編譯器只為指標保留記憶體空間,它並不為任何整型值分配記憶體空間。

6. 多維陣列的儲存順序是根據最右邊的下標率先變化的原則確定的。同時,在多維陣列中,只有第一維才能根據初始化列表預設地提供,剩餘的幾個維必須顯式地寫出。

7. 下標引用優先順序高於間接訪問、

1. nul位元組是字串的終止符,但它本身並不是字串的一部分,所以字串的長度並不包括nul位元組。

2. 表示式中不要混用有符號數和無符號數。

3. 避免講乙個長字串複製到短陣列中從而導致溢位。

1. 宣告結構是有兩種比較好的方式,分別是結構標籤和typedef。

2. 結構不能包含型別也是這個結構的成員,但它的成員可以是乙個指向這個結構的指標。如果你覺得乙個結構內部包含乙個指向該結構本身的指標有些奇怪,請記住它事實上所指向的是同一種型別的不同結構。更加高階的資料結構,如鍊表和樹,都是用這種技巧實現的。每個結構指向鍊錶的下乙個元素或者樹的下乙個分支。

3. 在確定結構中某個元素位置時要考慮邊界對齊。sizeof返回值包含了結構中因邊界對齊而浪費的記憶體空間。

4. 相比將整個結構當做引數傳入函式,把指向結構的指標傳入函式顯然是更高效的辦法,因為指標比整個結構要小得多。傳遞指標要付出的代價主要是我們必須在函式中使用間接訪問來訪問結構成員。結構越大,把指向它的指標傳遞給函式的效率就越高。

5. 乙個聯合的所有成員都儲存於同乙個記憶體位置。通過訪問不同型別的聯合成員,記憶體中相同的位組合可以被解釋為不同的東西。

1. malloc的引數就是需要分配的記憶體位元組數。如果記憶體池中的可用記憶體可以滿足這個需求,malloc函式就返回乙個指向被分配的記憶體塊起始位置的指標。

2. 動態記憶體分配最常見的錯誤就是忘記檢查所請求的記憶體是否成功分配。第二大錯誤是操作記憶體時超出了分配記憶體的邊界。

3. 釋放一塊兒記憶體的一部分是不允許的。動態分布的記憶體必須整塊兒一起釋放。但是,realloc函式可以縮小一塊動態分布的記憶體,有效地釋放它尾部的部分記憶體。

4. 分配記憶體並使用完之後要注意釋放記憶體,不然會引起記憶體洩漏。

5. 如果乙個指標不是從早先的malloc、calloc、realloc函式返回的,它是不能作為引數傳遞給free函式的。

1. 單鏈表、雙鏈表的插入和刪除操作。

1. 函式呼叫操作符 () 優先順序高於間接訪問操作符。

2. 函式只能返回標量值,不能返回陣列。

3. 字串和陣列無法作為引數傳遞給陣列,但指向它們的指標卻可以。

4. 當乙個字串常量出現於表示式當中時,它的值是乙個指標常量,是指向字串第乙個字元的指標。和陣列名一樣,你既可以使用指標表示式也可以用下標來使用字串常量。

所以表示式 「xyz」+1  的結果是乙個指標,指向字串中的第二個字元:y。

5. 如果某個執行環節實現了命令列引數,這些引數是通過兩個形參傳遞給main函式的。這兩個形參分別是argc和argv。argc是乙個整數,用於表示引數的數量。argv是乙個指標,它是指向乙個序列的字元型指標的指標。該序列中的每個指標指向乙個命令列引數,其中第乙個引數是程式的名字。該序列以乙個null指標作為結束標誌。程式可以通過對argv使用間接訪問操作來訪問命令列引數。

1. 在用#define指令插入大段**時,如果這部分**出現在程式的幾個地方,那麼更好的方法顯然是把它實現為乙個函式。

2. 巨集與函式:

巨集非常頻繁的用於執行簡單的計算,比如

#define max(a,b)   ((a)>(b)? (a):(b))
在類似這種小型計算中,若使用函式進行呼叫和返回占用的計算資源可能更多,所以這種情況下使用巨集比使用函式在程式的規模和速度方面都更勝一籌。但是,更為重要的是,函式的引數必須宣告為一種特定的型別,所以它只能在型別合適的表示式上使用。反之,巨集可以用於整型、長整型、單浮點型、雙浮點型以及其他任何可以用》操作符比較值大小的型別。換句話說,巨集與型別無關

3. 當頭檔案被包含時,位於標頭檔案內的所有內容都要被編譯。這個事實意味著每個標頭檔案只應該包含一組函式或資料的宣告。和把乙個程式需要的所有宣告都放入乙個巨大的標頭檔案相比,使用幾個標頭檔案,每個標頭檔案包含用於某個特定函式或模組的宣告的做法更好一些。

4. 不要在乙個巨集定義的末尾加上分號,使其成為一條完整的語句。

5.整個巨集定義的兩邊要加上括號,另外巨集定義中每個引數也要加上括號。

/*結束*/

C語言 指標 隨記(1)

指標變數的定義 型別名 指標變數名 型別名 可以是任意型別 包括void 也稱基型別 p i 讀作 p指向i 如果 p指向i,那麼 p就是i p 以p中所儲存的內容作為起始位址,以p的基型別所佔位元組數作為偏移量,訪問此空間。指標傳參 在被調函式中,通過對形參指標的間接訪問,可以改變主調函式中實參指...

C語言隨記 指標運用

下面是一列宣告 int p 返回值為int的函式 int p 3 int型陣列 int p 返回值為 乙個int型指標的指標 的函式 int p 返回值為int的函式指標 int p 6 指向 int型陣列 的指標 陣列指標 int p 返回值為 int型指標 的函式 int p 6 指向 返回值為...

C語言隨記

1.c11 c語言新標準 2.表示系統自帶的庫,也可寫成 h 表示使用者自定義的庫 3.main函式是c語言的程式入口,現在大多為int main 而不是void main 4.記憶裡的c語言新特性 5.原始檔 通過編輯器建立的檔案,包含源 通常是.c檔案 6.c語言程式 編輯程式 c或.cpp 編...