一、起因
事情的起因是這樣的,在看別人代碼時,發現了一種很有意思的寫法,因為本人主要是以應用層開發為主,所以對這種寫法還是比較少見的,所以研究了一下,就牽扯出了一些知識點,這里先賣個關子,繼續往下看。
二、經過
發現了一串這樣的代碼
static void do_mac(mcmd_t *mcmd, char *params)
{}
MIIO_CMD(mac, do_mac, NULL);
這個是明顯是串口數據的處理回調。進入MIIO_CMD看一下
#define MIIO_CMD_ADDON_NAME cmd
#define MIIO_CMD(_name, _cmd, _tip) \miio_addon_entry_complete(MIIO_CMD_ADDON_NAME, _name, _cmd, _tip, 0)
這里面就是一個宏定義,再進入 miio_addon_entry_complete 看一下
#define miio_addon_entry_complete(_addon, _name, _value, _tip, _acm) \miio_addon_entry_declare(_addon, _name) = miio_addon_value_complete(_addon, _name, _value, _tip, _acm)
這里面調用了 miio_addon_value_complete 賦值給了 miio_addon_entry_declare
先看 miio_addon_value_complete
#define __miio_addon_acm_assignment(_acm) , .acm = (_acm) & 0B11#define _miio_addon_value_complete(_addon, _name, _value, _tip, _acm){.name = #_name, .full_name = #_addon"."#_name, .value = _value, .tip = _tip __miio_addon_acm_assignment(_acm)}
#define miio_addon_value_complete(_addon, _name, _value, _tip, _acm) _miio_addon_value_complete(_addon, _name, _value, _tip, _acm)
這里面就是賦值,把入口參數賦值給結構體的各個元素。
這里介紹一個#參數,防止有些朋友不太懂。
#是一個字符串化操作符。就是把參數轉化為字符串。例如下面這段代碼
#define TO_STR(s) #sint a = 123;
printf("%s",TO_STR(a));
代碼的含義就是把Int類型的變量a轉化為字符串類型,并且輸出。
好,言歸正傳。再看 miio_addon_entry_declare 參數
#define _miio_addon_entry_declare(_addon, _name) \miio_addon_symbol_t _miio_addon_list_2_##_addon##_2_##_name \__attribute__((aligned(4))) \__attribute__((unused, section(".miio_addon_list_2_"#_addon"_2_"#_name)))
#define miio_addon_entry_declare(_addon, _name) _miio_addon_entry_declare(_addon, _name)
這里面有個 miio_addon_symbol_t 結構體,看一下
typedef struct miio_addon_symbol_s {const char* name;const char* full_name;void* value;const char* tip;const uint8_t acm;
}miio_addon_symbol_t;
這里面的元素就是 miio_addon_value_complete 宏定義的賦值。
#define _miio_ad