- 浏览: 37162 次
最新评论
今天拜读前辈的代码,看到了一种奇怪的用法:##。以为是C99的新标准,再翻查经典的 K&R,才发现原来早已是C语言的规范用法了。居然到今天才知道,真失败-_-!
##是一种预处理运算符,用在宏定义中,在宏解析时将实际的参数进行连接。简单的例子就是
现在,在代码中使用 cat(t1,t2) 的效果就是 t1t2,连接起来作为了一个整体。
##的一个很大的特点在于,对于枚举型的数据,##可以取到枚举的“名称”而不是枚举的“数值”。比如:
那么,cat(t,enumname2) 的结果就是 tenumname2。
这就使得##有了一个很大的用处:对于两个存在关联的巨型枚举类型而言,使用##能够显著的减少转换的工作量。
设想这样一种情况:我们需要一个可能很大的枚举来表示状态:State。同时,每个状态都对应一个定时器:State_Timer。每个定时器的命名都是状态名前面加上 Timer_ 。
当进入每一种状态的时候,都需要启动该状态的定时器。为了避免写一个巨长的switch-case来进行转换,我们的代码可以这样:
这样,通过##的处理,我们避免了一个庞大的switch-case 或者其他方式的转换,代码也简洁了许多。
前两天还在为二十多元的K&R是否值得买而犹豫。现在看来,静下心好好的巩固基础知识,才是真正的重中之重呀。
##是一种预处理运算符,用在宏定义中,在宏解析时将实际的参数进行连接。简单的例子就是
#define cat(a,b) a ## b
现在,在代码中使用 cat(t1,t2) 的效果就是 t1t2,连接起来作为了一个整体。
##的一个很大的特点在于,对于枚举型的数据,##可以取到枚举的“名称”而不是枚举的“数值”。比如:
enum
{
enumname1 = 2,
enumname2 = 3
} eT;
eT = enumname2;
{
enumname1 = 2,
enumname2 = 3
} eT;
eT = enumname2;
那么,cat(t,enumname2) 的结果就是 tenumname2。
这就使得##有了一个很大的用处:对于两个存在关联的巨型枚举类型而言,使用##能够显著的减少转换的工作量。
设想这样一种情况:我们需要一个可能很大的枚举来表示状态:State。同时,每个状态都对应一个定时器:State_Timer。每个定时器的命名都是状态名前面加上 Timer_ 。
当进入每一种状态的时候,都需要启动该状态的定时器。为了避免写一个巨长的switch-case来进行转换,我们的代码可以这样:
enum State
{
Active,
Idle,
Suspended,
Blocked,
//...
};
enum State_Timer
{
Timer_Active,
Timer_Idle,
Timer_Suspended,
Timer_Blocked,
//...
};
#define timer(state) Timer_ ## state
#define Enter_State(state); \
{\
start_timer( timer(state) );\
}
void start_timer ( enum State_Timer timer )
{
//...
}
{
Active,
Idle,
Suspended,
Blocked,
//...
};
enum State_Timer
{
Timer_Active,
Timer_Idle,
Timer_Suspended,
Timer_Blocked,
//...
};
#define timer(state) Timer_ ## state
#define Enter_State(state); \
{\
start_timer( timer(state) );\
}
void start_timer ( enum State_Timer timer )
{
//...
}
这样,通过##的处理,我们避免了一个庞大的switch-case 或者其他方式的转换,代码也简洁了许多。
前两天还在为二十多元的K&R是否值得买而犹豫。现在看来,静下心好好的巩固基础知识,才是真正的重中之重呀。
发表评论
-
入职第一天
2004-07-12 20:20 554很喧闹的一天新人训。当然,可以说是激情四射,或者说是嘈杂无聊。 ... -
迎接部门训
2004-07-13 18:07 511今天开始迎接部门的专业训了,C#、SQL Server、数据库 ... -
生活的颜色
2004-07-14 18:57 575一个诚实的裁判就这样慷慨赴义了,很多很多黑暗中的裁判们却还好端 ... -
历史的沉思
2004-07-16 12:43 639很久以前的一篇文章, ... -
选择的未来
2004-07-17 15:11 491先提一个问题:做一个技术员,技术能力重要还是业务知识重要?再提 ... -
统一的困惑
2004-07-19 20:45 532RUP(Rational统一过程)的基本开发方式是迭代。需求迭 ... -
开发的效率
2004-07-21 17:44 529面对多人协同开发的分层系统,有两种开发方式:其一、一人负责一到 ... -
模型或模式
2004-07-22 23:27 645不论是吵吵嚷嚷的软件工程、XP建模,还是死灰复燃的MDA、一心 ... -
对象的效率
2004-07-28 21:22 537面向对象带来方便的同时亦带来很多的问题。类的继承在扩展的同时也 ... -
泪写的文章
2004-07-29 20:20 512今天我又哭了。一个月前,我还觉得哭于我是很遥远的事情。甚至,我 ... -
期待的精彩
2004-07-31 11:08 534好久好久没有看到国足这么酣畅的胜利了,好久好久没有体会到看球的 ... -
转载的文章
2004-08-01 10:50 502今天转载一篇吧,记录一段可笑的过往。 别了,Dr.Dobb's ... -
TDD 心得
2004-08-03 16:19 788一直觉得,近年来,真正有意义的技术或者思想只有两个:Refac ... -
近期的任务
2004-08-06 12:54 5781、Test Driven Development2、Java ... -
上海印象一
2004-08-09 22:28 567车一进入上海,扑面而来的就是一片一片的高楼,黑压压地便压了过来 ... -
上海印象二
2004-08-10 21:19 522上海当然是天堂,但也是仅对一部分人一部分地区。对大多数人大部分 ... -
转载的文章
2004-08-13 23:38 453O/R Mapping中的继承~ http://www.cnb ... -
生日的祝福
2004-08-15 10:49 710今天是agate的生日。尽管这句话已经被用得很俗,不过我还是想 ... -
等爱的狐狸
2004-08-27 18:16 567“对我来说,你还只是一个小男孩,就像其他千万个小男孩一样。我不 ... -
飞翔的寓言
2004-08-30 20:58 514我才发现梦想与现实间的差别逆着风让自己体验每一个感觉就像是寓言 ...
相关推荐
C语言中#与##用法详解 C语言中,#与##是两个重要的预编译运算符,它们广泛应用于宏定义中。下面我们将详细介绍#与##的用法和示例。 一、#基本用法 #运算符的基本用法是将参数转换为字符串。在宏定义中,#运算符将...
在实际应用中,根据具体需求选择最适合的输入方法是非常重要的。例如,对于需要读取包含空格的字符串时,推荐使用`cin.getline()`或`getline()`;而对于安全性要求较高的场合,则应避免使用`gets()`。
### Nmap扫描原理与用法 #### Nmap简介 Nmap是一款开源且免费的网络发现(Network Discovery)和安全审计...对于想要深入了解网络结构和增强网络安全性的专业人士而言,掌握Nmap的使用方法是一项非常有价值的技能。
### 焊接式SMA接头的详细使用方法 #### SMA接头概述 SMA(Subminiature version A)接头是一种广泛应用于射频通信领域的小型化连接器,适用于频率高达18GHz的应用场景。传统的SMA接头安装方式通常采用压接式,即...
### 使用方法: 添加`subfunc`:打开matlab,右键`subfun`->`添加到路径`->`选定的文件夹和子文件夹` 运行`demox.m` # Swarm_Sim_Matlab ### 环境: matlab2020a Win10 ### 使用方法: 添加`subfunc`:打开...
关于 #define 指令的用法大全 #define 指令是 C 语言中的一种预处理指令,用于给常量赋予一个有意义的名称。在本文中,我们将详细介绍 #define 指令的用法、实例和注意事项。 定义 ---- #define 指令的基本语法有...
然而,`#define`的不当使用可能会引入一系列的问题和陷阱,本文将深入探讨这些陷阱及其解决方法。 #### 宏定义陷阱 ##### 1. 括号的重要性 当定义一个宏时,如果不正确地使用括号,可能会导致意想不到的结果。...
下面我们将详细地介绍它们的用法和实例分析。 #ifdef 命令 #ifdef 命令是用来判断一个宏是否已经被定义,如果宏已经被定义,那么编译器将编译后面的代码,否则将跳过。 例如: ``` #define NUM #ifdef NUM ...
###################本文件夹内为Arduino程序执行所需库文###############...使用方法:将库文件复制至Arduino IDE安装目录下的libraries文件夹内,重启软件后即可 MultiLCD -> OLED支持库 ServoTimer2 -> 舵机支持库
本文将详细介绍一种新型数字滤波器——MAX291至MAX297系列的性能与使用方法。这些数字滤波器由美国MAXIM公司推出,以其小巧的体积、简便的操作、出色的阻带衰减以及优良的通带特性而著称。尽管这些芯片具有共同的...
C 语言宏中 "#" 和 "##" 的用法是非常重要的,特别是在查看 Linux 内核源码的过程中,这两种符号经常被使用。下面我们将从一般用法、宏参数展开、应用特例三个方面来详细讲解这两种符号的用法。 一、一般用法 在 C...
#### 使用方法 1. **初始化调用**: - 第一次调用`strtok`时,必须提供待分割的字符串`s`以及分隔符`delim`。 - 示例代码: ```c char buf[] = "GoldenGlobalView"; char *token = strtok(buf, " "); ``` ...
本文将详细介绍`#`符号的使用方法及其应用场景,帮助读者更好地理解和掌握Struts2框架的相关知识。 #### 一、Struts2简介 Struts2是基于Struts1的基础上发展起来的一款开源Web应用框架,它使用MVC(Model-View-...
### OGNL中的#、%和$符号用法说明 #### 概述 OGNL(Object-Graph Navigation Language)是一种强大的表达式语言,用于获取和设置Java对象的属性。它在许多Java应用框架中得到了广泛应用,尤其是在Struts2中作为...
### GRUB的使用用法详解 #### 一、引言 GRUB(Grand Unified Bootloader)作为一款功能强大的启动加载程序,在Linux系统中扮演着重要的角色。它不仅可以用来引导Linux内核,还支持多种操作系统之间的多引导配置。...
#####使用方法: Windows系统下,请将out/win目录下的CharlesLoader.jar和run-charlesloader.bat两个文件放置在Charles/lib/下运行run-charlesloader.bat即可, Linux和Mac OS X等类Unix系统下,可以使用自行看bat中的...
#生成 Redis 协议以原始格式生成 Redis 协议,以便使用“redis-cli --pipe”命令在 redis 服务器中大量快速地插入/删除.... 键。它接受管道作为输入,其中包含格式为“DEL key”、“SET key value”... 的 redis ...
本文将详细介绍这两种工具的基本使用方法及其特点。 #### PyInstaller详解 **PyInstaller** 是一个广泛使用的Python程序打包工具,它可以将Python程序打包成独立的可执行文件。它支持多个平台,包括Windows、Linux...
在C语言中,“#”和“##”是预处理指令中使用的特殊操作符,它们在宏定义和对象参数化的上下文中具有独特的用法。以下是关于这两个操作符的详细知识点: 1. 宏定义中的“#”操作符 “#”操作符在宏定义中用于将宏...
### 用法 #### 1. 本地打包 ```shell script mvn package install -U -DskipTests ``` #### 2. 在项目中引入依赖包 ```xml <groupId>cn.caohd</groupId> <artifactId>seata-async <version>0.1.0-SNAPSHOT ...