C++ 預編譯命令

C++ 預編譯命令

C++預處理指令

#include

#define

#undef

#pragma

#import

#error

#line

#ifdef

#ifndef

#if

#else

#elif

#endif

 

宏以#起始 不以;結束

 

一.        #include 文件包含

預編譯期發現#include後,將會尋找HeaderName並把其包含到當前文件中

EG:#include <HeaderName>

常見形式:

#include <iostream.h>          //

#include <iostream>            //

#include "iostream"            //

#include "TestHeader.h"        //

#include "../TestHeader.h"     //

 

1.      #include <iostream.h>和#include <iostream>區別

#include <iostream.h>是老規範,現已經拋棄

#include <iostream>是新規範,使用名稱空間避免名稱衝突。即將所有的定義放在了一個名稱空間std中

 

2.      #include <iostream>和#include "iostream"區別

#include <iostream>直接在系統的路徑下查找此頭文件。多是系統的頭文件

#include "iostream"首先在當前目錄查找,如果沒有找到再到系統目錄查找

 

3.      頭文件的多次包含問題

編譯器對每個文件只編譯一次生成一份機器代碼.obj,如果在多個地方包含了同一個頭文件,則會出現多次包含的錯誤,即試圖讓編譯器將此文件編譯多次生成多份機器代碼。

預編譯保護解決此問題。

 

二.        #define  #undef 宏替換

#define 宏 宏主體

宏展開:在代碼中出現宏,會用宏實體代替宏

 

#define 定義常量、函數宏

#undef  結束常量、函數宏定義

 

1.    常量宏

常量宏:是最常見的一種形式。即使用一個宏代替實際的常量,如數據、字符、字符串常量等

#define CONST_VAL 2

#define MEG_EG "Test Macro!"

#define CHARACTOR_EG 'M'

 

注:

(1)    可以使用#undef結束常量宏定義,結束宏定義宏此宏不能再次使用。即時這個宏實際不存在,使用#undef結束宏定義也不是錯誤,相反在定義一個宏時如果不確定其是否已經定義可以先使用#undef結束其定義,然後重新定義

(2)    可以多次定義同一個宏

 

2.    函數宏

 函數宏:外形和作用都與函數類似並且有參數輸入

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

 

注:

(1)    定義函數宏是將宏體都用一個“( ) “括起來。

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

cout << "MAX = " << MAX(1,2) << endl;  //正確

 

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

cout << "MAX = " << MAX(1,2) << endl;  //錯誤。將<<和宏混淆

(2)    通常將函數宏第一爲一行,但可以使用“/“定義多行宏函數

           #define MAX(x, y) ( (x>y)?/

                       x:y )

(3)    可以使用#undef結束函數宏定義

    #undef MAX(x, y)和#undef MAX都可以

(4)    宏函數產生內聯代碼,形式上等同與inline函數,當沒有inline函數安全

(5)    宏函數不檢查輸入的參數(相比inline函數不安全)

(6)    宏函數沒有inline函數效率高

  

3.    #運算符

#運算符可以在一個字符串中輸入宏參數,使得一個字符串可以包含某個參數

EG:

#define STR_A(A) ( printf("STR_A(A) A = "#A" ") )

#define STR_B(B) ( "STR_B(B) B = "#B" " )

#define STR_C(CA, CB) ( "STR_C(CA, CB) C = "#CA"  "#CB" " )

        STR_A(1);

        cout << endl;

        cout << STR_B(2) << endl;

        cout << STR_B(B) << endl;

        cout << STR_C(CA, CB) << endl;

       

        string strB = "strB ";

        strB += " + ";

        strB += STR_B(B);

cout << "strB + Macro STR_B = " << strB << endl;

  

4.    ##運算符

  ##運算符用於創建變化的變量,即使用宏參數創建變化的變量

  

EG:

       #define VARIAVLE_NAME(N) ( n##N )

        int VARIAVLE_NAME(IntA) = 1;                // int nIntA

        int VARIAVLE_NAME(1) = 1;                   // int n1

        int VARIAVLE_NAME(2) = 1;                   // int n2

        cout << "nIntA = " << nIntA << endl;

        cout << "n" << 1 <<" = " << VARIAVLE_NAME(1) << endl;

        cout << "n" << 2 <<" = " << VARIAVLE_NAME(2) << endl;

       

        double VARIAVLE_NAME(DoubleA) = 1.1;

        cout << "nDoubleA = " << nDoubleA << endl;

      

三.        #pragma

其格式一般爲: #pragma para

其中para 爲參數,下面來看一些常用的參數。

(1)   #pragma once

多次包含的保護。只要在頭文件的最開始加入這條指令就能夠保證頭文件被編譯一次,這條指令實際上在VC6中就已經有了,但是考慮到兼容性並沒有太多的使用它。

 

等價於:(此爲C/C++標準 通用性更強)

#ifndef HEADER_NAME_HPP

#define HEADER_NAME_HPP

             Your Code

#endif //END HEADER_NAME_HPP

 

