宏定义中#和##的使用
1. #
#的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号
1 #define WARN_IF(EXP) / 2 do{ if (EXP) / 3 fprintf(stderr, "Warning: " #EXP "/n"); } / 4 while(0)
那么实际使用中会出现下面所示的替换过程:
1 WARN_IF (divider == 0);
被替换为
1 do { 2 if (divider == 0) 3 fprintf(stderr, "Warning" "divider == 0" "/n"); 4 } while(0);
这样每次divider(除数)为0的时候便会在标准错误流上输出一个提示信息。
2. ##
##被称为连接符(concatenator),用来将两个Token连接为一个Token,##符是把传递过来的参数当成字符串进行替代。
例如
1 #define PRINT( n ) printf( "token" #n " = %d", token##n )
则
PRINT(mine );
在编译时会被编译成
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 }