C基礎課程筆記總結9 預處理,巨集,以及其他

2021-07-02 04:47:38 字數 3782 閱讀 1242

課程:預處理,巨集

預處理語句是不需要用分號結尾的,其他任何語句都需要用分號結尾,預處理指令有3個:

1:巨集定義。

2.條件編譯。

3:檔案包含。

預處理指令是在**翻譯成0和1之前執行的指令,**執行需要首先編譯,翻譯為0和1,然後在鏈結,之後執行

所有的預處理指令都是以「#」號開頭,位置隨意,即可以定義在內部,也可以定義在外部,作用域由定義的那一行開始,一直到檔案結束。。

巨集定義:#define,分為兩種:帶引數或不帶引數。

不帶引數的巨集定義多用於更改陣列的長度,在迴圈條件中可以不用頻繁更改**,良好的程式設計習慣。

巨集定義的常量名全大寫,但是如果程式中有和巨集定義常量同名的字串,編譯時不對字串進行替換處理。

並且巨集名是乙個識別符號,要按照識別符號命名規則命名,通常使用"_"來代替「.」,可以定義乙個空的巨集名,即不做任何文字替換。

如果在檔案結束之前想讓巨集定義失效,使用指令:#undef 巨集名,在這一行開始,這個巨集名就不再有作用。

巨集名的命名規範:一般全大寫,或者以k(表示常量)開頭之後再全大寫。

帶引數的巨集: #define 巨集名(引數) 表示式,這個指令表示把左邊的巨集名完全代替為右邊的表示式(完全替換即純文字替換,寫什麼就是什麼),

表示式中最好每乙個都加上括號,否則極易出現未知的語義錯誤,加括號是良好的程式設計習慣。

對於簡單的運算,用巨集定義也能實現相關功能,用函式也能實現相關功能,但是巨集定義是純粹的文字替換,並沒有生成結果,效率更高,呼叫函式時系統需要先找到函式,

然後在分配記憶體空間。

條件編譯:

條件編譯即滿足條件時,某個**(塊)才會編譯為0和1,寫入。o檔案中執行,類似if else else elseif,最後的if一定不要忘記寫。

如果不寫條件編譯,則在程式中對於所有的if。。。else。。。語句都會全部編譯,使用條件編譯效率更高。

條件編譯在ios中很常用,條件編譯格式如下:

#if......

#elif...........注意是  e l i f,  不是else

#else.........這個才是else

#endif   這個一定不能忘記寫,有了#if 一定要有#endif,否則出現未知錯誤因為如果沒有#endif,在預處理指令執行後,除了滿足條件的那個語句被保留編譯為01,這條語句之後的所有一切,

包括其他**,和配對的大括號,都會全部不編譯為01,因此,系統編譯時會報錯,而加入#endif之後表示作用if 和elseif 之間。

條件編譯是預處理命令,因此必須保證條件編譯中所涉及的相關變數在編譯函式之前就存在,一般和巨集定義搭配使用,保證最先存在。

還有一些不常用的操作如下:

#if define ()   =#ifdef 巨集常量:如果定義了乙個對應的巨集常量,編譯此語句。

#if !define() = #ifndef 巨集常量:如果沒有定義乙個對應的巨集常量,編譯此語句。

書寫習慣,在寫了#if之後必須寫上#endif

檔案包含:

需要呼叫檔案外部函式時,必須先宣告這個外部函式,可以通過包含那個函式檔案的。h檔案來實現,在。h檔案中,宣告了所有的相關函式

檔案包含不允許迴圈包含,即不能你包含我,我包含你,在檔案中,函式只能定義一次,而函式的宣告可以宣告n次,每一次 編譯器都會翻譯,降低了編譯器的效率。

#ifndef abc

#define abc

宣告相關函式

#endif     有了#if。。。一定要寫#endif

則在其他檔案中宣告該。h檔案時,根據預處理指令的執行順序,宣告函式永遠只宣告一次,但在多個。h檔案中,有可能定義同名的巨集,因此在實際開發中,通常使用檔名作為巨集定義變數,以此保證巨集名的唯一性。

用<>表示包含系統檔案,用「」表示包含自定義的檔案

關鍵字:typedef

typedef比較常用,可以簡化**量

格式如下:

typedef 型別名  型別別名

例如:typedef int  myint 即定義了乙個int型別的別名,還可以個myint 在定義另乙個別名。因此typedef作用就是定義別名,配合結構體變數可以少寫**量,也可以配合匿名結構體,即可以搭配自定義型別使用,來簡化**量定義方法靈活多變。

也可以配合列舉型別enum來使用,,還有指向結構體變數的指標,  還有指向函式的指標,也可以配合typedef使用,但是格式略有不同。

typedef既可以定義在內部,也可以定義在外部。

typedef使用的注意點:

