C語言-預處理程序

我們可以在C源程序中插入傳給編譯程序的各中指令,這些指令被稱爲預處理器指令,它們擴充了程序設計的環境。現把常用的預處理命令總結如下:
1.      預處理程序
按照ANSI標準的定義,預處理程序應該處理以下指令:
#if
#ifdef
#ifndef
#else
#elif
#endif
#define
#undef
#line
#error
#pragma
#include
顯然,上述所有的12個預處理指令都以符號#開始,,每條預處理指令必須獨佔一行。
2.      #define
#define指令定義一個標識符和一個串(也就是字符集),在源程序中發現該標識符時,都用該串替換之。這種標識符稱爲宏名字,相應的替換稱爲宏代換。一般形式如下:
#define macro-name char-sequence
這種語句不用分號結尾。宏名字和串之間可以有多個空白符,但串開始後只能以新行終止。
例如:我們使用LEFT代表1,用RIGHT代表0,我們使用兩個#define指令:
#define LEFT 1
#define RIGHT 0
每當在源程序中遇到LEFTRIGHT時,編譯程序都用10替換。
定義一個宏名字之後,可以在其他宏定義中使用,例如:
#define ONE 1
#define TWO ONE+ONE
#define THREE ONE+TWO
宏代換就是用相關的串替代標識符。因此,如果希望定義一條標準錯誤信息時,可以如下定義:
#define ERROR_MS “Standard error on input /n”
如果一個串長於一行,可在行尾用反斜線”/”續行,如下:
#define LONG_STRING “This is a very very long /
String that is used as an example”
3.      #error
#error指令強制編譯程序停止編譯,它主要用於程序調試。#error指令的一般形式是:
#error error-message
注意,宏串error-message不用雙引號包圍。遇到#error指令時,錯誤信息被顯示,可能同時還顯示編譯程序作者預先定義的其他內容。
4.      #include
程序中的#include指令要求編譯程序讀入另一個源文件。被讀入文件的名字必須用雙引號(“”)或一對尖括號(<>)包圍,例如:
#include “stdio.h”
#include <stdio.h>
都使C編譯程序讀入並編譯頭文件以用於I/O系統庫函數。
包含文件中可以包含其他#include指令,稱爲嵌套包含。允許的最大嵌套深度隨編譯器而變。
文件名被雙括號或尖括號包圍決定了對指定文件的搜索方式。文件名被尖括號包圍時,搜索按編譯程序作者的定義進行,一般用於搜索某些專門放置包含文件的特殊目錄。當文件名被雙括號包圍時,搜索按編譯程序實時的規定進行,一般搜索當前目錄。如未發現,再按尖括號包圍時的辦法重新搜索一次。
通常,絕大多數程序員使用尖括號包圍標準的頭文件,雙引號用於包圍與當前程序相關的文件名。
5.      條件編譯指令
若干編譯指令允許程序員有選擇的編譯程序源代碼的不同部分,這種過程稱爲條件編譯。
5.1#if#else#elif #endif
條件編譯指令中最常用的或許是#if,#else,#elif#endif。這些指令允許程序員根據常數表達式的結果有條件的包圍部分代碼。
#if的一般形式是:
#if constant-expression
 Statement sequence
#endif
#if後的常數表達式爲真,則#if#endif中間的代碼被編譯,否則忽略該代碼段。#endif標記#if塊的結束。
 
#else指令的作用與C語言的else相似,#if指令失敗時它可以作爲備選指令。例如:
#include <stdio.h>
#define MAX 100
 
Int main(void)
{
 #if MAX>99
 printf(“Compiled for array greater than 99./n”);
 #else
 printf(“Complied for small array./n”);
 #endif
 return 0;
}
注意,#else既是標記#if塊的結束,也標記#else塊的開始。因爲每個#if只能寫一個#endif匹配。
 
#elif指令的意思是“否則,如果”,爲多重編譯選擇建立一條if-else-if(如果-否則-如果鏈)。如果#if表達式爲真,該代碼塊被編譯,不測試其他#elif表達式。否則,序列中的下一塊被測試,如果成功則編譯之。一般形式如下:
#if expression
 Statement sequence
