#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++ 語言中,“宏” 分為有引數和無引數兩種。
一、無參宏定義
-
無參宏定義的一般形式為:#define 識別符號 字串
-
其中的 “#” 表示這是一條預處理命令。凡是以 “#” 開頭的均為預處理命令。“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)
還要說明的是:
-
宏定義是用宏名來表示一個字串,在宏展開時又以該字串取代宏名,這只是一種簡單的代換,字串中可以含任何字元,可以是常數,也可以是表示式,預處理程式對它不作任何檢查。如有錯誤,只能在編譯已被宏展開後的源程式時發現。
-
宏定義不是說明或語句,在行末不必加分號,如加上分號則連分號也一起置換。
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)