在C语言开发中,宏定义是一个非常有用的工具,它可以使我们的代码更容易理解,更容易维护。如查一个常量在多处被使用,且今后可能会根据不同需要而修改的话,将其define一下那是再好不过了。除此之外,宏定义还有其他的功能,了解它,将更好地辅助我们开发C程序。先看个例子:

  1. #define Conn(x,y)   x##y
  2. #define ToString(x) #x
  3. #define ToChar(x)   #@x

这几个宏定义中分别用到了“##”、“#”,“#@”它们的功能分别是:
1、粘接操作符##——连接两个宏名,注意所连接的是宏名,而不是其所指代的值;
如int Conn(a,b);定义了一个int型变量ab,以后可以直接调用ab,而不必采用Conn(a,b)的形式;
printf(Conn("ab","cd"));输出结果为:abcd
但是:

  1. #define M 0
  2. #define var(x) Var_##x
  3. ...
  4. int var(M);//此处定义了什么?

根据ANSI/ISO C,##操作符只是简单地粘接两个宏名,则int var(M)定义的应该就是Var_M,据测试,这一点是没有问题的。但在一些比较古老的C编译环境中,也有可能定义的是Var_0,比如在TC 2.0中测试发现“Var_0=0”可编译通过,而“Var_M=0”出现ERROR。

2、字符串化操作符#——将宏名转化为字符串

如printf(ToString(var1));输出结果为:var1。var1可以是一个已定义的变量名,也可以是一个从未出现的字符组合
类似地,若有:

  1. #define STR 0
  2. ...
  3. printf(Tostring(STR));//

当前流行编译环境会输出STR,而TC 2.0则会输出0。

3、字符化操作#@——将宏名转化为字符,注意:早期编译器可能不支持
如:

  1. char c;
  2. c = ToChar(1);//c = '1'
  3. c = ToChar(a);//c = 'a'

如果提供的宏中不止一个字符(注意,不能超过4个,否则编译器报错),则转化结果为最后一个字符,如

  1. c = ToChar(abc);//c = 'c'
  2. c = ToChar(abcd);//c= 'd'
  3. c = ToChar(abcde);//ERROR

总结一下,关于其用法是自己总结的,肯定不全。

1、使用中遵循ANSI C中规定,但要记得编译通不过是可能是早期编译器不支持C标准的问题;
2、##操作可应用在变量定义中,若程序开发中遇到要定义一大堆变量,且这些变量具有相同的前缀时,##很显得尤为重要,它可以使代码更加整洁,且减少了出错的机率。如果一旦后来发现需要批量修改变量前缀,你会庆幸自己使用了这么一件利器;
3、#操作符可用于调试时将变量名输出,可配合##一起使用,如定义#define CHECK_VAR(x,fmt) printf(#x " = " #fmt "\n", x),则CHECK_VAR(var1,%d)相当于printf("var = %d\n", var1);

Tips:
1、ANSI C中规定若宏定义名出现在引号(' '或" ")中,则不进行替换,但有些早期编译器的处理可能有所不同,如#define CTRL(c) (‘c’ & 37),按照标准CTRL(d)被扩展成('c' & 37)。显然,这没有完成作者的本意,它在某些编译器下碰巧能工作不过是个意外,实际使用中应避免。
2、字符串的连接不必使用##这么麻烦,实际中两个字符串常量可以直接写到一起,如printf("ab""cd")输出abcd。或在使用##宏定义时,可以用printf(ToString(str) "\n");输出字符串后换行,以前不敢这样用,后来试验了下发现还比较好使,当然直接用puts也可完成同样功能。
3、若要使#或##转换的是宏字符常量的值也不是其名字,可以使用间接方法,如:

  1. #define ToString(x) #x
  2. #define Xstr(x) ToString(x)
  3. #define STR1 STR2
  4. ...
  5. printf(Xstr(STR1));//输出结果是STR2而非STR1

转载于:https://blog.51cto.com/sunnylgz/628831

