在本章中 將 介紹 C 程式 中 #define 及 #include 等的使用, 與 C 編譯器之間的關係。
對於一個 C 程式 編譯之前, C 編譯器 會先處理 C 程式 中含有 #define、#undef、#if、#ifdef、#ifndef、#endif、#elif、#else 及 #include 敘述, 將之置換成一新 C 程式, 再將之編譯 成一 assembly 程式, 再轉成 machine code(或 object code)。 再經由 linker 變成一執行檔。
本章主要重點 即在討論 C 編譯器 前置處理 的部份 #define 及 #include 等的使用。
於 第 8.1 節 將介紹 #define 巨集 ( macro ) 的宣告與使用,
於 第 8.2 節 將介紹 #include 的使用,
於 第 8.3 節 將介紹 #if、#ifdef 等的使用。
本 章 主 要 內 容 如 下:
第 8.1 節 #define 巨集的宣告與使用
巨集指令 #define 宣告的格式如下
巨集指令的使用(或呼叫),如同函數的呼叫,將 macroname 置於程式中,
為一辨識個體(identifier)即可。對於含引數型的巨集指令(將於 8.1.2 節談到
引數型的巨集指令),其呼叫方式與函數的呼叫型式完全一樣。
巨集指令的使用範圍為有宣告處起至檔案的結束,一般而言,巨集指令
都是宣告於檔案的開端,或是宣告於檔頭,即檔案其副檔名為 .h 再以 #include
的方式加入。
例 1: 設有一 C 程式檔 file.c 其內容為:
第 8.1.1 節 常數辨識個體的宣告
為了程式易讀易維修,程式中的常數通常都是以巨集方式來宣告一常數
名稱,該名稱通常是以大寫的字串來表示。
本節將重複介紹 第 2.2.5 節 所提到的 符號常數。
例 2: 設有一 C 程式其內容如下:
說明:
一些常用的常數如 EOF, NULL 都是宣告於 stdio.h 檔中,要使用這些常數,於檔案
中必須加上 #include
第 8.1.2 節 含引數型的巨集指令
含引數型的巨集指令,其宣告格式為
其說明如下:
例 3:對於巨集指令的宣告
例 4:對於巨集指令的宣告
含引數的巨集指令,稍一不慎就會產生錯誤,如例 4 中 swap_int(s,t); 則會產生問題,
為什麼?
巨集指令的宣告亦有階層式,即可利用前面宣告過的巨集指令,如例 5。
例 5:階層式巨集指令
問題:試比較 macro 與 function 的優劣點。
第 8.2 節 #include 的使用
C 程式的設計,不僅可以用模組化的方式,以函數來表現,亦可將程式碼
依其不同的目的與功能,呈現在不同的檔案中。為了程式碼的一致性,如
常數,巨集指令,全域(global)變數的宣告(含 extern,將於第九章說明)一
些函數的宣告(僅列出函數的標題 heading)等,都放在一檔頭檔 .h,
當然不見的是要以 .h 當作副檔名,不過,一般都是以 .h 來當作
include 檔的副檔名,
再以指令 #include 方式將該檔 加入即可。指令 #include 的宣告方式如下
經過編譯器前置處理後,含指令 #include 這行則由該檔 filename 來代替,
如果 filename 是由 <,> 所含,則編譯器會到 include 目錄下去找該檔或至
預先所定的目錄去找。
例 6: 假設檔案 file1.h 的內容如下:
註:
第 8.3 節 #if、#ifdef 等的使用
如果我們在一檔案欲 include 一檔頭檔 file1.h ,又想避免在同一檔案宣告兩次相
同的東西,例如:
欲避免這種情況發生,每個 #include "file1.h" 指令, 我們可以改變為如下指令:
註:
#define macroname string
其說明如下:
#define MAXSIZE 100
main( )
{ int A[MAXSIZE]; }
於編譯時經過前置處理後,該程式變成
main( )
{ int A[100]; }
其中所有的 #define 指令都不見了,MAXSIZE 也都變成了 100。當然前
置處理後的結果我們也見不到。
#define MAXSIZE 100
:
:
main( )
{ int A[MAXSIZE]; .....;}
void f( )
{ ......
for (i=0;i < MAXSIZE; i++)
.........
}
#define macroname(arg1[,arg]) string1 arg1
其呼叫方式如同函數呼叫方式一樣。
#define set_nonnegative(A); if (A<0)\
A=A*(-1);
則於程式中
set_nonnegative(i);
經過前置處理後即變成
if(i<0)
i=i*(-1);
其中形式引數 A 皆由實際引數 i 來替代。
#define swap_int(A,B); {int t;\
t=A;A=B;B=t;}
於程式中巨集呼叫
swap_int(i,j);
經過前置處理後即變成
{int t; t=i; i=j; j=t;}
#define max(A,B) ((A>B)?A:B)
#define max3(A,B,C) max( max(A,B),c)
C++ 的 inline 作用如同 macro 的作用。
#include <filename>
或
#include "filename"
#define MAXSIZE 100
extern int size;
int f(int x);
假設檔案 file2.c 的內容如下:
#include "file1.h"
main()
{ int A[MAXSIZE],i,sum;
for(i=0;i < size;i++)
sum=sum+f(i);
}
又假設 file1.h 與 file2.c 都在同一目錄下
則經過前置處理, file2.c 就先變成
#define MAXSIZE 100
extern int size;
int f(int x);
main()
{ int A[MAXSIZE],i,sum;
for(i=0;i < size;i++)
sum=sum+f(i);
}
經過前置處理完成後,file2.c 就變成
extern int size;
int f(int x);
main()
{ int A[100],i,sum;
for(i=0;i < size;i++)
sum=sum+f(x);
}
回本章主目錄
又
則在檔案 file.c 內,變數 size 重複宣告了兩次而產生錯誤。
#if !define(FILE1)
#define FILE1 "file1.h"
#include FILE1
#endif
或是
#ifndef FILE1
#define FILE1 "file1.h"
#include FILE1
#endif
回第 7 章
至第 9 章
回 C 程式 主目錄