源代碼的預(yù)處理發(fā)生在編譯為機(jī)器指令之前。
預(yù)處理階段可以執(zhí)行由#
符號(hào)啟動(dòng)的預(yù)處理指令指定的操作范圍。
預(yù)處理階段在編譯之前處理C源代碼。
在預(yù)處理階段后,將分析和執(zhí)行所有指令,并且所有預(yù)處理指令將不再出現(xiàn)在源代碼中。
#include
和 #define
是兩個(gè)流行的指令。
用#define語(yǔ)句定義常量。
#include <stdio.h>
#define PI 3.14159
int main(void)
{
float area, circum, radius;
printf("What is the radius of your pizza?\n");
scanf("%f", &radius);
area = PI * radius * radius;
circum = 2.0 * PI *radius;
printf("Your basic pizza parameters are as follows:\n");
printf("circumference = %1.2f, area = %1.2f\n", circum,
area);
return 0;
}
上面的代碼生成以下結(jié)果。
你完全熟悉這樣的語(yǔ)句:
#include <stdio.h>
上面的代碼將標(biāo)準(zhǔn)庫(kù)頭文件的內(nèi)容帶入您的程序。
#include指令引入到程序中的文件也可能包含#include指令。
您可以定義自己的頭文件,通常使用擴(kuò)展名為.h。
頭文件不應(yīng)包括實(shí)現(xiàn)。
您創(chuàng)建頭文件以包含聲明。
所有的函數(shù)定義和全局變量都放在擴(kuò)展名為.c的源文件中。
您可以將函數(shù)原型,結(jié)構(gòu)類型定義,符號(hào)定義,extern語(yǔ)句和typedefs放在頭文件中。
一個(gè)典型的例子可能是:
#include "myfile.h"
要使用另一個(gè)文件的全局變量,請(qǐng)使用extern關(guān)鍵字將該變量聲明為當(dāng)前源文件的外部變量。
例如,假設(shè)您的語(yǔ)句在另一個(gè)文件中定義了全局變量:
int number = 0; double in_to_mm = 2.54;
在要訪問這些文件的源文件中,指定這些變量名稱是外部的:
extern int number; extern double in_to_mm;
這些語(yǔ)句不會(huì)創(chuàng)建這些變量。
他們通知編譯器這些名稱被定義在哪里。
您可以通過將其聲明為靜態(tài)來(lái)確保函數(shù)僅在您定義它的源文件中可見。
例如:
static double average(double x, double y) { return (x + y) / 2.0; }
define預(yù)處理器指令的一般形式如下:
#define identifier sequence_of_characters
這里,標(biāo)識(shí)符符合C中標(biāo)識(shí)符的通常定義。
在#define語(yǔ)句中定義字符串。
#include <stdio.h>
#define PRAISE "You are an extraordinary being."
int main(void)
{
char name[40];
printf("What"s your name? ");
scanf("%s", name);
printf("Hello, %s. %s\n", name, PRAISE);
return 0;
}
上面的代碼生成以下結(jié)果。
宏是預(yù)處理器,允許可以稱為多個(gè)參數(shù)化替換。
這涉及到用于令牌標(biāo)識(shí)符的字符序列的替換。
一個(gè)例子將使這更容易理解:
#define Print(My_var) printf_s("%d", My_var)
My_var
是一個(gè)參數(shù)名稱,可以指定一個(gè)字符串。
該指令提供兩個(gè)替代級(jí)別。
代碼中的Print(My_var)的出現(xiàn)將被緊隨其后的字符串以及您為My_var指定的任何參數(shù)所代替。
例如,你可以寫下列內(nèi)容:
Print(ival);
這將在預(yù)處理期間轉(zhuǎn)換為此語(yǔ)句:
printf_s("%d", ival);
剛才討論的替代方式的一般形式如下:
#define macro_name( list_of_identifiers ) substitution_string
以下代碼顯示了如何使用以下指令定義最多生成兩個(gè)值的宏:
#define max(x, y) x>y ? x : y
然后,您可以將該語(yǔ)句放在程序中:
int result = max(myval, 99);
這將在預(yù)處理期間擴(kuò)展,以生成以下代碼:
int result = myval>99 ? myval : 99;
由于在先前的#define指令中已創(chuàng)建標(biāo)識(shí)符,因此我們可以測(cè)試是否存在標(biāo)識(shí)符。
它采取以下形式:
#if defined identifier // Statements... #endif
如果指定的標(biāo)識(shí)符在此之前由#define指令定義,則#if之后的語(yǔ)句將包含在程序代碼中,直到指令#endif為止。
如果未定義標(biāo)識(shí)符,則#if和#endif之間的語(yǔ)句將被跳過。
您可以測(cè)試缺少標(biāo)識(shí)符。
該指令的一般形式是:
#if !defined identifier // Statements... #endif
這里,如果以前沒有定義標(biāo)識(shí)符,那么#if下面的#endif之后的語(yǔ)句將被包含。
這可以避免重復(fù)的功能或其他代碼和指令。
這個(gè)機(jī)制只是把你想避免重復(fù)的代碼塊的頂部和尾部如下所示:
#if !defined block1 #define block1 /* Statements you do not */ /* want to occur more than once. */ #endif
您可以使用邏輯運(yùn)算符來(lái)測(cè)試是否定義了多個(gè)標(biāo)識(shí)符。例如:
#if defined block1 && defined block2 // Statements... #endif
如果先前已經(jīng)定義了block1和block2,則此值將為true。
您可以使用||和!運(yùn)算符結(jié)合&&。
我們可以取消定義您之前定義的標(biāo)識(shí)符。
這是使用指令實(shí)現(xiàn)的,例如:
#undef block1
如果先前定義了block1,則該指令不再被定義。
您可以使用#if指令的形式來(lái)測(cè)試常量表達(dá)式的值。
如果常量表達(dá)式的值不為零,則下列語(yǔ)句直到下一個(gè)#endif包含在程序代碼中。
如果常量表達(dá)式計(jì)算為零,則會(huì)跳過下一個(gè)#endif的下一個(gè)語(yǔ)句。
#if指令的一般形式是:
#if constant_expression
您可能會(huì)有以下語(yǔ)句序列,例如:
#if CPU == Intel printf("Performance should be good.\n" ); #endif
你有#else指令。
如果#if條件失敗,它會(huì)標(biāo)識(shí)要執(zhí)行的一組指令或要包括的語(yǔ)句,例如:
#if CPU == Intel printf_s("Performance should be good.\n" ); #else printf_s("Performance may not be so good.\n" ); #endif
#elif指令具??有一般形式:
#elif constant_expression
__DATE__宏會(huì)以Mmm dd yyyy格式生成日期的字符串表示形式。
這里Mmm是個(gè)月,如1月,2月等等。
一對(duì)字符dd是一對(duì)數(shù)字1到31的形式,其中單位數(shù)字前面有一個(gè)空格。
最后,例如,yyyy是2012年的四位數(shù)字。
__TIME__提供一個(gè)包含時(shí)間值的字符串,格式為hh:mm:ss。
時(shí)間是編譯器執(zhí)行時(shí),而不是當(dāng)程序運(yùn)行時(shí)。
當(dāng)您的程序上次使用此語(yǔ)句進(jìn)行編譯時(shí),可以使用此宏來(lái)記錄輸出:
printf_s("Program last compiled at %s on %s\n", __TIME__, __DATE__ );
執(zhí)行此語(yǔ)句將產(chǎn)生類似于以下內(nèi)容的輸出:
Program last compiled at 15:27:01 on Nov 24 2015
__FILE__宏將當(dāng)前源文件的名稱表示為字符串文字。
__LINE__宏包含與當(dāng)前行號(hào)相對(duì)應(yīng)的整數(shù)常量。
您可以結(jié)合使用__FILE__宏來(lái)識(shí)別源代碼中哪個(gè)特定事件或錯(cuò)誤已被檢測(cè)到。
例如:
fprintf(stderr, "Failed to open file in %s line %d\n", __FILE__, __LINE__);
更多建議: