C++的基礎知識(六)--條件編譯及編譯預處理階段

一、編譯預處理

   預處理過程先於編譯器對源代碼進行處理:讀入源代碼,檢查包含預處理指令的語句和宏定義,並對源代碼進行相應的轉換,還會刪除程序中的註釋和多餘的空白字符。
   預編譯程序所完成的基本上是對源程序的“替代”工作。經過此種替代,生成一個沒有宏定義、沒有條件編譯指令、沒有特殊符號的輸出文件。這個文件的含義同沒有經過預處理的源文件是相同的,但內容有所不同。下一步,此輸出文件將作爲編譯程序的輸出而被翻譯成爲機器指令。

二、僞指令(或預處理指令)定義

  C預處理器:以 # 開頭,不允許以分號結尾,C++中除了不允許對同一個結構做出多次聲明外,通常可以對同一個東西聲明很多次,但只能對它定義一次。 
   可以使用 #undef 指令反定義(刪除)一個現有的常量定義:#undef ConstDef
包括以下四個方面:

1. 宏定義指令
宏定義了一個代表特定內容的標識符。預處理過程會把源代碼中出現的宏標識符替換成宏定義時的值。宏最常見的用法是定義代表某個值的全局符號。宏的第二種用 法是定義帶參數的宏(宏函數),這樣的宏可以象函數一樣被調用,但它是在調用語句處展開宏,並用調用時的實際參數來代替定義中的形式參數。
1.1 #define指令

       該指令最簡單的格式是:聲明一個標識符,給出這個標識符代表的代碼(比如像圓周率這樣的數)。在後面的源代碼中,我們就可以使用定義的宏取代要使用的代碼,習慣上總是全部用大寫字母來定義宏,這樣易於把程序的宏標識符和一般變量標識符區別開來。如果想要改變數組的大小,只需要更改宏定義並重新編譯程序即可。
       舉例如下:
       //例1 #define MAX_NUM 10
       int array[MAX_NUM]; 
       for(i=0;i<MAX_NUM;i++)

注意:
(1) 宏表示的值可以是一個常量表達式,允許宏嵌套(必須在前面已定義)。
(2)一般要求宏定義要有其實際意義.
(3)宏還可以代表一個字符串常量,
(4)帶參數的#define指令(宏函數) //例4 #define Cube(x) (x)(x)(x)
1.2 #運算符
出現在宏定義中的#運算符把跟在其後的參數轉換成一個字符串。有時把這種用法的#稱爲字符串化運算符。
宏定義中的#運算符告訴預處理程序,把源代碼中任何傳遞給該宏的參數轉換成一個字符串。
##運算符用於把參數連接到一起。預處理程序把出現在##兩側的參數合併成一個符號。

  1. 條件編譯指令。
    通過定義不同的宏來決定編譯程序對哪些代碼進行處理。條件編譯指令將決定哪些代碼被編譯,而哪些是不被編譯的。可以根據表達式的值或者某個特定的宏是否被定義來確定編譯條件。

2.1 #if/#endif/#else/#elif指令

#if指令檢測跟在製造另關鍵字後的常量表達式。如果表達式爲真,則編譯後面的代碼,知道出現#else、#elif或#endif爲止;否則就不編譯。
#endif用於終止#if預處理指令。 #else指令用於某個#if指令之後,當前面的#if指令的條件不爲真時,就編譯#else後面的代碼。

//例2
#define DEBUG       //此時#ifdef DEBUG爲真
//#define DEBUG 0  //此時爲假
int main()
{
   #ifdef DEBUG
      printf("Debugging\n");
   #else
      printf("Not debugging\n");
   #endif
   printf("Running\n");
   return 0;
}

這樣我們就可以實現debug功能,每次要輸出調試信息前,只需要#ifdef DEBUG判斷一次。不需要了就在文件開始定義#define DEBUG

elif預處理指令綜合了#else和#if指令的作用。

//例3
#define TWO
int main()
{
   #ifdef ONE
          printf("1\n");
   #elif defined TWO
          printf("2\n");
   #else
          printf("3\n");
   #endif
}
//輸出結果是2。

2.2 #ifdef和#ifndef
這二者主要用於防止重複包含。我們一般在.h頭文件前面加上這麼一段:

//頭文件防止重複包含
//funcA.h
#ifndef FUNCA_H
#define FUNCA_H
//頭文件內容
#end if

這樣,如果a.h包含了funcA.h,b.h包含了a.h、funcA.h,重複包含,會出現一些type redefination之類的錯誤。 #if defined等價於#ifdef; #if !defined等價於#ifndef.
3、頭文件包含指令。
在程序中包含頭文件有兩種格式:

      #include <my.h> 用尖括號把頭文件括起來。這種格式告訴預處理程序在編譯器自帶的或外部庫的頭文件中搜索被包含的頭文件。
      #include "my.h" 用雙引號把頭文件括起 來。這種格式告訴預處理程序在當前被編譯的應用程序的源代碼文件中搜索被包含的頭文件,如果找不到,再搜索編譯器自帶的頭文件。

4、特殊符號。
4.1 LINE

注意,是雙下劃線,而不是單下劃線 。

注意,是雙下劃線,而不是單下劃線 。
__FILE__ 包含當前程序文件名的字符串
__LINE__  表示當前行號的整數
__DATE__ 包含當前日期的字符串
__STDC__  如果編譯器遵循ANSI C標準,它就是個非零值
__TIME__ 包含當前時間的字符串
//例4
#include<stdio.h>
int main()
{
   printf("Hello World!\n");
   printf("%s\n",__FILE__);
   printf("%d\n",__LINE__);
   return 0;
}

4.2 #line等
#error指令將使編譯器顯示一條錯誤信息,然後停止編譯。
#line指令改變 LINEFILE 的內容,它們是在編譯程序中預先定義的標識符。
#pragma指令沒有正式的定義。編譯器可以自定義其用途。典型的用法是禁止或允許某些煩人的警告信息。

//例5,#line舉例
#line   100          //初始化行計數器 
#include<stdio.h>    //行號100
int main()
{
    printf("Hello World!\n");
    printf("%d",__LINE__);
    return 0;
}
//輸出104
發佈了36 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章