宏定義中#和##的使用

1. #node

#的功能是將其後面的宏參數進行字符串化操做(Stringfication),簡單說就是在對它所引用的宏變量經過替換後在其左右各加上一個雙引號app

1   #define WARN_IF(EXP) /
2   do{ if (EXP) /
3   fprintf(stderr, "Warning: " #EXP "/n"); } /
4   while(0)

 

那麼實際使用中會出現下面所示的替換過程:ide

1 WARN_IF (divider == 0);

 被替換爲post

1 do {
2   if (divider == 0)
3   fprintf(stderr, "Warning" "divider == 0" "/n");
4 } while(0);

這樣每次divider(除數)爲0的時候便會在標準錯誤流上輸出一個提示信息。spa

 

2. ##code

##被稱爲鏈接符(concatenator),用來將兩個Token鏈接爲一個Token,##符是把傳遞過來的參數當成字符串進行替代。對象

例如blog

1 #define PRINT( n ) printf( "token" #n " = %d", token##n )

token

PRINT(mine );ci

在編譯時會被編譯成

1 printf( "token" "mine" " = %d", tokenmine );

 

 

舉例說明

例一:

 1 #include<cstdio> 
 2 #include<climits>
 3 using namespace std; 
 4 #define STR(s) #s 
 5 #define CONS(a,b) int(a##e##b)
 6 int main() 7 { 8 printf(STR(vck)); // 輸出字符串"vck" 9 printf("%d\n", CONS(2,3)); // 2e3 輸出:2000 10 return 0; 11 }

例二:Canopen協議中對象字典和相關變量的關聯

 1 /* A macro to initialize the data in client app.*/
 2 /* CO_Data structure */
 3 #define CANOPEN_NODE_DATA_INITIALIZER(NODE_PREFIX) {\
 4     /* Object dictionary*/\
 5     & NODE_PREFIX ## _bDeviceNodeId,     /* bDeviceNodeId */\
 6     NODE_PREFIX ## _objdict,             /* objdict  */\
 7     NODE_PREFIX ## _PDO_status,          /* PDO_status */\
 8     NULL,                                /* RxPDO_EventTimers */\
 9     _RxPDO_EventTimers_Handler,          /* RxPDO_EventTimers_Handler */\
10     & NODE_PREFIX ## _firstIndex,        /* firstIndex */\
11     & NODE_PREFIX ## _lastIndex,         /* lastIndex */\
12     & NODE_PREFIX ## _ObjdictSize,       /* ObjdictSize */\
13     & NODE_PREFIX ## _iam_a_slave,       /* iam_a_slave */\
14     NODE_PREFIX ## _valueRangeTest,      /* valueRangeTest */\
15     \
16     /* SDO, structure s_transfer */\
17     {\
18           REPEAT_SDO_MAX_SIMULTANEOUS_TRANSFERS_TIMES(s_transfer_Initializer)\
19     },\
20     \
21     /* State machine*/\
22     Unknown_state,      /* nodeState */\
23     /* structure s_state_communication */\
24     {\
25         0,          /* csBoot_Up */\
26         0,          /* csSDO */\
27         0,          /* csEmergency */\
28         0,          /* csSYNC */\
29         0,          /* csHeartbeat */\
30         0,           /* csPDO */\
31         0           /* csLSS */\
32     },\
33     _initialisation,     /* initialisation */\
34     _preOperational,     /* preOperational */\
35     _operational,        /* operational */\
36     _stopped,            /* stopped */\
37     NULL,                /* NMT node reset callback */\
38     NULL,                /* NMT communications reset callback */\
39     \
40     /* NMT-heartbeat */\
41     & NODE_PREFIX ## _highestSubIndex_obj1016, /* ConsumerHeartbeatCount */\
42     NODE_PREFIX ## _obj1016,                   /* ConsumerHeartbeatEntries */\
43     NODE_PREFIX ## _heartBeatTimers,           /* ConsumerHeartBeatTimers  */\
44     & NODE_PREFIX ## _obj1017,                 /* ProducerHeartBeatTime */\
45     TIMER_NONE,                                /* ProducerHeartBeatTimer */\
46     _heartbeatError,           /* heartbeatError */\
47     \
48     {REPEAT_NMT_MAX_NODE_ID_TIMES(NMTable_Initializer)},\
49                                                    /* is  well initialized at "Unknown_state". Is it ok ? (FD)*/\
50     \
51     /* NMT-nodeguarding */\
52     TIMER_NONE,                                /* GuardTimeTimer */\
53     TIMER_NONE,                                /* LifeTimeTimer */\
54     _nodeguardError,           /* nodeguardError */\
55     & NODE_PREFIX ## _obj100C,                 /* GuardTime */\
56     & NODE_PREFIX ## _obj100D,                 /* LifeTimeFactor */\
57     {REPEAT_NMT_MAX_NODE_ID_TIMES(nodeGuardStatus_Initializer)},\
58     \
59     /* SYNC */\
60     TIMER_NONE,                                /* syncTimer */\
61     & NODE_PREFIX ## _obj1005,                 /* COB_ID_Sync */\
62     & NODE_PREFIX ## _obj1006,                 /* Sync_Cycle_Period */\
63     /*& NODE_PREFIX ## _obj1007, */            /* Sync_window_length */\
64     _post_sync,                 /* post_sync */\
65     _post_TPDO,                 /* post_TPDO */\
66     _post_SlaveBootup,            /* post_SlaveBootup */\
67   _post_SlaveStateChange,            /* post_SlaveStateChange */\
68     \
69     /* General */\
70     0,                                         /* toggle */\
71     NULL,                   /* canSend */\
72     NODE_PREFIX ## _scanIndexOD,                /* scanIndexOD */\
73     _storeODSubIndex,                /* storeODSubIndex */\
74     /* DCF concise */\
75     NULL,       /*dcf_odentry*/\
76     NULL,        /*dcf_cursor*/\
77     1,        /*dcf_entries_count*/\
78     0,        /* dcf_status*/\
79     0,      /* dcf_size */\
80     NULL,   /* dcf_data */\
81     \
82     /* EMCY */\
83     Error_free,                      /* error_state */\
84     sizeof(NODE_PREFIX ## _obj1003) / sizeof(NODE_PREFIX ## _obj1003[0]),      /* error_history_size */\
85     & NODE_PREFIX ## _highestSubIndex_obj1003,    /* error_number */\
86     & NODE_PREFIX ## _obj1003[0],    /* error_first_element */\
87     & NODE_PREFIX ## _obj1001,       /* error_register */\
88     & NODE_PREFIX ## _obj1014,       /* error_cobid */\
89     /* error_data: structure s_errors */\
90     {\
91     REPEAT_EMCY_MAX_ERRORS_TIMES(ERROR_DATA_INITIALIZER)\
92     },\
93     _post_emcy,              /* post_emcy */\
94     /* LSS */\
95     lss_Initializer\
96 }
相關文章
相關標籤/搜索