小白來學C語言之宏定義(#define)

畢竟是小白,從小白視角看可能不會太深,但應該都能看懂。
這篇博客就是也是寫給新手的,希望大家都能學懂學好,嘿嘿,寫的不好還望大佬勿噴。

可以使用#define 僞指令來定義一個宏。 宏分爲不帶參數的宏和帶參數的宏。
宏定義以#define 關鍵字後面出現的第一個連續字符序列作爲宏名,剩下的部分作爲宏體。
宏定義具有文件作用域,不論宏定義出現在文件中的哪個地方,例如函數體內、類型定義內部、名字空間內部等,在它後面的任何地方都可以引用宏

宏的幾個特點和注意事項如下。

  1. 宏定義不是C++/C語句,因此不需要使用語句結束符 “;”, 否則它也被看做宏體的一部分。例如:
    例一:正確寫法:
#include <stdio.h>
#define PRICE 30
void main(){
   int num , total;
   num = 10;
   total = PRICE*num;
   printf("%d\n",total);
 }

例二:錯誤寫法

#include <stdio.h>
#define PRICE 30;   //注意這邊的分號
void main(){
   int num , total;
   num = 10;
   total = PRICE*num; /
   printf("%d\n",total);
 }

例三:正確:這後面的分號就被看作宏體的一部分了

#include <stdio.h>
#define PRICE 30;   //注意這邊的分號
void main(){
   int num , total;
   num = 10;
   total = num*PRICE; //注意這邊的分號  這句也可以這樣寫,結果一樣 total = num*PRICE; ;
   printf("%d\n",total);
 }

使用方法爲:

OUTPUT(I like swimming very much.);

替換結果就是:

cout << “I like swimming very much.”《endl;

  1. 任何宏在編譯預處理階段都只是進行簡單的文本特換。不做類型檢查和話法檢在,這個工作留給編譯器進行。參數替換髮生在宏擴展之前。
  2. )宏定義可以嵌套。例如:
#define PI3.14
#definePI 2 (2* PI)
  1. 宏不可以調試,因爲宏不會進入符號表(符號表是編澤器創建的。在編譯時宏已經消失了),即使宏替換後出現了語法錯誤,編譯器也會將錯誤定位到源程序中而不是定位到具體的某個宏定義中。
  2. 程序裏使用雙引號括起來的字符串中即使出現了與宏同名的子串,預處理遵過程也不進行替換。
  3. 定義帶參數的宏時,宏名和左括號之間不能出現空格,否則使用時會出現問題,但是編譯器不會檢查出這種錯誤。例如,宏TEXT如果定義爲下面這樣是報錯的
#include <stdio.h>
#define PRICE 30;
#define TEXT (str)   //注意這邊的分號
void main(){
   printf(TEXT(Hello));
 }
  1. 帶參數的宏體和各個形參應該分別用括號括起來,以免造成意想不到的錯誤。例如:
#define SQUARE(x) ((x)* (x))

a= SQUARE(3+ 5):
*************************
a=8*8=64

如果寫成

#define SQUARE(x)  x*x
a= SQUARE(3+ 5):
**************************
a=3+5*3+5=23
  1. 不要在引用宏定義的參數列表中使用增量和減量運算行,否則可能導致變量多次求值,且結果可能與預期不符,因爲複合表達式中子表達式的求值順序。因具體編譯器的不同而不同。
#define SQUARE(x) ((x)* (x))
int n=5;

int x= SQUARE(n++);

其結果可能是30,也可能是25
  1. 帶參數的宏定義不是函數,因此沒有函數調用的開銷,但是其每次擴展都會生成重複的代碼,結果使可執行代碼的體積增大。
  2. 當我們不再使用某個宏時,可以使用#undef來取消其定義。否則簡單地刪除宏定義會帶帶來許多編譯錯誤,例如:
 #undef TEXT

建議

  1. 雖然宏定義很靈活,並且通過彼此結合可以產生許多變形用法是C++/C程序員不要定義很複雜的宏,宏定義應該簡單而清晰
  2. 宏名採用大寫字符組成的單詞或其縮寫序列,並在各單詞之間使用 _ 下劃線分隔
  3. 如果需要公佈某個宏,那麼該宏定義應當放置在頭文件中,否則放置在實現文件(.cpp) 的頂部:
  4. 不要使用宏來定義新類型名,應該使用typedef, 否則容易造成錯誤;
  5. 給宏添加註釋時請使用塊註釋(/* */), 而不要使用行註釋。因爲有些編譯器可能會把宏後面的行註釋理解爲宏體的一部分;
  6. 儘量使用const取代宏來定義符號常量
  7. 對於較長的使用頻率較高的重複代碼片段,建議使用函數或模板而不要使用帶參數的宏定義:而對於較短的重複代碼片段,可以使用帶參數的宏定義,這不僅是出於類型安全的考慮,而且也是優化與折衷的體現;
  8. 儘量避免在局部範圍內(如函數內、類型定義內等)定義宏,除非它只在該局部範圍內使用,否則會損害程序的清晰性。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章