C语言中如何使用宏连接多个字符串(#和##的用法)
2017-10-02 09:32
459 查看
最近在编写一个项目的代码时,需要在宏定义中连接多个字符串,具体来说就是,先定义一个软件版本号,然后再定义一个硬件版本号, 然后再将他们拼合起来生成一个综合版本号。这些动作我都希望在宏定义中直接完成,提供代码的可读性和可移植性。
类似于下面这样的:
如上,为了把SOFTWARE_VERSION和HARDWARE_VERSION连接起来,一般的程序猿应该都了解,其实办法很简单,就是使用“#”和“##”这两个特殊的宏转义字符。下面就对他们进行一下简单的介绍:
1、#:字符串
“#”的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量,通过替换后在其左右各加上一个双引号。比如下面代码中的宏:
那么实际使用中会出现下面所示的替换过程:
被替换为
2、##:连接两个参数
“##”被称为连接符(concatenator),用来将两个Token连接为一个Token。注意这里连接的对象是Token就行,而不一定是宏的变量。比如你要做一个菜单项命令名和函数指针组成的结构体的数组,并且希望在函数名和菜单项命令名之间有直观的、名字上的关系。那么下面的代码就非常实用:
COMMAND宏在这里充当一个代码生成器的作用,这样可以在一定程度上减少代码密度,间接地也可以减少不留心所造成的错误。我们还可以n个##符号连接 n+1个Token,这个特性也是#符号所不具备的。比如:
所以,上面提出的问题,自然就可以解决掉了。如下:
但是,经过实际测试,以上的代码,只能用于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连接起来,一般的程序猿应该都了解,其实办法很简单,就是使用“#”和“##”这两个特殊的宏转义字符。下面就对他们进行一下简单的介绍:
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##_##d typedef 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
待续……..
相关文章推荐
- 使用 “+”号实现多个字符串的连接
- 如何正确获得mysql,access的ADO连接字符串,并使用该连接字符串连接数据库
- 如何:使用数据源控件时保证连接字符串的安全性 (Visual Studio)
- C语言:使用冒泡排序,排序多个字符串(优化)。
- Python学习笔记之疑问10:如何使用分隔符连接list中的字符串
- None用法+连接字符串优先使用join +用format而不是%+区别可变对象和不可变对象(list的深拷贝和浅拷贝)
- [导入]如何使用 ASP.NET 实用工具加密凭据和会话状态连接字符串
- c语言中如何使用字符串
- 不要使用连接来合并多个字符串,应该使用StringBuilder来提高性能
- 如何使用 ASP.NET 实用工具加密凭据和会话状态连接字符串
- c语言中字符串的之间的复制与连接,memcpy和strcat的简单使用。
- C语言:使用冒泡排序,排序多个字符串(优化)。
- C语言 不使用strcat函数实现连接两个字符串功能
- NET中使用三层构架如何从DAL层读取web.config中的数据库连接字符串!
- C语言(如何优雅地使用字符串)
- C语言字符串连接strcat、strncat用法说明和注意事项
- [导入].NET中使用三层构架如何从DAL层读取web.config中的数据库连接字符串!
- split -l的使用及nohup命令连接多个程序名& 用法探讨
- c语言连接多个字符串(strcat函数实现)
- 使用spring.net+nibernate时如何用aspnet_regiis加密数据库连接字符串