C语言宏与单井号(#)和双井号(##)
C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念)。下面对常遇到的宏的使用问题做了简单总结。
关于#和##
在C语言的宏中,#的功能是将其后面的宏参数进行字符串化操作(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);
这样每次divider(除数)为0的时候便会在标准错误流上输出一个提示信息。
而##被称为连接符(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;
## 连接符号由两个井号组成,其功能是在带参数的宏定义中将两个子串(token)联接起来,从而形成一个新的子串。但它不可以是第一个或者最后一个子串。所谓的子串(token)就是指编译器能够识别的最小语法单元。
#符是把传递过来的参数当成字符串进行替代。
下面来看看它们是怎样工作的。这是MSDN上的一个例子。 假设程序中已经定义了这样一个带参数的宏:
#define paster( n ) printf( "token" #n " = %d", token##n )
同时又定义了一个整形变量: int token9 = 9;
现在在主程序中以下面的方式调用这个宏: paster( 9 );
那么在编译时,上面的这句话被扩展为: printf( "token" "9" " = %d", token9 );
注意到在这个例子中,paster(9);中的这个”9”被原封不动的当成了一个字符串,与”token”连接在了一起,从而成为了token9。而#n也被”9”所替代。 可想而知,上面程序运行的结果就是在屏幕上打印出token9=9
定义单行宏:主要有以下三种用法.
1) 前加##或后加##,将标记作为一个合法的标识符的一部分.注意,不是字符串.多用于多行的宏定义中.例如:
2) 前加#@,将标记转换为相应的字符,注意:仅对单一标记转换有效
3) 前加#,将标记转换为字符串.
C语言宏与单井号(#)和双井号(##)的更多相关文章
- C语言宏定义时#(井号)和##(双井号)的用法
C语言中如何使用宏C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念).下面对常遇到的宏的使用问题做了简单总结. 关于#和## 在C语言的宏中,#的功能是将其后面 ...
- C语言宏定义时#(井号)和##(双井号)的用法1
#在英语里面叫做 pound 在C语言的宏定义中,一个#表示字符串化:两个#代表concatenate 举例如下: #include <iostream> void quit_comman ...
- 转:C语言宏定义时#(井号)和##(双井号)的用法
转自:http://www.cnblogs.com/welkinwalker/archive/2012/03/30/2424844.html#2678295 #在英语里面叫做 pound 在C语言的宏 ...
- C语言宏定义时#(井号)和##(双井号)作用
#的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量 通过替换后在其左右各加上一个双引号. #define example(instr) prin ...
- C/C++ 中##(两个井号)和#(一个井号)用法
##(两个井号)和#(一个井号)都是什么意思 连接符 ##(两个井号) 不知道什么符 #(一个井号) ## 连接符号由两个井号组成,其功能是在带参数的宏定义中将两个子串(token)联接起来,从而形成 ...
- C语言(C++语言)中##(两个井号)和#(一个井号)用法[转]
文章来源:http://blog.csdn.net/starboybenben/article/details/49803315 C语言(C++语言)中的宏(Macro)属于编译器预处理的范畴,属于编 ...
- C++中##(两个井号)和#(一个井号)用法
C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念).下面对常遇到的宏的使用问题做了简单总结.关 于#和##在C语言的宏中,#的功能是将其后面的宏参数进行字符串化 ...
- C语言 单引号和双引号的区别
最近的C语言课在教字符串,貌似N多同学搞不清楚单引号和双引号的区别,有人还以为在C语言里用哪个都可以...其实C语言中的单引号和双引号含义是一点也不一样滴... 1.含义不同. 用单引号引起的一个字符 ...
- C语言进阶—— 单引号和双引号14
单引号和双引号 C语言中的单引号用来表示字符字面量 C语言中的双引号用来表示字符串字面量 ‘a’表示字符字面量,在内存中占用一个字节,'a'+1表示'a'的ASCII码加1,结果为'b' " ...
随机推荐
- Windows7 下安装 CentOS6.5
内容来自:http://blog.163.com/for_log/blog/static/2162830282013031031278/第一部分:安装前准备1. 准备两个fat32格式的分区,一个用于 ...
- thinkphp ajax检测是否数据可用
模板文件:如 index.html 模板文件如:(index.html) <form><input type="text" name="username ...
- [转]PHP Session原理分析及使用
之前在一个叫魔法实验室的博客中看过一篇<php session原理彻底分析>的文章,作者从session的使用角度很好阐述了在代码运行过程中,每个环节的变化以及相关参数的设置及作用.本来想 ...
- 【python】分片copy和等号的区别
例一 >>> list1=[1,2,3,4]>>> list2=list1>>> list3=list1[:]>>> list1 ...
- Python学习_数据处理split方法
用open方法导入文件“sketch.txt”后,用split()方法进行分割: >>> import os >>> os.chdir('C:/Python33/H ...
- C++库编译
C++库编译 1. POCO编译 进入源文件目录,选择相应的VS版本进行编译(build_vs140). 设置系统环境变量: POCO_BASE 2. Boost编译 ####简单编译 在 ...
- C# 实现繁体字和简体字之间的转换
今天收到一个需求,将一组简体的汉字转换成繁体的汉字,刚开始有点茫然,后来在网上搜了一下思路,结果很少有涉及,终于我在看了MSDN后找到了如何解决,可能这方面对一些高程来说很Easy,但是除了高程还有很 ...
- 可以用来开发h5的软件小结
webStorm phoneGap notepad++ eclips text sublime dreamWeaver intellij idea 学习h5 需要掌握的 大块的知识 xhtml ja ...
- 计算几何模板 (bzoj 1336,poj 2451 ,poj3968)
poj 3968 (bzoj 2642) 二分+半平面交,每次不用排序,这是几个算几版综合. #include<iostream> #include<cstdio> #incl ...
- comet ajax轮询
http://www.ibm.com/developerworks/cn/webservices/ws-tip-jaxwsrpc.html http://www.cnblogs.com/pifoo/a ...