(2)   #pragma warning()

#pragma warning( warning-specifier : warning-number-list

 [; warning-specifier : warning-number-list...] )

#pragma warning( push[ ,n ] )

#pragma warning( pop )

      

       EG:

       #pragma warning( disable : 4507 34; once : 4385; error : 164 )

等價於:

#pragma warning(disable:4507 34) // 不顯示和號警告信息

#pragma warning(once:4385)       // 4385號警告信息僅報告一次

#pragma warning(error:164)       // 把號警告信息作爲一個錯誤。

 

同時這個pragma warning 也支持如下格式:

#pragma warning( push [ ,n ] )

#pragma warning( pop )

這裏n代表一個警告等級(1---4)。

#pragma warning( push )保存所有警告信息的現有的警告狀態。

#pragma warning( push, n)保存所有警告信息的現有的警告狀態,並且把全局警告

等級設定爲n。

#pragma warning( pop )向棧中彈出最後一個警告信息,在入棧和出棧之間所作的

一切改動取消。例如:

#pragma warning( push )

#pragma warning( disable : 4705 )

#pragma warning( disable : 4706 )

#pragma warning( disable : 4707 )

//.......

#pragma warning( pop )

在這段代碼的最後,重新保存所有的警告信息(包括,和)。

(3)   #pragma warning()

#pragma warning( warning-specifier : warning-number-list

 [; warning-specifier : warning-number-list...] )

#pragma warning( push[ ,n ] )

#pragma warning( pop )

      

       EG:

       #pragma warning( disable : 4507 34; once : 4385; error : 164 )

等價於:

#pragma warning(disable:4507 34) // 不顯示和號警告信息

#pragma warning(once:4385)       // 4385號警告信息僅報告一次

#pragma warning(error:164)       // 把號警告信息作爲一個錯誤。

 

同時這個pragma warning 也支持如下格式:

#pragma warning( push [ ,n ] )

#pragma warning( pop )

這裏n代表一個警告等級(1---4)。

#pragma warning( push )保存所有警告信息的現有的警告狀態。

#pragma warning( push, n)保存所有警告信息的現有的警告狀態,並且把全局警告

等級設定爲n。

#pragma warning( pop )向棧中彈出最後一個警告信息,在入棧和出棧之間所作的

一切改動取消。例如:

#pragma warning( push )

#pragma warning( disable : 4705 )

#pragma warning( disable : 4706 )

#pragma warning( disable : 4707 )

//.......

#pragma warning( pop )

在這段代碼的最後,重新保存所有的警告信息(包括,和)。

四.        #import

常用於導入.dll

 

五.        #error

    該指令用於程序的調試, 當編譯中遇到#error指令就停止編譯。

     #if !defined(__cplusplus)

#error C++ compiler required.

#endif

如果沒有在__cplusplus環境下,就會輸出This software requires the cplusplus OS.然後誘發編譯器終止。所以總的來說,這條指令的目的就是在程序崩潰之前能夠給出一定的信息。 

六.        #line

用於重置__FILE__和__LINE__

初看起來似乎沒有什麼用,不過,他還是有點用的,那就是用在編譯器的編寫中,我們知道編譯器對C++源碼編譯過程中會產生一些中間文件,通過這條指令,可以保證文件名是固定的,不會被這些中間文件代替,有利於進行分析

    

   

   

    重置後

     

   

七.        #ifdef  #ifndef  #if  #else  #elif  #endif 條件編譯

預處理器不能識別標記代碼塊的花括號{},對於條件編譯的沒有條件判斷塊必須使用 #endif來指定終止

1、 
    #ifdef  identifier 
              your code 
      #endif 
      如果identifier爲一個定義了的符號,your code就會被編譯,否則剔除 
    2、 
      #ifndef identifier 
              your code 
      #endif 
      如果identifier爲一個未定義的符號,your code就會被編譯,否則剔除 
    3、 
      #if  expression 
           your code 
      #endif 
      如果expression非零,your code就會被編譯,否則剔除 
    4、 
      #ifdef identifier 
             your code1 
      #else 
             your code2 
      #endif 
      如果identifier爲一個定義了的符號,your code1就會被編譯,否則your code2     

就會被編譯 
    5、 
      #if   expressin1 
            your code1 
      #elif expression2 
            your code2 
      #else 
            your code3 
      #enif   

 

八.        預定義宏

    __DATE__       進行預處理的日期

    __FILE__       當前軟代碼文件名的字符串文字

    __LINE__       當前源代碼中的行號的整數常量

    __TIME__       源文件的編譯時間

    __TIMESTAMP__  源文件的編譯完整時間

  

cout << "__DATE__ = " << __DATE__ << endl;

    cout << "__FILE__ = " << __FILE__ << endl;

    cout << "__LINE__ = " << __LINE__ << endl;

    cout << "__TIME__ = " << __TIME__ << endl;

cout << "__TIMESTAMP__ = " << __TIMESTAMP__ << endl;

    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章