1. 程式人生 > >C++_3種預處理功能

C++_3種預處理功能

1.檔案包含#include

作用:把指定的原始檔或標頭檔案的全部內容包含到當前檔案中。 形式1:#include<檔名>,直接按系統標準方式檢索檔案目錄。 形式2:#include"檔名",在當前的原始檔的目錄中尋找,找不到再按照系統標準方式檢索其他檔案目錄。

2.巨集定義#define命令

#include<iostream>
using namespace std;
#define name1 北京郵電大學;
#define name2 "北京郵電大學";

int main()
{
//    char n1[] = name1;//預處理後為 char n1[] = 北京郵電大學,非法語句
    char n2[] = name2;//預處理後為 char n1[] = "北京郵電大學",合法語句
    cout << n2 <<endl;
    return 0;
}
(1)帶引數的巨集定義 作用:除了進行字元序列替換外,在進行引數替換。 形式:#define 巨集名(引數列表) 字元序列。 巨集替換過程:用指定的字元序列替換巨集名,然後用實參替換引數列表中的形參。
#include<iostream>
#include <stdio.h>
#define sq(x) ( (x) * (x) )
using namespace std;
int main()
{
	int i = 3, j;
	j = sq(i++);//j = ((i++) * (i++));
//	j = sq(++i);//結果:25 5
	printf("%d  %d", j, i);
    return 0;
}
注意:<1>不能忽視巨集定義中的空格,如:#define f  (x) ((x)-1) 被理解為不帶引數的巨集替換;    <2>“實參”與“形參”應一一對應,無型別而言,僅替換;“實參” 如果是表示式,並不進行運算;    <3>與函式的形參和實參有本質上的區別:不分配記憶體、引數無型別、表示式不求值、巨集展開在預編譯時進行(函式呼叫在執行時進行);    <4>巨集替換不佔執行時間,只佔編譯時間;    <5>在定義巨集時最好把每個引數都括起來,整個結果表示式也括起來,括號多用於在複雜表示式中遇到的優先順序問題:define abs(x)  (((x) >= 0) ? (x) : -(x)),如果定義成define abs(x)  x > 0 ? x : -x ,abs(a-b)得到a - b > 0 ? a - b : - a - b錯誤結果 。
(2)巨集並不是型別定義 巨集的一個常見用途是:使多個不同變數的型別可在一個地方說明,只需要改變一行程式碼,就能改變f1和a的型別。
<pre name="code" class="cpp">#define FTYPE struct f
FTYPE f1;
FTYPE a;
但是最好使用型別定義:typedef struct f FTYPE。比如:
#define  T1  struct   f *
typedef  struct   f   *T2;
以上T1,T2都是指向結構體 f 的指標型別,用它們宣告多個變數時 ,將出錯:
T1   a,b;   //展開 struct  f *a,b,出錯,a定義為指向結構體的指標,b被定義為一個結構體 
T2   a,b;   //正確
(3)在替換中使用引數
C語言還專門提供了一個特殊的符號作為引數標識,被稱為符號引數。符號引數用“#”和“##”表示。“#”是在引用處用引數字串直接替換,”##”是在引用處的符號引數續接。
#include <iostream>
#include <stdio.h>
using namespace std;
#define pr(x) printf(#x"\n")
#define PI 3.14
#define PI2 6.28
#define PIOut(x) printf("%f\n",PI##x)
int main()
{
    pr(abc);
    PIOut(2);
    return 0;
}

3.條件編譯命令

作用:對滿足條件的部分程式內容進行編譯,否則不參與編譯。
功能:便於除錯 。
(1)判斷符號常量,進行條件編譯:
形式1:#ifdef 識別符號
                程式段
                # endif
作用:如果識別符號被定義過(一般用#define命令定義),則編譯程式段,否則不編譯。
形式2:#ifdef 識別符號
                  程式段1
                  #else
                  程式段2
                  # endif
作用:如果識別符號被定義過,則編譯程式段1,否則編譯程式段2。
形式3:#ifndef 識別符號
                 程式段
                 # endif
作用:如果識別符號沒有被定義過,則編譯程式段,否則不編譯。
形式4:#ifndef 識別符號
                    程式段1
                  #else
                 程式段2
                 # endif
作用:如果識別符號沒有被定義過,則編譯程式段1,否則編譯程式段2 。
(2)判斷表示式,進行條件編譯:
形式1:#if(表示式)
                 程式段
                  # endif
作用:如果表示式成立(表示式為“真”)則編譯程式段,否則不編譯。
形式2:#if(表示式)
                 程式段1
                #else
                  程式段2
                # endif
作用:如果表示式成立則編譯程式段1,否則編譯程式段2 。
說明:
①只對在判斷範圍內的程式段進行條件編譯,其它的程式部分均不編譯;
②不編譯=不可能執行;
③省編譯時間,減少目標程式的長度,便於程式移植。
#include <iostream>
#include <stdio.h>
using namespace std;
#define Student 1
int main()
{
    #ifdef Student
    printf("處理學生資訊\n");
        #if(Student)
            printf("處理大學生資訊\n");
        #else
            printf("處理小學生資訊\n");
        #endif
    #else
         printf("處理教師資訊\n");
    #endif // Student
}