在分析一些c原始碼時,經常會遇到各種巨集定義操作,本文即總結一下c語言巨集定義中常見的預定義巨集、除錯巨集;巨集的條件編譯用法及特殊的巨集關鍵字用法。
#line
#error
# 用法
## 用法
#pragma 用法
#undef 限定巨集的作用域
一般來講巨集的作用域從 #define 開始直到檔案末尾,但如果需要限定巨集的作用域就可以用 #undef 來限定巨集的作用域,就是該巨集只能作用與 #define … #undef 區間內
常見預定義巨集
預定義巨集也稱為編譯器內建巨集,這些巨集並沒有定義在哪個標頭檔案中,而是編譯器在預處理時會自動處理這些預定義巨集,這裡介紹幾個常用的預定義巨集,其中__func__、__file__、__line__三個巨集在除錯時經常用到,來定位bug,為了方便可以自己定義乙個debug巨集: #define debug printf("%s %s %d\n", __file__,func, __line__);
void
test_1()
執行測試結果:
巨集的條件編譯
所謂條件編譯,也就是在預編譯時,預編譯器可以通過 「條件編譯」 幫你保留某些**、以及幫你去掉某些**,第二階段編譯時就只編譯保留的**,條件編譯可以包含任意內容,可以是 #include 標頭檔案、整個函式、或者函式內部的**塊、變數定義、或是整個檔案的內容(一般標頭檔案中比較多)。條件編譯在linux驅動**以及一些跨平台軟體**中非常常用,針對不同的硬體環境選擇性編譯不同的**塊來提高**的相容性。下面列出常見的條件編譯用法的例子:
#ifdef 和 #ifndef
#ifdef 如果定義了該巨集,就編譯對應的 #endif 之間的**塊;#ifndef 如果沒有定義該巨集,就編譯對應的 #endif 之間的**塊
#define a
#define c
void
test_2()
執行測試**:
e:\c_demo>chong.exe#if 用法this is a.
this is b.
void
test_3()
如果 #if 表示式為真,預編譯保留中間**,為假時,則不保留中間**
執行該**如下:
e:\c_demo>chong.exe#if 常常會和 defined、#elif、#else 搭配使用預編譯這行**
#define a
#define b
void
test_4()
執行測試**如下:
e:\c_demo>chong.exe如果 a 和 b 都定義
void
test_5()
執行測試**結果如下:
e:\c_demo>chong.exe#line如果以上兩個都不滿足,保留這段**
可以根據自己的需求,修改__line__和__file__的值,也就是修改行號和檔名,並且修改的值永久生效。如下測試**:
void
test_6()
執行以上測試**結果:
e:\c_demo>chong.exe#error修改檔名和行號之前:e:\c_demo\chong.c: 65
修改檔名和行號之後:test.c: 100
在linux驅動移植中,往往會修改原始碼中的巨集定義比較多,因為條件編譯需要這些巨集來開啟和關閉,所以在預編譯階段如果就能準確的提示缺少某個巨集的話,可以幫助我們快速排查巨集的錯誤。
void
test_7()
當 pi 沒有定義時,編譯器編譯以上**會列印報錯,提示該巨集沒有定義:
executing task: d:\mingw-w64\mingw64\bin\gcc.exe -g e:\c_demo\chong.c -o chong.exe <# 用法e:\c_demo\chong.c: in function 『test_6』:
e:\c_demo\chong.c:66:2: error: #error pi not defined!
#error pi not defined!
^~~~~
the terminal process terminated with exit code: 1
將 # 傳入的引數變成字串,如下**
#define s1(s) #s
#define s2(s) #s" friend"
#define s3(s) "hello "#s
void
test_8()
執行以上**,輸出三個 「hello friend」,通過預編譯後檢視**也能夠看出,該巨集會將引數轉換成字串
## 用法
將兩個識別符號連線在一起,合成乙個識別符號。還是一樣舉個例子說明
#define merge(a, b) a##b
#define print1 printf("print one\n");
#define print2 printf("print two\n");
void
test_9()
#undef merge
執行以上**結果如下:
e:\c_demo>chong.exe#pragma 用法print one
print two
*表示僅c++支援,其它的c/c++都支援關於一些常用的巨集定義操作就先記錄到此了,對於 #pragma 巨集的使用,之後有接觸更多用法再作更新…alloc_text | comment | init_seg* | optimize | auto_inline | component
inline_depth | pack | bss_seg | data_seg | inline_recursion | pointers_to_members*
check_stack | function | intrinsic | setlocale | code_seg | hdrstop
message | vtordisp* | const_seg | include_alias | once | warning
C語言之關鍵字 巨集定義 條件編譯
區域性變數 特點 注意 區域性變數沒有固定的初始化值,開發中千萬不能使用未初始化的區域性變數 儲存位置 區域性變數儲存在棧中,當作用域結束系統會自動釋放棧中的的區域性變數。特點 如果存在和全域性變數同名的區域性變數,那麼區域性變數會覆蓋全域性變數 注意 全域性變數如果沒有進行初始化,系統缺省會將全域...
C語言中巨集定義 define和關鍵字typedef
define巨集定義是字元替換,typedef是定義型別。define int int是將程式中字元為int的字元全部替換為int,在編譯預處理是進行簡單的字元替換,不做正確性檢查,不管含義是否正確,都進行替換。typedef int int是將int定義為int型的字元型別,是採取像定義變數的方法...
c學習筆記 3關鍵字 巨集與函式定義
好久之前的了,學習c語言的筆記。依舊是老套路,從基礎的變數型別,到函式定義一步步學起 include include 函式定義 與關鍵字 define用於巨集定義 程式中不能更改數值 define mynaem 1234 define age 10 資料型別就不仔細說了 1 資料型別關鍵字 12個 ...