1、預先處理指令
(1)概念:C語言在對來源程式進行編譯之前,會先對一些特殊的預先處理指令作解釋(比如#include<>檔案包含指令),產生一個新的來源程式,這個過程稱為編譯預先處理,之後再進行通常的編譯。
(2)預先處理指令都是以符合“#”開頭的,並且結尾不用分號。
(3)預先處理指令可以放在檔案任何位置,他的作用範圍是從它出現的位置到檔案尾,習慣上我們常把它放在來源程式頭部,這樣它的作用範圍就是整個來源程式檔案了。
(4)預先處理指令可分成三類:宏定義、檔案包含、條件編譯
2、宏定義
(1)不帶參數的宏定義(宏名一般大寫)
一般形式:#define 宏名 字串 如:#define COUNT 5;
(2)帶參數的宏定義
一般形式:#define 宏名 (參數) 用括弧把參數括起來可以防止宏單純替換時因為運算子優先關係而造成運算結果不準確。
帶參數的宏比函數效率高,宏只會替換數值(文本對換),不計算,不會替換雙引號括住的字串。
舉例:
1)使用宏定義可以統一變數,方便維護。
#include<stdio.h>
#define COUNT 5 //宏名一般大寫,結尾不放分號“;”
void main()
{
int a[COUNT] = {1,2,3,4,5};
for(int i =0;i< COUNT;i++){
printf(“a[%d] = %d\n”,i,a[i]);
}
}
2)宏定義只會單純的替換,不會計算,不會替換雙引號括住的字串。
#include<stdio.h>
#define sum(a,b) a+b //宏定義只會單純的替換,不會計算,所以參數我們最好要用括弧括起來,如下那個宏定義
#define mul(a,b) ((a)*(b)) //如果mul(1+2,3+4)這種參數傳到宏這裡,因為用括弧把參數括起 來了,就不用擔心出現多個相同的宏計算不正確的問題了。
void main()
{
int b =sum(1,2);//這一句宏定義類似調用了函數
printf(“sum(1,2)=%d\n”,b);
int c =mul(1+2,3+4);
printf("mul(1+2,3+4)=%d\n",c);
int d =mul(2,3)/mul(4,2);//這樣相當於((2)*(3)) / ((4)*(2)),由於參數都有括弧括住了,不用擔心運算子優先關係而造成計算結果不準確的問題。所以說參數最好用括弧括起來。
printf(“mul(2,3)/mul(4,2)=%d”,d);
}
3、條件編譯
(1)概念:當滿足設定的條件時才把進行條件裡面的代碼編譯,這就是條件編譯。
(2)格式:
#if 條件1
...code1...
#elif 條件2
...code2...
#else
...code3...
#endif
說明:預先處理指令是編譯之前的,不是運行時的,所以條件編譯時間要注意if的條件,不要還沒運行,就先用來源程式裡面的變數作為條件進行判斷,變數是運行時才產生的,而條件編譯呢是在運行之前編譯的。所以條件編譯的條件一般是利用宏定義,因為宏定義和條件編譯都是編譯之前進行的。
如下面的一個錯誤例子:
#include<stdio.h>
void main()
{
int a =8;
#if a>7
printf("a>7");
#elif a<7
printf("a<7");
#else
printf("a!=7");
#endif
}
運行結果為a<7,與我們期望的結果不一樣,正常應該是輸出a>7才對。
正確的寫法如下:
#include<stdio.h>
#define a 8
void main()
{
#if a>7
printf("a>7");
#elif a<7
printf("a<7,%d",a);
#else
printf("a!=7");
#endif
}
輸出結果為a>7
(3)其他用法
1)#if defined(宏名)
...code...
#endif
說明:表示如果已經定義這個宏,則編代碼塊裡面的內容。
2)#if !defined(宏名)
...code...
#endif
如果沒有定義過這個宏,就將code編譯進去。
3)#ifdef 宏名 跟第一種一樣。
4)#ifndef 宏名 跟第二種一樣。
4、檔案包含
(1)概念:其實就#include指令,如果是系統內建的就用#include<檔案名稱>,它會到C語言函數標頭檔所在的目錄中尋找檔案。如果是要引入自己的檔案,則用#include “檔案名稱”,系統會先在來源程式目前的目錄下尋找,如果沒有,再到作業系統的path路徑中尋找,還找不到,才會到C語言的庫函數標頭檔所在目錄尋找。
(2)檔案包含要注意引入檔案重複問題,檔案重複會導致聲明重複。要想解決重複問題,可以通過宏定義判斷進行判斷是否已經定義過了,如果定義過了就不匯入進來,如果沒有再匯入進來。
代碼如下:
//防止一個標頭檔被重複包含
#ifndef _ONE_H 表示如果沒有定義過one.h
#define _ONE_H 就定義one.h這個宏