C语言中如何使用宏连接多个字符串(#和##的用法)
最近在編寫一個項目的代碼時,需要在宏定義中連接多個字符串,具體來說就是,先定義一個軟件版本號,然后再定義一個硬件版本號, 然后再將他們拼合起來生成一個綜合版本號。這些動作我都希望在宏定義中直接完成,提供代碼的可讀性和可移植性。
類似于下面這樣的:
#define SOFTWARE_VERSION "Software:V1.00" #define HARDWARE_VERSION "Hardware:V1.00" #define SYSTEM_VERSION ????如上,為了把SOFTWARE_VERSION和HARDWARE_VERSION連接起來,一般的程序猿應該都了解,其實辦法很簡單,就是使用“#”和“##”這兩個特殊的宏轉義字符。下面就對他們進行一下簡單的介紹:
1、#:字符串
“#”的功能是將其后面的宏參數進行字符串化操作(Stringfication),簡單說就是在對它所引用的宏變量,通過替換后在其左右各加上一個雙引號。比如下面代碼中的宏:
#define WARN_IF(EXP) \ do { \if (EXP) { \fprintf(stderr, "Warning: " #EXP "/n"); \} \ } while(0);那么實際使用中會出現下面所示的替換過程:
WARN_IF (divider == 0);被替換為
do {if (divider == 0) {fprintf(stderr, "Warning" "divider == 0" "/n");}} while(0);2、##:連接兩個參數
“##”被稱為連接符(concatenator),用來將兩個Token連接為一個Token。注意這里連接的對象是Token就行,而不一定是宏的變量。比如你要做一個菜單項命令名和函數指針組成的結構體的數組,并且希望在函數名和菜單項命令名之間有直觀的、名字上的關系。那么下面的代碼就非常實用:
struct command {char * name;void (*function) (void); };#define COMMAND(NAME) {NAME, NAME##_command}// 然后你就用一些預先定義好的命令來方便的初始化一個command結構的數組了:struct command commands[] = {COMMAND(quit),COMMAND(help),... }COMMAND宏在這里充當一個代碼生成器的作用,這樣可以在一定程度上減少代碼密度,間接地也可以減少不留心所造成的錯誤。我們還可以n個##符號連接 n+1個Token,這個特性也是#符號所不具備的。比如:
#define LINK_MULTIPLE(a,b,c,d) a##_##b##_##c##_##dtypedef struct _record_type LINK_MULTIPLE(name,company,position,salary);// 這里這個語句將展開為:// typedef struct _record_type name_company_position_salary;所以,上面提出的問題,自然就可以解決掉了。如下:
#define SOFTWARE_VERSION "Software:V1.00" #define HARDWARE_VERSION "Hardware:V1.00" #define SYSTEM_VERSION SOFTWARE_VERSION##" "##HARDWARE_VERSION但是,經過實際測試,以上的代碼,只能用于KEIL/ADS/IAR等集成編譯環境中。如果是在linux下,使用gcc編譯器的話,上述代碼就會出錯,目前尚未查出具體原因。經過一番折騰后,發現gcc環境下,如果要連接多個字符串,直接使用空格連接就行了。所以將其改為如下語句就可以了:
#define SOFTWARE_VERSION "Software:V1.00" #define HARDWARE_VERSION "Hardware:V1.00" #define SYSTEM_VERSION SOFTWARE_VERSION HARDWARE_VERSION待續……..
總結
以上是生活随笔為你收集整理的C语言中如何使用宏连接多个字符串(#和##的用法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OSS对象储存_oss存储是什么意思
- 下一篇: 如何使用makefile编译不同平台的目