在某些場合中使用巨集定義 #define  純文字替換,也可以完成typedef的功能,但始終要記住,巨集定義只是純粹的問題替換而已,而typedef是根據乙個實在存在的型別去定義替換的,因此還是有區別的,不建議使用巨集定義替換型別

關鍵字:static和extern

在實際開發中static經常使用,而extern(外部的)在面試中常見。

這兩個關鍵字都可以作用於函式和變數。

整個專案的不同檔案中的外部函式不能同名,會有衝突

內部函式:定義的函式只可以在本檔案中訪問,使用static定義的函式,如果要定義和宣告乙個內部函式,不能省略static 關鍵字,內部函式相當於對外部不可見,在不同檔案中可以有同名的內部函式。

對變數的作用:

變數也分為兩種:全域性變數

全域性變數又分為兩種:外部全域性變數,內部全域性變數,顧名思義。在預設情況下,所有的全域性變數都是外部變數,並且預設初始化值是0,所有檔案都可以訪問,

同一種變數型別,同乙個變數名,不論宣告多少次,不論是在哪個檔案中,都是指向同乙個全域性變數。但是如果是不同變數型別,同變數名呢??????

c中全域性外部變數使得資料封裝性很差,任意外部都可以改變變數的值。

而全域性內部變數,只能是所在定義的檔案訪問,其他檔案無法訪問。用static修飾定義在函式外部的變數即可,有定義的那一行開始生效,直到當前檔案結束。

而extern作用於變數,則表示該變數為外部變數,既可以在函式內部宣告,也可以在外部宣告。

extern對於函式的作用,既可以宣告也可以定義(extern可以省略)

extern對變數的作用,只能是宣告變數 

static對於函式的作用,既能定義也可以宣告。

static對於變數既可以定義,也可以宣告變數。

static對區域性變數的作用

區域性變數必須手動初始化,全域性變數有預設的初始化值。

區域性變數即是定義在函式內部的變數,當這個函式被呼叫時,才會在記憶體中開闢儲存空間,當這個函式執行完畢時,分配個這個函式的空間也將釋放,這些空間中的變數也會消失,

再次呼叫同乙個函式時,又會重新分配乙個新的記憶體空間。

當用static定義乙個區域性變數時,則這個變數的在該函式第一次呼叫時分配記憶體空間,在函式執行完畢後不會消失,當再次呼叫該函式時,就能繼續使用這個static區域性變數,這個區域性變數一直存在於同乙個記憶體位址中,直到整個程式結束後記憶體才釋放,

但是這個變數的作用範圍仍是該函式內部,使用static定義後並沒有改變這個變數的作用域。即對於這個變數而言,它將會被所有的同乙個函式所共享,但不是被所有函式共享

使用static修飾區域性變數,可以在一定程度上優化效能。對於乙個函式而言,如果函式中有某個變數需要頻繁使用,但是該變數的值是一直不變的,則可以將變數定義為乙個static區域性變數

例如求圓的周長或面積時所使用的圓周率,則可以定義為乙個static區域性變數,為何不用全域性變數呢?因為只有呼叫到求周長和面積函式時才需要用到pi。

遞迴:問:函式的內部遞迴也會一直分配新的記憶體空間嗎??

答:是的,遞迴也是函式呼叫,每一次函式呼叫都會分配記憶體空間(不是在同一塊記憶體空間,而是另外的空間),所以遞迴十分消耗系統資源,多層遞迴時有可能造成系統崩潰。

設計遞迴函式首先先找出思路,找出重複步驟,並且要有乙個終止條件。

C基礎課程筆記總結5 陣列

課程 陣列 陣列在c中屬於構造型別,構造型別即有n個基本資料型別所組成的一種型別。陣列名的含義永遠是乙個位址值。sizwof 陣列名 返回陣列所佔的總位元組數,總位元組數是指當前每個元素所佔記憶體空間的大小再x元素個數,除以相應的型別位元組數,即可得到陣列的長度,即儲存了多少個元素。在c中,陣列的下...

侯捷老師C 基礎課程筆記1 2

基於物件 object based 與物件導向 object oriented 的區別 通常 基於物件 使用物件,但無法利用現有的物件模版產生新的物件型別,繼而產生新的物件。即 基於物件 只有封裝,沒有繼承和多型的特點。物件導向 具有 封裝 繼承 多型 三大特點,缺一不可。版本c 98 是c 1.0...

慕課網《HTML CSS基礎課程》筆記總結(五)

每一條css樣式宣告 定義 由兩部分組成,形式如下 選擇器 在 之前的部分就是 選擇器 選擇器 指明了 中的 樣式 的作用物件,也就是 樣式 作用於網頁中的哪些元素。比如右側 編輯器中第7行 中的 body 就是選擇器。p 上面的css樣式 的作用 為p標籤設定12px字型大小,行間距設定1.6em...