2017年10月27日 星期五

[C]實用巨集範例

除錯:
將描述式給一起印出

case1:
#define DPRINTF(expr) printf("%s=%d\n",#expr, expr)
or
#define DPRINTF(expr) printf(#expr"=%d",expr)

case2:
#define WARN_IF(EXP) \
     do { if (
EXP) \
             fprintf (stderr, "Warning: "
#EXP "\n"); } \
     while (0)

Note:
  1. "#":字串話運算子可將當前內容轉完字串
  1. #expr本質就為一個字串的巨集


case1:
DPRINTF(x); //if x = 0xaa
=>x=0xaa;

case2:
int main() {
    int x = 0;
    WARN_IF(x == 0);
}
=>Warning: x == 0

除錯巨集
#define DBG_PRINTF(fmt, args...)\
printf("[%s,%d]" fmt, __FUNCTION__, __LINE__,##args)
int main()
{
DBG_PRINTF("Hello\n");
}

Note:
  1. \結尾,表示巨集的換行
  2. fmt:為上例的"Hello\n"
  3. 不定變數沒用到參考(巨集與不定變數)
=>[main,7]Hello
除錯巨集的分級審查

#if DBG_LEVEL==0
#define PRINTF(fmt,...)
#else
#define PRINTF(fmt,...) printf(fmt,##__VA_ARGS__)
#endif


包裝:
利用參數來選擇呼叫的函式
#define test(x) test##x
test1(){
printf("%s\n",__FUNCTION__);
}
test2(){
printf("%s\n",__FUNCTION__);
}

main(){
test(1)();
}

Note:
  1. ##: 為連結運算子,CPP會將字元串作連結

=>test2
程式碼封裝(do while巨集定義)

#define HELLO(str) do{\
printf("Hello:%s\n",str);\
}while(0)

Note:
  1. do while封裝的意義在於,可以使巨集像函式一般使用而不會遇到一些狀況的編輯錯誤,如下:
#define HELLO(str) printf("Hello:%s\n",str);

main(){
if(condition)
printf();;//多一個分號會視為if結構結束,
     //else被視為新的程式(沒有if)
else
printf()
}
test.c:9:2: error: ‘else’ without a previous ‘if’


將表格(cmd table)簡單化:

#define COMMAND(name) {#name, name ## _command}
struct command {
    char *name;
    void (*f)(void);
} cmds[] = {
   
COMMAND(quit),
   
COMMAND(help),
};
Note: #name: 為字串 "xxx"

展開=>
 struct command {
     char *name;
     void (*f)(void);
 } cmds[] = {
     {"quit", quit_command},
     {"help", help_command},

 };

功能:

buffer中得到字串的大小

#define _STRING_LEN_GET(expr) sizeof #expr//stringize the expanded value("test.c")
#define STRING_LEN_GET(expr) STRING_LEN_GET(expr) //展開為 main.c

int main()
{
char buf[128] = __FILE__;
printf("%d\n",sizeof(buf));

printf("%d\n",STRING_LEN_GET(buf));
}

=>
128
4
round up/down

#define ROUND_DOWN_TO_DIVISIBLE(num,div) \
( (UINT32)(num) & -(UINT32)(div) )
#define ROUND_UP_TO_DIVISIBLE(num,div) \
ROUND_DOWN_TO_DIVISIBLE( (UINT32)(num) + (div) - 1, div )


沒有留言:

張貼留言