C++宏:#ifndef, #define, #endif 作用

轉載:https://www.cnblogs.com/challenger-vip/p/3386819.html

 

#ifndef, #define, #endif 作用

#ifndef

  它是if not define 的簡寫,是宏定義的一種,實際上確切的說,這應該是預處理功能三種(宏定義、文件包含、條件編譯)中的一種----條件編譯。

  在c語言中,對同一個變量或者函數進行多次聲明是不會報錯的。所以如果h文件裏只是進行了聲明工作,即使不使用# ifndef宏定義,多個c文件包含同一個h文件也不會報錯。

  但是在c++語言中,#ifdef的作用域只是在單個文件中。所以如果h文件裏定義了全局變量,即使採用#ifdef宏定義,多個c文件包含同一個h文件還是會出現全局變量重定義的錯誤。

使用#ifndef可以避免下面這種錯誤:如果在h文件中定義了全局變量,一個c文件包含同一個h文件多次,如果不加#ifndef宏定義,會出現變量重複定義的錯誤;如果加了#ifndef,則不會出現這種錯誤。

示例:

   

#ifndef x                 //先測試x是否被宏定義過
#define x
   程序段1blabla~    //如果x沒有被宏定義過,定義x,並編譯程序段 1
#endif   
  程序段2blabla~   //如果x已經定義過了則編譯程序段2的語句,“忽視”程序段 1

  條件指示符#ifndef 的最主要目的是防止頭文件的重複包含和編譯。瞭解:條件編譯當然也可以用條件語句來實現。 但是用條件語句將會對整個源程序進行編譯,生成的目標程序程序很長,而採用條件編譯,則根據條件只編譯其中的程序段1或程序段2,生成的目標程序較短。如果條件選擇的程序段很長,採用條件編譯的方法是十分必要的。

#ifndef 和 #endif 要一起使用,如果丟失#endif,可能會報錯。總結一下:在c語言中,對同一個變量或者函數進行多次聲明是不會報錯的。所以如果h文件裏只是進行了聲明工作,即使不使用# ifndef宏定義,一個c文件多次包含同一個h文件也不會報錯。 使用#ifndef可以避免下面這種錯誤:如果在h文件中定義了全局變量,一個c文件包含同一個h文件多次,如果不加#ifndef宏定義,會出現變量重複定義的錯誤;如果加了#ifndef,則不會出現這種錯.

#ifdef

  與ifndef類似,ifdef顧名思義,就是if define,看例子

#ifdef  x
    程序1blabla~
#endif

  翻譯:如果宏定義了x,則執行程序1.

  此外,還有其他形式,還是看例子好些:

#ifndef  x
#define x
    程序段 1
#else
    程序段 2
#endif

  當x沒有由#define定義過,則編譯“程序段1”,否則編譯“程序段2”。

#if 表達式
    程序段 1
#else
    程序段 2
#endif

  它的作用是 當“表達式”值爲真時。編譯程序段1。否則則編譯程序段2。當沒有程序段2時,直接是#if---#endif

#define

  在C或C++語言源程序中允許用一個標識符來表示一個字符串,稱爲“宏”。“define”爲宏定義命令。

  被定義爲“宏”的標識符稱爲“宏名”。在編譯預處理時,對程序中所有出現的“宏名”,都用宏定義中的字符串去代換,這稱爲“宏代換”或“宏展開”。宏定義是由源程序中的宏定義命令完成的。宏代換是由預處理程序自動完成的。

  優點:

    (1) 方便程序的修改。這個就不多說了。

    (2) 提高程序的運行效率。使用帶參數的宏定義可完成函數調用的功能,又能減少系統開銷,提高運行效率。正如C語言中所講,函數的使用可以使程序更加模塊化,便於組織,而且可重複利用,但在發生函數調用時,需要保留調用函數的現場,以便子函數執行結束後能返回繼續執行,同樣在子函數執行完後要恢復調用函數的現場,這都需要一定的時間,如果子函數執行的操作比較多,這種轉換時間開銷可以忽略,但如果子函數完成的功能比較少,甚至於只完成一點操作,如一個乘法語句的操作,則這部分轉換開銷就相對較大了,但使用帶參數的宏定義就不會出現這個問 題,因爲它是在預處理階段即進行了宏展開,在執行時不需要轉換,即在當地執行。宏定義可完成簡單的操作,但複雜的操作還是要由函數調用來完成,而且宏定義所佔用的目標代碼空間相對較大。所以在使用時要依據具體情況來決定是否使用宏定義。

  在C或C++語言中,“宏”分爲有參數和無參數兩種。

  一、無參宏定義

    1.  無參宏定義的一般形式爲:#define 標識符 字符串

      2.  其中的“#”表示這是一條預處理命令。凡是以“#”開頭的均爲預處理命令。“define”爲宏定義命令。“標識符”爲所定義的宏名。“字符串”可以是常數、表達式、格式串等。

    

複製代碼

 1 #include <stdio.h>
 2 #define    M    ( a+b )
 3 int main( int argc, char * argv[] )
 4 {
 5     int s, a, b;
 6     printf( "input number a& b: " );
 7     scanf( "%d%d", &a, &b );
 8     s = M*M;
 9     printf( "s=%d\n" ,s );
10 }

複製代碼

 

  上例程序中首先進行宏定義,定義M來替代表達式(a+b),在 s= M * M 中作了宏調用。在預處理時經宏展開後該語句變爲: S=(a+b)*(a+b)  但要注意的是,在宏定義表達式(a+b)兩邊的括號不能少。否則會發生錯誤。  如當作以下定義後:#define M (a)+(b)  在宏展開時將得到下述語句:S= (a)+(b)*(a)+(b)

還要說明的是:

  1.宏定義是用宏名來表示一個字符串,在宏展開時又以該字符串取代宏名,這只是一種簡單的代換,字符串中可以含任何字符,可以是常數,也可以是表達式,預處理程序對它不作任何檢查。如有錯誤,只能在編譯已被宏展開後的源程序時發現。

  2.宏定義不是說明或語句,在行末不必加分號,如加上分號則連分號也一起置換。

  3..宏定義必須寫在函數之外,其作用域爲宏定義命令起到源程序結束。如要終止其作用域可使用#undef命令

  二、帶參宏定義

  c語言允許宏帶有參數。在宏定義中的參數稱爲形式參數,在宏調用中的參數稱爲實際參數。對帶參數的宏,在調用中,不僅要宏展開,而且要用實參去代換形參

  帶參宏定義的一般形式爲:  #define 宏名(形參表) 字符串

  例: 

#define  M(y)  ((y)*(y)+3*(y))            /*宏定義*/
k = M(5);             /*宏調用*/

複製代碼

#include <stdio.h>
#define MAX( a, b )  ((a>b)?(a):(b))
int main( int argc, char * argv[] )
{
    int x, y, max;
    printf( "input two numbers: " );
    scanf( "%d%d", &x, &y );
    max = MAX( x, y );
    printf( "max=%d\n", max );
    return 0;
}

複製代碼

  上例程序的第一行進行帶參宏定義,用宏名MAX表示條件表達式 (a>b)?a:b ,形參a,b均出現在條件表達式中。程序中 max=MAX(x,y) 爲宏調用,實參x,y,將代換形參a,b。宏展開後該語句爲: max=(x>y)?x:y;  用於計算x,y中的大數。

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