ifndef_ define_ endif 作用

viewoverlook發表於2024-05-13

#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 中的大數。

轉自(https://www.cnblogs.com/challenger-vip/p/3386819.html)

相關文章