#elif expression1
 Statement sequence
#elif expression2
 Statement sequence
.
.
.
#elif expression
 Statement sequence
#endif
5.2#ifdef#ifndef
條件編譯的另一個方法是使用編譯指令#ifdef#ifndef,分別表示“如果已定義”和“如果未定義”。#ifdef的一般形式如下:
#ifdef macro-name
 Statement sequence
#endif
如果macro-name原先已經被一個#define語句定義,則編譯其中的代碼塊。
#ifndef的一般形式是:
#ifndef macro-name
 Statement sequence
#endif
如果macro-name當前未被#define語句定義,則編譯其中的代碼塊。
#ifdef#ifndef都可以使用#else#elif語句。
 
#inlucde <stdio.h>
#define T 10
 
Int main(void)
{
 #ifdef t
 Printf(“Hi T/n”);
 #else
 Printf(“Hi anyone/n”);
 #endif
 #ifndef M
 Printf(“M Not Defined/n”);
 #endif
 
 Return 0;
}
6.      #undef
#undef指令刪除前面定義的宏名字。也就是說,它“不定義”宏。一般形式爲:
#undef macro-name
7.      使用defined
#ifdef之外,還有另外一種確定是否定義宏名字的方法,即可以將#if指令與defined編譯時操作符一起使用。defined操作符的一般形式如下:
defined macro-name
如果macro-name是當前定義的,則表達式爲真,否則爲假。
例如,確定宏MY是否定義,可以使用下列兩種預處理命令之一:
#if defined MY
#ifdef MY
也可以在defined之前加上感嘆號”!”來反轉相應的條件。例如,只有在DEBUG未定義的情況下才編譯。
#if !defined DEBUG
 Printf(“Final Version!/n”);
#endif
使用defined的一個原因是,它允許由#elif語句確定的宏名字存在。
8.      #line
#line指令改變__LINE____FILE__的內容。__LINE____FILE__都是編譯程序中預定義的標識符。標識符__LINE__的內容是當前被編譯代碼行的行號,__FILE__的內容是當前被編譯源文件的文件名。#line的一般形式是:
#line number “filename”
其中,number是正整數並變成__LINE__的新值;可選的“filename”是合法文件標識符並變成__FILE__的新值。#line主要用於調試和特殊應用。
9.      #pragma
#pragma是編譯程序實現時定義的指令,它允許由此向編譯程序傳入各種指令。例如,一個編譯程序可能具有支持跟蹤程序執行的選項,此時可以用#pragma語句選擇該功能。編譯程序忽略其不支持的#pragma選項。#pragma提高C源程序對編譯程序的可移植性。
10. 預處理操作符###
有兩個預處理操作符:###,它們可以在#define中使用。
操作符#通常稱爲字符串化的操作符,它把其後的串變成用雙引號包圍的串。例如:
#include <stdio.h>
#define mkstr(s) #s
int main(void)
{
 Printf(mkstr(I like C));
 
 Return 0;
}
 
預處理程序把以下的語句:
Printf(mkstr(I like C));
變成
Printf(“I like C”);
操作符##把兩個標記拼在一起,形成一個新標記。例如:
#include <stdio.h>
#define concat(a,a) a##b
 
int main(void)
{
 Int xy = 10;
 Printf(“%d”,concat(x,y));
 Return 0;
}
預處理程序把以下語句:
Printf(“%d”,concat(x,y));
變成
Printf(“%d”,xy);
操作符###主要作用是允許預處理程序對付某些特殊情況,多數程序中並不需要。
11. 預定義宏
C規範了5個固有的預定義宏,它們是:
__LINE__
__FILE__
__DATE__
__TIME__
__STDC__
 
__LINE____FILE__包含正在編譯的程序的行號和文件名。
__DATE__和內容形如month/day/year(//)的串,代表源文件翻譯成目標碼的日期。
__TIME__中的串代表源代碼編譯成目標碼的時間,形如hour:minute:second(時:分:秒)
如果__STDC__的內容是十進制常數1,則表示編譯程序的實現符合標準C
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章