`
阅读更多
今天拜读前辈的代码,看到了一种奇怪的用法:##。以为是C99的新标准,再翻查经典的 K&R,才发现原来早已是C语言的规范用法了。居然到今天才知道,真失败-_-!

##是一种预处理运算符,用在宏定义中,在宏解析时将实际的参数进行连接。简单的例子就是

#define cat(a,b) a ## b

现在,在代码中使用 cat(t1,t2) 的效果就是 t1t2,连接起来作为了一个整体。

##的一个很大的特点在于,对于枚举型的数据,##可以取到枚举的“名称”而不是枚举的“数值”。比如:

enum
{
   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 )
{
    
//...
}

这样,通过##的处理,我们避免了一个庞大的switch-case 或者其他方式的转换,代码也简洁了许多。

前两天还在为二十多元的K&R是否值得买而犹豫。现在看来,静下心好好的巩固基础知识,才是真正的重中之重呀。
分享到:
评论

相关推荐

    c语言中#与##用法详解

    C语言中#与##用法详解 C语言中,#与##是两个重要的预编译运算符,它们广泛应用于宏定义中。下面我们将详细介绍#与##的用法和示例。 一、#基本用法 #运算符的基本用法是将参数转换为字符串。在宏定义中,#运算符将...

    cin.get()等函数的详细用法总结

    在实际应用中,根据具体需求选择最适合的输入方法是非常重要的。例如,对于需要读取包含空格的字符串时,推荐使用`cin.getline()`或`getline()`;而对于安全性要求较高的场合,则应避免使用`gets()`。

    Nmap扫描原理与用法pdf

    ### Nmap扫描原理与用法 #### Nmap简介 Nmap是一款开源且免费的网络发现(Network Discovery)和安全审计...对于想要深入了解网络结构和增强网络安全性的专业人士而言,掌握Nmap的使用方法是一项非常有价值的技能。

    焊接式SMA接头的详细使用方法

    ### 焊接式SMA接头的详细使用方法 #### SMA接头概述 SMA(Subminiature version A)接头是一种广泛应用于射频通信领域的小型化连接器,适用于频率高达18GHz的应用场景。传统的SMA接头安装方式通常采用压接式,即...

    集群机器人Matlab仿真.rar

    ### 使用方法: 添加`subfunc`:打开matlab,右键`subfun`->`添加到路径`->`选定的文件夹和子文件夹` 运行`demox.m` # Swarm_Sim_Matlab ### 环境: matlab2020a Win10 ### 使用方法: 添加`subfunc`:打开...

    #define——用法大全

    关于 #define 指令的用法大全 #define 指令是 C 语言中的一种预处理指令,用于给常量赋予一个有意义的名称。在本文中,我们将详细介绍 #define 指令的用法、实例和注意事项。 定义 ---- #define 指令的基本语法有...

    #define 问题 用法陷阱

    然而,`#define`的不当使用可能会引入一系列的问题和陷阱,本文将深入探讨这些陷阱及其解决方法。 #### 宏定义陷阱 ##### 1. 括号的重要性 当定义一个宏时,如果不正确地使用括号,可能会导致意想不到的结果。...

    #ifdef,#else,#endif,#if用法详解

    下面我们将详细地介绍它们的用法和实例分析。 #ifdef 命令 #ifdef 命令是用来判断一个宏是否已经被定义,如果宏已经被定义,那么编译器将编译后面的代码,否则将跳过。 例如: ``` #define NUM #ifdef NUM ...

    Arduino所需库

    ###################本文件夹内为Arduino程序执行所需库文###############...使用方法:将库文件复制至Arduino IDE安装目录下的libraries文件夹内,重启软件后即可 MultiLCD -> OLED支持库 ServoTimer2 -> 舵机支持库

    一种新型数字滤波器的性能及用法

    本文将详细介绍一种新型数字滤波器——MAX291至MAX297系列的性能与使用方法。这些数字滤波器由美国MAXIM公司推出,以其小巧的体积、简便的操作、出色的阻带衰减以及优良的通带特性而著称。尽管这些芯片具有共同的...

    C语言宏中#和##的用法[文].pdf

    C 语言宏中 "#" 和 "##" 的用法是非常重要的,特别是在查看 Linux 内核源码的过程中,这两种符号经常被使用。下面我们将从一般用法、宏参数展开、应用特例三个方面来详细讲解这两种符号的用法。 一、一般用法 在 C...

    分割字符串用法

    #### 使用方法 1. **初始化调用**: - 第一次调用`strtok`时,必须提供待分割的字符串`s`以及分隔符`delim`。 - 示例代码: ```c char buf[] = "GoldenGlobalView"; char *token = strtok(buf, " "); ``` ...

    struts2中#号的用法

    本文将详细介绍`#`符号的使用方法及其应用场景,帮助读者更好地理解和掌握Struts2框架的相关知识。 #### 一、Struts2简介 Struts2是基于Struts1的基础上发展起来的一款开源Web应用框架,它使用MVC(Model-View-...

    OGNL中的#、%和$符号用法说明

    ### OGNL中的#、%和$符号用法说明 #### 概述 OGNL(Object-Graph Navigation Language)是一种强大的表达式语言,用于获取和设置Java对象的属性。它在许多Java应用框架中得到了广泛应用,尤其是在Struts2中作为...

    grub的使用用法

    ### GRUB的使用用法详解 #### 一、引言 GRUB(Grand Unified Bootloader)作为一款功能强大的启动加载程序,在Linux系统中扮演着重要的角色。它不仅可以用来引导Linux内核,还支持多种操作系统之间的多引导配置。...

    charlesloader-master

    #####使用方法: Windows系统下,请将out/win目录下的CharlesLoader.jar和run-charlesloader.bat两个文件放置在Charles/lib/下运行run-charlesloader.bat即可, Linux和Mac OS X等类Unix系统下,可以使用自行看bat中的...

    我使用 redis 的工具.zip

    #生成 Redis 协议以原始格式生成 Redis 协议,以便使用“redis-cli --pipe”命令在 redis 服务器中大量快速地插入/删除.... 键。它接受管道作为输入,其中包含格式为“DEL key”、“SET key value”... 的 redis ...

    Python程序打包工具py2exe和PyInstaller详解

    本文将详细介绍这两种工具的基本使用方法及其特点。 #### PyInstaller详解 **PyInstaller** 是一个广泛使用的Python程序打包工具,它可以将Python程序打包成独立的可执行文件。它支持多个平台,包括Windows、Linux...

    C语言中“#”和“##”的用法.pdf

    在C语言中,“#”和“##”是预处理指令中使用的特殊操作符,它们在宏定义和对象参数化的上下文中具有独特的用法。以下是关于这两个操作符的详细知识点: 1. 宏定义中的“#”操作符 “#”操作符在宏定义中用于将宏...

    基于seata+springboot的分布式事务项目源码.zip

    ### 用法 #### 1. 本地打包 ```shell script mvn package install -U -DskipTests ``` #### 2. 在项目中引入依赖包 ```xml <groupId>cn.caohd</groupId> <artifactId>seata-async <version>0.1.0-SNAPSHOT ...

Global site tag (gtag.js) - Google Analytics