最近在编写一个项目的代码时,需要在宏定义中连接多个字符串,具体来说就是,先定义一个软件版本号,然后再定义一个硬件版本号, 然后再将他们拼合起来生成一个综合版本号。这些动作我都希望在宏定义中直接完成,提供代码的可读性和可移植性。

类似于下面这样的:

#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语言中如何使用宏连接多个字符串(#和##的用法)相关推荐

  1. c语言宏定义比较三个数大小,C语言中两个宏进行大小对比,其中一个没有定义,这种行为如何定义。...

    1.C语言中两个宏进行大小对比,其中一个没有定义,这种行为如何定义呢? 在学习U-boot的过程中遇到这么一个定义: # if (CONFIG_ENV_ADDR >= CONFIG_SYS_MO ...

  2. C语言中预定义宏的应用

    __LINE__                       在源代码中插入当前源代码行号         __FILE__                       在源代码中插入当前源代码文件名 ...

  3. 谈谈你对c语言中数据(各种常量,变量,函数参数,字符串)的存储认识,自考《高级语言程序设计》知识点总结(二)...

    2.1 C语言的数据类型 数据类型包含两方面的内容:数据的表示和对数据加工的操作.数据的全部可能表示构成数据类型的值的集合.数据全部合理的操作构成数据类型的操作集合. 在C语言中,把整型.实型和字符型 ...

  4. C语言中如何将小数或整数和字符串合二为一

    如何将小数和字符串结合在一起 问题 用到的知识 字符串拼接 C 字符串函数 sprintf() 实现功能 后续 问题 我们在平时的开发中,经常会遇到,想将小数或者整数和字符串结合在一起,然后使用或者输 ...

  5. c语言求n个数的最小值博客,C语言中的#define宏定义 求一组数的最大值和最小值(转)...

    C语言有很多预编译关键字,如#if.#include.#else--,所有以#开头的的关键字都属于这一类,此处讨论#define关键字 #define的核心就是"替换" 如#def ...

  6. 如何在Excel中使用VB宏连接SAP系统

    准备工作 Excel连接SAP的时候需要使用RFC library, 首先从Service Marketing Place下载RFC SDK. 具体路径如下: http://service.sap.c ...

  7. sbit在c语言中的作用,C语言中对引的读写操作 sbit的三种用法

    描述 在C语言里.如果直接写P1.O,C编译器并不能识别,而且P1.O也不是一个合法的C语言变量名,所以得给它另起一个名字,比如起名为P1-0,可是P1-0是不是就是P10呢? 可以这么认为,C编译器 ...

  8. html语言中注释标记,html注释代码<!--......--> 标签的用法详解

    别小看了简单的html注释代码标签,它的作用还是挺大的,对于复杂而庞大的代码量,有必要在需要说明,备注,解释的地方插入一些注释内容,方便以后编辑.修改.查询代码,还可以对某些不需要显示或执行的代码进行 ...

  9. C语言怎么判断字符YN,c语言中的宏_详解(转)

    1. 简单宏定义 简单的宏定义有如下格式: [#define指令(简单的宏)] #define 标识符替换列表 替换列表是一系列的C语言记号,包括标识符.关键字.数.字符常量.字符串字面量.运算符和标 ...

最新文章

  1. HelloServlet
  2. 【推导】【线段树】hdu5929 Basic Data Structure
  3. Python学习教程实用技法:通过公共键对字典列表排序—itemgetter
  4. 不会三种编程语言的不算程序员 走近阿里云 MVP烁淼吐槽大佬
  5. LInux--进程间通信
  6. jquery checked 操作多选
  7. springMVC使用注解方式进行页面跳转
  8. python def函数_Python教程之Lambda表达式知识概述
  9. 当Python的lambda表达式遇上变量作用域
  10. 存储过程与函数的区别
  11. DH参数法 例题 机器人学
  12. Acid-PEG2000-Pyrene,羧基和芘丁酸修饰的PEG,HOOC-PEG2000-Pyrene
  13. 设计模式(一)--编程界的九阳神功
  14. 使用python+opencv写一个简单的条形码识别代码
  15. Windows环境安装MySQL步骤
  16. 外贸独立站之Facebook广告
  17. Eclipse安装PMD插件
  18. 【四轴飞行器】【电机部分】PWM驱动空心杯转速
  19. idea多环境配置及问题解决
  20. JavaScript调用原生API获取手机型号

热门文章

  1. 记一次 Vue 移动端活动倒计时优化
  2. A1-2017级算法上机第一次练习赛 H 模式寻对
  3. iOS 编写高质量Objective-C代码(六)
  4. 织梦生成栏目找不到模板怎么知道是哪个栏目和模板
  5. UVA 11210 中国麻将
  6. Mongoose Schemas定义中timestamps选项的妙用
  7. VS2013引入boost库编译时出现'QueueUserAPC' : is not a member of '`global namespace'
  8. CentOS6.x下GitLab安装
  9. 用chkconfig配置linux自启动服务
  10. 什么导致了交换机端口呈现err-disable状态?