天天看點

define在C語言中用法

原來以為什麼是宏?無非就是定義一個替換的量,好比#define PI 3.1415926,這樣的功能,再深一點就是寫一個類似函數的定義,好比#define MAX(a,b) ((a) > (b) ? (a) : (b))這樣的功能,再問一下宏是什麼?無非就是預處理階段所要展開的亂七八糟的東西,其實也就知道這麼點,當看了Linux Kernel Code,其實會發現自己懂得那些其實都是皮毛,不值一提的小東西,才發現自己OUT了,為此部落客将#define的使用方法總結了一下,如下所示:(如有不足請批評指正)

1. 最最最簡單的define定義

    不贅述了,說一下其他的吧,如#define MAX 10,編譯器在處理這個代碼之前會對MAX進行處理,替換為10,或許有些人認為這樣的定義看起來和const常量很相似,但是他們還是有差別的,#define的定義其實就是簡單的文本的替換,并不是作為一個量來使用

2. 用#define來對函數進行“定義”

    很多就會問了,什麼?居然還能用#define來定義函數,坑爹麼?其實咋說呢,就是類似的一個函數定義罷了,和真正的函數定義當然還是有差別的了,下面進行舉例說明:

   還是用上面的MAX的例子:#define MAX(a,b) ((a) > (b) ? (a) : (b)),這個定義就傳回兩個數中較大的那個,不知道你們看到了沒看到,這個”函數“沒有類型檢查,像不像函數模闆?像?不像?

    其實是有點像的,可以作為一個普通的模闆來使用罷了,他肯定沒函數模闆那麼安全,WHY?看下面的例子:

    #define MINUS(a,b) a - b,眨眼一看,這個肯定是減法操作的define,有木有?對,沒錯,就是這個意思,這個定義在一般的使用中沒問題,但是在特定的情況下使用會出現問題,如果我們要這樣去使用     的話,展開之後會是什麼樣子呢?如:2 * MINUS(a,b) / 4,就像我前面所說的那樣,宏其實就是一個簡單的文本替換,是以展開時候就變為 2 * a - b / 4,和我們想要的結果是不是不一樣?是不是錯         了?有木有?那要如何解決這個問題呢,很簡單,給原定義加一個括号就OK了,也就是#define MINUS(a,b) (a - b)

    再說一個經常出現的一個錯誤,看下面的例子:

    #define pin (int *)

    pin a,b;

    本意其實都想讓a和b成為int型指針,但是實際上卻變成了int *a,b;a是int型指針,b是int型變量,咋處理捏?這個時候typedef就出來了,它說我可以滿     足define滿足不了的要求,是以改成

    typedef pin (int *) 就OK了。

    TIP:我們在寫code的時候一定要養成一個良好的習慣和一個良好的代碼編寫風格,建議所有的層次都加上括号

3. define的單行定義,舉例說明之,屬于少見用法

    #define A(x) ##x

    #define B(x) #@x

    #define C(x) #x

    如果我們假設x=1,那麼A(1)就是1,B(1)就是‘1’,C(1)就是”1“

4. define的多行定義

    #define可以進行多行定義,雖然看起來有點蛋疼,但是确實是一個灰常經典而且在裝置驅動代碼中經常要用到的一個方法,格式如下:

    #define MACRO(arg1,arg2) do {  \

    test1; \

    test2; \

    }while(0)

    TIP:在每一行的末尾要加上\,切記!

5. 定義宏和取消宏定義的方法

    定義一個宏使用#define,取消一個宏定義使用#undef

6. 使用宏進行條件編譯

    格式如下:#ifdef ... (#else) ... #endif

    如:

    #ifdef HELLO

    #define WORLD 1

    #else

    #define WORLD 0

    #endif

7. 用define來處理頭檔案被頭檔案或者源檔案包含的情況

    由于頭檔案包含可以嵌套,那麼c檔案有可能包含多次同一個頭檔案,就會出現重複定義的問題的,那麼可以就通過條件編譯開關來避免重複包含,如下:

    #ifndef _HELLO_H_

    #define _HELLO_H_

    ...

    //檔案内容

    ...

    #endif