C 預處理

2018-05-20 16:35 更新

學習C - C預處理

源代碼的預處理發(fā)生在編譯為機器指令之前。

預處理階段可以執(zhí)行由#符號啟動的預處理指令指定的操作范圍。

預處理階段在編譯之前處理C源代碼。

在預處理階段后,將分析和執(zhí)行所有指令,并且所有預處理指令將不再出現(xiàn)在源代碼中。

#include #define 是兩個流行的指令。

用#define語句定義常量。


#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é)果。



包括頭文件

你完全熟悉這樣的語句:

#include <stdio.h>

上面的代碼將標準庫頭文件的內(nèi)容帶入您的程序。

#include指令引入到程序中的文件也可能包含#include指令。

定義頭文件

您可以定義自己的頭文件,通常使用擴展名為.h。

頭文件不應包括實現(xiàn)。

您創(chuàng)建頭文件以包含聲明。

所有的函數(shù)定義和全局變量都放在擴展名為.c的源文件中。

您可以將函數(shù)原型,結(jié)構(gòu)類型定義,符號定義,extern語句和typedefs放在頭文件中。
一個典型的例子可能是:

#include "myfile.h"

外部變量

要使用另一個文件的全局變量,請使用extern關(guān)鍵字將該變量聲明為當前源文件的外部變量。

例如,假設(shè)您的語句在另一個文件中定義了全局變量:

int number = 0; 
double in_to_mm = 2.54; 

在要訪問這些文件的源文件中,指定這些變量名稱是外部的:

extern int number; 
extern double in_to_mm; 

這些語句不會創(chuàng)建這些變量。

他們通知編譯器這些名稱被定義在哪里。


靜態(tài)函數(shù)

您可以通過將其聲明為靜態(tài)來確保函數(shù)僅在您定義它的源文件中可見。

例如:

static double average(double x, double y) { return (x + y) / 2.0; }

程序源代碼中的替換

define預處理器指令的一般形式如下:

#define identifier sequence_of_characters 

這里,標識符符合C中標識符的通常定義。

在#define語句中定義字符串。


#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é)果。

宏是預處理器,允許可以稱為多個參數(shù)化替換。

這涉及到用于令牌標識符的字符序列的替換。

一個例子將使這更容易理解:

#define Print(My_var) printf_s("%d", My_var) 

My_var 是一個參數(shù)名稱,可以指定一個字符串。

該指令提供兩個替代級別。

代碼中的Print(My_var)的出現(xiàn)將被緊隨其后的字符串以及您為My_var指定的任何參數(shù)所代替。

例如,你可以寫下列內(nèi)容:

Print(ival);

這將在預處理期間轉(zhuǎn)換為此語句:

printf_s("%d", ival);

宏函數(shù)

剛才討論的替代方式的一般形式如下:

#define macro_name( list_of_identifiers ) substitution_string

以下代碼顯示了如何使用以下指令定義最多生成兩個值的宏:

#define max(x, y) x>y ? x : y

然后,您可以將該語句放在程序中:

int result = max(myval, 99);

這將在預處理期間擴展,以生成以下代碼:

int result = myval>99 ? myval : 99; 

條件編譯

由于在先前的#define指令中已創(chuàng)建標識符,因此我們可以測試是否存在標識符。

它采取以下形式:

#if defined identifier 
// Statements... 
#endif 

如果指定的標識符在此之前由#define指令定義,則#if之后的語句將包含在程序代碼中,直到指令#endif為止。

如果未定義標識符,則#if和#endif之間的語句將被跳過。

您可以測試缺少標識符。

該指令的一般形式是:

#if !defined identifier 
// Statements... 
#endif 

這里,如果以前沒有定義標識符,那么#if下面的#endif之后的語句將被包含。

這可以避免重復的功能或其他代碼和指令。

這個機制只是把你想避免重復的代碼塊的頂部和尾部如下所示:

#if !defined block1 
  #define block1 
  /* Statements you do not          */ 
  /* want to occur more than once.  */ 
#endif 

測試多個條件

您可以使用邏輯運算符來測試是否定義了多個標識符。例如:

#if defined block1 && defined block2 
   // Statements... 
#endif 

如果先前已經(jīng)定義了block1和block2,則此值將為true。

您可以使用||和!運算符結(jié)合&&。

未定義標識符

我們可以取消定義您之前定義的標識符。

這是使用指令實現(xiàn)的,例如:

#undef block1

如果先前定義了block1,則該指令不再被定義。

測試標識符的特定值

您可以使用#if指令的形式來測試常量表達式的值。

如果常量表達式的值不為零,則下列語句直到下一個#endif包含在程序代碼中。

如果常量表達式計算為零,則會跳過下一個#endif的下一個語句。

#if指令的一般形式是:

#if constant_expression

您可能會有以下語句序列,例如:

#if CPU == Intel
  printf("Performance should be good.\n" ); 
#endif 

多重選擇

你有#else指令。

如果#if條件失敗,它會標識要執(zhí)行的一組指令或要包括的語句,例如:

#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__宏會以Mmm dd yyyy格式生成日期的字符串表示形式。

這里Mmm是個月,如1月,2月等等。

一對字符dd是一對數(shù)字1到31的形式,其中單位數(shù)字前面有一個空格。

最后,例如,yyyy是2012年的四位數(shù)字。

__TIME__提供一個包含時間值的字符串,格式為hh:mm:ss。

時間是編譯器執(zhí)行時,而不是當程序運行時。

當您的程序上次使用此語句進行編譯時,可以使用此宏來記錄輸出:

printf_s("Program last compiled at %s on %s\n", __TIME__, __DATE__ );

執(zhí)行此語句將產(chǎn)生類似于以下內(nèi)容的輸出:

Program last compiled at 15:27:01 on Nov 24 2015 

__FILE__宏將當前源文件的名稱表示為字符串文字。

__LINE__宏包含與當前行號相對應的整數(shù)常量。

您可以結(jié)合使用__FILE__宏來識別源代碼中哪個特定事件或錯誤已被檢測到。

例如:

fprintf(stderr, "Failed to open file in %s line %d\n", __FILE__, __LINE__);
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號