C與言筆記-宏定義 define 的注意事項與陷阱

這幾篇會對宏定義#define做個筆記:

-------------------------------------------------------------------------------------------

宏定義主要執行文本交換,以下有些陷阱要避開:


陷阱1:
#define double(x) 2*x


執行
int main(void)
{
    printf("double(4):%d\n",double(4));
}
結果為8
--------------------
執行
int main(void)
{
    printf("double(1+1):%d\n",double(1+1));
}


結果不會是預期的8而是10
因為替換後變成
printf("double(1+1):%d\n",1+1*8);

為了預防這種錯誤,最好事都加上括號()
#define double(x)  (2*x)


最常見的宏定義就是:
#define max(a,b)   ((a)>(b)?(a):(b))


---------------------------------------------------------
陷阱2:宏定義的兩端要加上大括號{}


#define increament(a,b)    \
        (a)++;                          \
        (b)++;

沒有加大括號,如果把他放在if後面會有此風險:

int x=1,y=0;
if(x>y)
    increament(x,y);
展開的話變成:

int x=1,y=0;
if(x>y)
    (x)++;
(y++);

這是一種常見的宏定義陷阱
---------------------------------------------------------

陷阱3:就算加上大括號還是有陷阱在裡面要注意!!

#define increase(a,b)  {\
        (a)++;                    \
        (b)++;                    \
}
if(a>b) increase(a,b);

else return 0;

展開變成:

 if(a>b){
    (a)++;
    (b)++;
};
else rerutn 0;

可能導致變易錯誤,因為else前面有一個分號

解決辦法只有一個,就是加上只做一次的do -while迴圈:

#define increase(a,b)  do{  \
    (a)++;                              \
    (b)++;                              \
}while(0)



陷阱4: 有break的情況下仍然有陷阱
#define Assert_(ecpression,action) do{  \
    if(!(expression)) action;
}while(0)

double total=0;
double array[100];

for(int i=0;i<100;i++)
{
    Assert_(!isnan(array[i])),break;);
    total+=array_[i];
}
break被嵌入do-while裡面,這種情況就不能用do-while來包裝了!!




本章節是整理"C成續設計新思維(第2版)"中的部分章節,做個筆記
有興趣可以去構此書來翻閱















這個網誌中的熱門文章

FreeRTOS學習筆記 (二)-任務創建和刪除(xTaskCreate及vTaskDelete)

FreeRTOS學習筆記 (三)-時間管理vTaskDelay()及vTaskDelayUntil()

C語言筆記-文本處理(1) 善用 asprintf取代sprintf