狠狠撸

狠狠撸Share a Scribd company logo
應用前置處理
? 前置處理功能
? 使用#define指令
? 使用#include指令
? 使用條件式編譯指令
Revised on July 18, 2021
Make
each
day
count
? 編譯器在進行程式編譯之前,會先處理以#開頭的命令,之後再將處理
結果與程式?起進行編譯,稱為前置處理
? 這些以以#開頭的命令並不是C語言敘述,又在程式編譯之前就被處理,
之為前置處理指令
? C 語言前置處理功能包括下列三種
? 引入檔案
? 使用 #include 前置處理指示詞引入指定標頭檔 (header file)
? 定義巨集
? 使用 #define 前置處理指示詞,將程式中之常值或程式碼以巨集名稱取
代,直到使用 #undef 前置處理指示詞解除
? 條件編譯
? 使用 #if、#elif、#endif 前置處理指示詞,產生適合執行環境的指令敘述
前置處理 1/2
2
Make
each
day
count
? 使用前置處理器具有下列優點
? 提高程式的可讀性
? 使用前置處理指示詞可使程式碼更簡潔,提高程式可讀性。例如
#include前置處理指示詞,可以取代??串標頭檔內容;使用 #define
定義符號常數,可方便閱讀及維護程式
? 提高執行效率
? 前置處理器執行後,會將程式中常數、字串、巨集名稱,用其內容取代,
程式執行時就不用再轉換,所以執行速度較快
? 適合開發大型程式
? 使用條件式編譯前置處理指示詞,可以依據環境執行不同的敘述,避免
產生錯誤
前置處理 2/2
3
Make
each
day
count
? #define 前置處理指示詞可以使用有意義的巨集名稱來代替常用的常值
或程式區塊,語法如下:
#define 巨集名稱 常值
#define 巨集名稱 (運算式)
#define 巨集名稱(引數列) (運算式)
? 定義常值
#define PI 3.14159
#define TRUE 1
#define FALSE 0
#define AUTHOR "wu, shyishiou"
#define BOOKS "書名:%s tt 作者:%s t 出版社:%s n"
? 已定義常值可使用#undef取消定義
? 定義無引數的巨集指令
#define DAY_SECONDS (60 * 60 * 24)
#define前置處理指示詞 1/4
4
Make
each
day
count
? 定義含引數的巨集指令
#define PI 3.14159
#define CIRCLE_AREA(r) (double)(PI * r * r)
#define MAX(x, y) (x > y? x : y)
#define ABS(x) ((x < 0)? –x : x)
? 巨集指令處理
#define MAX(x, y) (x > y? x : y)
int main(int argc, char** argv) {
printf("%d", MAX(3, 5));
printf("%f", MAX(5.3, 4.2));
}
經過前置處理,所有巨集名稱被置換為對應的運算式
int main(int argc, char** argv) {
printf("%d", (3 > 5? 3 : 5));
printf("%f", (5.3 > 4.2? 5.3 : 4.2));
}
#define前置處理指示詞 2/4
5
Make
each
day
count
? 如果巨集定義內容太?時,可以在行尾使用反斜線 () 換行
#include <stdio.h>
#include <stdlib.h>
#define LEAP_YEAR(x) x % 400 == 0 || 
x % 4 == 0 && x % 100 != 0
void test_macro2(void){
short year = 1;
while (year) {
printf("輸入?元的年代(0代表結束):");
scanf("%d", &year);
if (year) {
if (LEAP_YEAR(year))
printf("?元%d為潤年n", year);
else
printf("?元%d為平年n", year);
}
}
}
#define前置處理指示詞 3/4
6
Make
each
day
count
? 巨集指令則是每?個出現巨集指令處都會被置換為巨集定義內容,因
此程式碼會變?;由於沒有參數傳遞及回傳作業,執行效能較函式高
? 巨集則不會檢查參數資料型別,雖不利程式除錯,但使用較具彈性
#define MAX(x, y) (x > y? x : y)
printf("%d", MAX(3, 5));
printf("%f", MAX(5.3, 4.2));
? 經過前置處理後,程式碼如下
printf("%d", (3 > 5? 3 : 5));
printf("%f", (5.3 > 4.2? 5.3 : 4.2));
巨集指令與函式比較 1/2
7
Make
each
day
count
? 函式不管呼叫幾次,都是共用同?份函式定義指令敘述;
? 編譯器在編譯函式呼叫指令時,會檢核引數數目及資料型別,較有利
於程式除錯。若引數不同就必須定義不同的函式
int imax(int x, int y) {
return (x > y? x : y);
}
float fmax(float x, float y) {
return (x > y? x : y);
}
printf("%d", imax(3, 5));
printf("%f", fmax(5.3, 4.2));
? 簡單的運算適合使用巨集,而功能複雜的迴圏、條件式運算等,不容
易定義成巨集,就必須靠函式來實現
巨集指令與函式比較 2/2
8
Make
each
day
count
? 已完成測試又經常使用的巨集,可以將這些巨集單獨儲存成標頭檔,
新的程式只要以#include前置處理指示詞含入標頭檔就能直接使用
? #include前置處理指示詞語法如下:
#include <標頭檔名稱.h>
? 到系統預設的資料夾尋找指定的標頭檔,通常是用來含入標準標頭檔
#include "標頭檔名稱.h"
? 先到原始程式檔資料夾中尋找指定的標頭檔,若找不到再到系統預設的資料夾尋找
指定的標頭檔,通常是用來含入自定標頭檔
#include "路徑標頭檔名稱.h"
? 先到指定資料夾尋找指定的標頭檔,若找不到再到系統預設的資料夾尋找指定的標
頭檔,通常是用來含入自定標頭檔
#include前置處理指示詞 1/2
9
Make
each
day
count
--- define.h檔 ---
#define PI 3.14159
#define TRUE 1
#define FALSE 0
#define AUTHOR "wu, shyishiou"
#define CAUTHOR "吳錫修"
#define BOOKS "書名:%s tt 作者:%s t 出版社:%s n"
--- test_define.c檔 ---
#include "define.h"
void test_include(void) {
printf(BOOKS, "MASM 6.X組合語言程式設計", CAUTHOR, "松崗");
}
#include前置處理指示詞 2/2
10
Make
each
day
count
? 編譯時預設會編譯全部的程式碼,我們可使用條件式編譯前置處理指
示詞,使編譯器依據指定的條件,編譯或不編譯部份敘述,如此?來,
程式將會更有彈性
? #ifdef 及 #ifndef 條件編譯結構
? 程式中巨集如果重複定義,或未定義就呼叫使用都會造成錯誤
? 使用 #ifdef …#else…#end 結構可以判斷巨集是否已定義完成,來分別執
行不同的敘述
? #ifdef 可以認為是 #if defined 的縮寫
#ifdef _DEBUG
printf("正在使用 Debug 模式编译程序...n");
#else
printf("正在使用 Release 模式编译程序...n");
#endif
條件式編譯前置處理指示詞 1/5
11
Make
each
day
count
? 使用 #ifndef …#else…#end 結構可以判斷巨集是否還未定義,來分別執行
不同的敘述
#define PI 3.14
#ifndef PI
#define PI 3.14159
#endif
條件式編譯前置處理指示詞 2/5
12
Make
each
day
count
#include <stdio.h>
#define DEBUG
void test_preprocess(void){
int i, sum = 0;
#ifdef DEBUG
printf("debugingn");
#endif
#ifndef DEBUG
printf("no debugingn");
#endif
#ifdef WINDOWS
printf("windows coden");
#elif defined(UNIX)
printf("unix coden");
#endif
條件式編譯前置處理指示詞 3/5
13
Make
each
day
count
for (i = 0; i <= 5; i++){
#ifdef DEBUG
printf("%2d + %2d = %2dn", sum, i, sum + i);
#endif
sum = sum + i;
}
printf("sum = %dn", sum);
}
條件式編譯前置處理指示詞 4/5
14
Make
each
day
count
#define MY_PRINTF_VERSION 1
#if !defined(MY_PRINTF_VERSION)
#define MY_PRINTF_VERSION 1
#endif
#if MY_PRINTF_VERSION == 1
void printf(char* str) {
...
}
#elif MY_PRINTF_VERSION == 2
int printf(char* fmt, char* args, ...) {
...
}
#elif MY_PRINTF_VERSION == 3
int printf(unsigned char com_number, char* str) {
...
}
#endif
條件式編譯前置處理指示詞 5/5
15

More Related Content

颁语言应用前置处理