C语言宏定义##连接符和#符的使用(MFC就是靠##自动把消息和消息函数对应起来了,借助宏来减少switch case代码的编写量)
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; http://blog.csdn.net/dotphoenix/article/details/4345174
http://www.cnblogs.com/xuxm2007/archive/2011/06/10/2077255.html
https://my.oschina.net/shelllife/blog/123202
C语言宏定义##连接符和#符的使用(MFC就是靠##自动把消息和消息函数对应起来了,借助宏来减少switch case代码的编写量)的更多相关文章
- c/c++中宏定义##连接符 和#符的使用
C语言中如何使用宏C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念).下面对常遇到的宏的使用问题做了简单总结.关于#和##在C语言的宏中,#的功能是将其后面的宏 ...
- C语言宏定义##连接符和#符的使用
1. 关于宏(Macro) 属于编译器预处理的范畴,属于编译器概念(而非运行期概念). 2. 关于# #的功能:是 将其后面的宏参数进行 字符串化操作(Stringfication),即:在对它所引用 ...
- C语言的本质(19)——预处理之一:宏定义
我们在写代码时已多次使用过以"#"号开头的预处理命令.如包含命令#include,宏定义命令#define等.在源程序中这些命令都放在函数之外,而且一般都放在源文件的前面,它们称为 ...
- 宏定义(无参宏定义和带参宏定义),C语言宏定义详解
1.宏定义说明 宏定义是比较常用的预处理指令,即使用"标识符"来表示"替换列表"中的内容.标识符称为宏名,在预处理过程中,预处理器会把源程序中所有宏名,替换成宏 ...
- 黑马程序员——C语言基础 枚举 宏定义 自定义 static exterm
Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) (一)枚举 1)枚举类型的定义 枚举是C语言中的一种基本数据类型,并不是构 ...
- C语言宏定义和宏定义函数
要写好C语言,漂亮的宏定义是非常重要的.宏定义可以帮助我们防止出错,提高代码的可移植性和可读性等. 在软件开发过程中,经常有一些常用或者通用的功能或者代码段,这些功能既可以写成函数,也可以封装成为宏定 ...
- VC中预处理指令与宏定义详解
刚接触到MFC编程的人往往会被MFC 向导生成的各种宏定义和预处理指令所吓倒,但是预处理和宏定义又是C语言的一个强大工具.使用它们可以进行简单的源代码控制,版本控制,预警或者完成一些特殊的功能. 一个 ...
- 宏定义中的##操作符和... and _ _VA_ARGS_ _
1.Preprocessor Glue: The ## Operator 预处理连接符:##操作符 Like the # operator, the ## operator can be used i ...
- C/C++ 宏定义
宏定义(无参宏定义和带参宏定义) 宏定义是比较常用的预处理指令,即使用"标识符"来表示"替换列表"中的内容.标识符称为宏名,在预处理过程中,预处理器会把源程序中 ...
随机推荐
- 用Canvas画一个刮刮乐
Canvas 通过 JavaScript 来绘制 2D图形.Canvas 是逐像素进行渲染的.开发者可以通过javascript脚本实现任意绘图.Canvas元素是HTML5的一部分,允许脚本语言动态 ...
- C#连接Sqlserver代码
刚开始把数据库的密码搞错了,硬是连不上... //数据库连接类 SqlConnection conn = new SqlConnection("server=.;database=test; ...
- 常见排序算法(java实现)
常见排序算法介绍 冒泡排序 代码: public class BubbleSort { public static void sort(int[] array) { int tValue; for ( ...
- Methods for Using Message Queuing Telemetry Transport for Sensor Networks to Support Sleeping Devices
Methods support a sleep mode for an embedded device. Embedded devices like sensors and actuators use ...
- Hibernate——(2)增删改查
案例名称:Hibernate完成增删改查 案例描述:抽取出工具类并完成删除.修改.查询功能. 具体过程: 1.使用上面的例子(Hibernate--(1)Hibernate入门http://blog. ...
- Smarty优缺点
Smarty优点: 1. 速度:采用smarty编写的程序可以获得最大速度的提高,这一点是相对于其它的模板引擎技术而言的. 2. 编译型:采用smarty编写的程序在运行时要编译成一个非模板技术的PH ...
- vue 使用jquery (全局)
1 全局配置jquery , 个人习惯 , 离不开jquery了 然后重启项目 就 完事
- Alien Widgets加速了绘制、减少了闪烁。但通过设置,还可以使用Native Widget
QWidget::createWindowContainer和QWindow::setParentNative Widgets vs Alien Widgets http://doc.qt.io/qt ...
- node lesson2
var express = require('express'); var utility = require('utility'); var app = express(); app.get('/' ...
- Android笔记--自定义控件仿遥控器的圆形上下左右OK圆盘按钮
原文:Android笔记--自定义控件仿遥控器的圆形上下左右OK圆盘按钮 上面就是几张预览图!代码在最底下 主要就两个步骤,画图.监听点击 1.整个控件基本上是一步步画出来的,重写onDraw方法开始 ...