日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

c語言的預處理/條件編譯,最全整理看這里

 

語言的編譯過程中第一步進行的就是預編譯了,預編譯中就是執行#開頭的語句,這些處理就是本篇總結的知識點,預處理和條件編譯。

通俗的講預處理就是編譯器自動的幫我們上去整理一遍代碼,它依據的規則(我們交代給他的囑托)就是預處理指令和條件編譯的指令。

編譯器根據指令,將需要包含的代碼整體復制放到要包含的文件中,檢查條件編譯的條件是否成立,刪除用不到的代碼,留下有用的代碼,預處理的過程僅此而已。

要讓編譯器準確的完成我們交給他的任務,我們就必須準確的給它下達正確的命令,這些命令就是下面總結的內容了。只是常用到的知識點的總結,水平有限有錯誤在所難免歡迎指正。

1.預處理是c文件在編譯前的處理過程。

這個過程包括如下幾個內容:

  1. 刪除注釋
  2. 插入被#include包含的文件的內容
  3. 替換有#define定義的符號
  4. 確認條件編譯具體該進行編譯的部分

2.預定義器定義的符號(現成的)

這些符號是編譯器自帶的,不用我們自己定義,直接使用就可以。

一般在我們調試程序時,打印這些信息時使用它們。

  • __FILE__ :要進行編譯的文件的文件名
  • __LINE__:文件該符號所在行得行號
  • __DATE__:文件被編譯的日期
  • __TIME__:文件被編譯的時間

3.#define 定義符號名的用法

  1. 為數值命名一個符號。

Eg: #define name stuff (很容易跟typedef搞混前后順序)

用法:

  • 一般在程序的頭部定義該語句,之后就可以用name去代替stuff寫代碼了。編譯時語句中如果出現name,就會被預編譯器替換成stuff。

b. 文本替換

Eg1:

#define Ret returnval 為簡化名字的書寫和閱讀方便

Eg2:

#define Loop while(1); 可以替換一個語句,替換語句時注意“;”的問題

4.宏的使用

所謂的宏,其實是#define的文本替換的活用。

本質是是在文本替換的基礎上,再追加一步,參數的替換。

Eg 1:

#define MAX(a,b) ( (a)>(b)?(a):(b))

在代碼中的使用過程是這樣的:

第一步:文本替換

maxnum=MAX(2,4); —> ( (a)>(b)?(a):(b));

第二步:參數代入

maxnum=( (2)>(4)?(2):(4));

到此預處理器的宏處理階段完成。

5.宏的參數代入過程看起來很像是與函數的參數傳遞過程,有什么不一樣呢?

  • 1.宏的參數不限制類型使用參數時也不需要聲明類型,但是函數的參數必須聲明(規定)參數類型。

宏的這個特點有時可以帶入函數無法帶入的參數類型,進行運算。

Eg :

#define MALLOC(n,type) ( (type)*) malloc( (n) * sizeof(type) ) )

帶個數的結果:MALLOC(5,int ) —>(int*)malloc( (5)*sizeof(int) )

這里的參數type,函數是無法用參數進行傳遞的。

  • 2.實現機制不同,宏是通過預處理時文本替換實現,函數是通過運行時臨時調用和返回,這就帶來他們的優缺點:
  • 宏:不需要調用開銷,執行頻繁的簡單計算,缺點會增加代碼體積。
  • 函數:比較耗費系統資源,但不增加代碼體積。
  •  

6.#運算符和##運算符

#:將將宏參數插入字符串中。

Eg :

#define PRINT(a) pirntf("the value of a is %d.n",(a) )

int b=2;

PRINT(b); => the value of a is 2.

#define PRINT(a) pronrf("the calue of "#a"is %d.n",(a) )

int b=2;

PRINT(b); => the value of b is 2.

  • ##:粘合劑 字符合并

Eg :

#define RENAME(A) NewName ## A

RENAME(3); => NewName3

7.宏的注意點

  • 宏名全大寫字母表示
  • 每個參數必須加()
  • 宏的整體外面加一層括號
  • 不要在宏的末尾加分號
  • 替換文本(stuff)的內容太多可以用“”連接換行
  • 宏定義時:宏的參數列表(括號的左邊)與宏名(name)之間不能有空格。在代碼中使用無此規定
  • 宏的參數不能用 自增、自減等運算符,會有副作用

8.條件編譯

  • 用法1:

#if 常量表達式

statements

#endif

Eg :常用的調試語句

#define DEBUG 1 //1:打開 ,0:屏蔽

#if DEBUG

printf("File is %s,Line is %d",__FILE__,__LINE__);

#endif

這樣debug語句不會 影響程序本身運行。

  • 用法2:選擇編譯

#if 常量表達式

Statements;

#elif 常量表達式

Statements;

#elif 常量表達式

Statements;

#else

Statements;

#endif

預處理器從第一條依次判斷常量表達式的真假(0為假),

  • 從前往后當一個為真時,就編譯該分支的語句,忽略之后的所有 分支的語句,當所有的常量表達式均為假,才編譯“#else”分支的語句。
  • 注意:這里的常量表達式,一般用是一個用#define 聲明的常量,不要錯誤使用全局變量,或是const 修飾的只讀變量。

9.文件包含

  • a.你編寫被包含文件(.h)時,在文件頭部加上:

#ifndef _FILENAME_H

#define _FILENAME_H

XXXX(其他語句)

#endif

來防止重復包含

  • b.包含文件時的寫法分兩種:
  • #incldue <FileName.h>
  • 使用尖括號的,這是指包含的文件時自帶的庫函數頭文件
  • #include“FileName.h”
  • 使用雙引號的,這是包含用戶自己編寫的頭文件
  • 這兩種的區別就是編譯器搜索文件的方式不同。

在結束的時候,還是再說一下學習過程中的感想,預編譯這塊很容易被我們忽視,初學起來感覺難度并沒有很大,但是這里可以深究的地方還是很多的,多看一看這方面的例子,或者稍復雜些的宏定義,就會有很容易掉坑里的感覺,而且這里出現的Bug是很不容易被發現的。在程序編寫時,恰當的使用宏和條件編譯會讓程序的結構得到優化,在uboot中大規模的使用宏定義條件編譯相關的語句來實現配置選擇和功能的選擇,所以說這部分的知識很重要,需要取細細研究。爭取做到準確,熟練,快速的看懂,看的對宏的意圖!

分享到:
標簽:語言
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定