C语言预处理功能——关于字符串化和符号粘贴相关推荐

  1. C 语言 宏定义 :字符串化 stringify 的应用

    字符串化 通过C 语言的宏(MICRO),可以把数值或者一段字符的组合,转换为字符串. 因为 C语言的宏在[预处理]阶段就展开了,所以可以实现一些比较使用的功能,比如一些数据的初始化操作 比如定义一个 ...

  2. C语言把宏定义字符串化

    原文链接 有时候想要把一个宏定义的内容嵌入到字符串中去. 例如宏定义: #define RATE 15000 #define STR1(R) #R #define STR2(R) STR1(R)pri ...

  3. C语言,宏的字符串化

    背景: 目前项目中牵扯到多节点通讯,而每个节点都需要有ID,这个ID分别以hex格式,字符串格式各存一份,但每次改设备ID都得两个都改,于是想试试在字符串中可不可以使用宏定义来避免这个问题. 正文: ...

  4. C语言试题三十二之编写函数function,它的功能是:将一个字符串转换为一个整数(不得调用c语言提供的将字符串转换为整数的函数)。

    1. 题目 请编写函数function,它的功能是:将一个字符串转换为一个整数(不得调用c语言提供的将字符串转换为整数的函数). 2 .温馨提示 C试题汇总里可用于计算机二级C语言笔试.机试.研究生复 ...

  5. 25.请编写一个函数fun,它的功能是:比较两个字符串的长度,(不得调用C语言提供的求字符串长度的函数),函数返回较长的字符串。若两个字符串长度相同,则返回第一个字 符串。

    25.请编写一个函数fun,它的功能是:比较两个字符串的长度,(不得调用C语言提供的求字符串长度的函数),函数返回较长的字符串.若两个字符串长度相同,则返回第一个字 符串. 例如,输入:beijing ...

  6. 24.请编写一个函数fun,它的功能是:将一个数字字符串转换为一个整数(不得调用C语言提供的将字符串转换为整数的函数)。

    24.请编写一个函数fun,它的功能是:将一个数字字符串转换为一个整数(不得调用C语言提供的将字符串转换为整数的函数). 例如,若输入字符串"-1234",则函数把它转换为整数值- ...

  7. R语言数据预处理、数据因子化并自定义因子标签、通过labels参数指定因子标签

    R语言数据预处理.数据因子化并自定义因子标签.通过labels参数指定因子标签 目录

  8. c语言相邻字符串字面量,C语言预处理#运算符的细节

    #运算符将宏的一个参数转换为字符串字面量,它仅允许出现在带参数的宏的替换列表中. 例如:使用PRINT_INT宏作为一个快捷的方法来整形变量或者表达式的值,#运算符可以使PRINT_INT为每个输出的 ...

  9. R 多变量数据预处理_超长文详解:C语言预处理命令

    一  前言 预处理(或称预编译)是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作.预处理指令指示在程序正式编译前就由编译器进行的操作,可放在程序中任何位置. 预处理是C语言的一个重要功能 ...

最新文章

  1. CentOS下yum安装nginx服务
  2. #39;$(this)#39;和#39;this#39;有什么区别?
  3. linux学习之路(一)--centos7安装JDK
  4. Codevs2822 爱在心中
  5. 关于WebBrowser.DocumentCompleted事件
  6. Qt中的基础图形绘制
  7. BAT面试进阶:最全Memcached面试30题含答案
  8. layui 分页ajax,实现Ajax异步的layui分页
  9. 用到f6的快捷键_简单上手excel秘籍:6大Excel技巧展示+50个常用快捷键!会这些就够了...
  10. POJ3349 Snowflake Snow Snowflakes(hash)
  11. java如何去掉文件后缀名_JAVA 递归批量更改文件后缀名 删除后缀
  12. mqtt测试工具(持续更新...)
  13. macbook安装linux分区,如何在MacBook Pro Retina上安装Linux
  14. 用socket搭建web服务器(TCP协议)
  15. 程序员常用的这十个电子书下载网站,你值得拥有
  16. 题目:在C语言中,表达式23|2^5的值是()
  17. python怎么才能不挂科_如何才能在大学里不挂科?
  18. 优盘格式化为FAT64
  19. 一次HTTP链接会产生多少数据流量
  20. 2018阿里巴巴基础平台研发工程师实习生笔试题:一.十进制数转换成的二进制数中有几个1. 二.输出IP所在的网段

热门文章

  1. Java中int[]与Integer[]相互转化的方法
  2. java 累进计费率计算_设计费400万,缴纳所得税100万,如何筹划
  3. STL源码剖析 仿函数
  4. Android Glide图片加载框架(四)回调与监听
  5. Android UI卡顿监控
  6. Android SharedPreferences总结及优化
  7. 永远和靠谱的人在一起!
  8. 米饭凉一凉再吃会更加地健康
  9. 超详细 图解 : IntelliJ IDEA 逆向生成 JAVA 实体类
  10. NGINX 配置超时时间