很多东西已经记不起来了,想到一点写一点,碰到一点写一点,慢慢累积。

关于#

#在宏定义中用于替换传入变量的字符,例如: #define whole_operation(n)   do { printf(#n "=%d\n", (n));} while(0);

调用whole_operation(5*6), 输出:5*6=30, 有助于增加输出的可读性。

关于##

##是c99中定义的用于粘连两个符号,标识符或参数。例如:#define name_index(index)  name_##index

调用name_index(1),则生成name_1变量, 所以很多时候##用于动态的调用标识符具有一定规律的函数,宏或者变量。

举个列子,如果现在有add_arg_1(), add_arg_2()两个函数,只有在运行时才知道调用哪个函数,那么可以使用如下代码:

#define call_add_arg(argc)    add_arg_##argc()

IPnet的log模块中,因为log级别不同而log级别的前几个标识符都是IPCOM_LOG_,所以采用IPCOM_LOG_##x的方式在运行是判断需要输出什么级别的log。

关于不定参数...

很久以前在防火墙上做log模块的时候,用到一个比较有意思的trick。因为log要接收不同模块的不同信息,但是每个模块都含有自己独特的信息,为了保证所有信息都能被log接受,当时用了不定参的函数作为log的接口log(msgid, ...),通过va_list ap; va_start(ap, firstarg); va_arg(ap, type);va_end(ap);的方式来接受传入的各个参数。事实上,大多数prinf也是通过这个方式实现。 但是这种方式的函数调用容易出问题, 函数不知道什么时候参数结束,有可能导致程序崩溃。

C99定义了__VA_ARGS__ 用于接受不定参数的宏:#define LOG(msgid, ...)  log(msgid, __VA_ARGS__, lastarg) 或者#define LOG(msgid, arg...)  log(msgid, arg, lastarg)  lastarg是预定义的用于标识结束的宏或变量, 若不用__VA_ARGS__,则需用arg...来替代。 这样,LOG函数就可以接受任意多1个以上参数而不需要关系什么时候结束。那么如果LOG调用时只有一个msgid参数,就会变成log(msgid,,lastarg),这时候就需要借助##的另一个作用,如果##,后面没有参数,那么逗号就会被省略,于是LOG函数的最终定义变成: #define LOG(msgid, ...)  log(msgid, ##__VA_ARGS__, lastarg) 

关于C语言的一些trick的更多相关文章

  1. 编写高质量代码 改善Python程序的91个建议 (读后 小记)

    此书是自己好久之前买的,当时总觉得Python语言中有各种trick, 总是要自己猝不及防的掉入到陷阱之中, 看了一些资料后发现了这本书,感觉很是不错,不过可惜自己平时总是杂事太多,总是找不到整块的时 ...

  2. C语言全局变量那些事儿

    转自:http://blog.csdn.net/bingqingsuimeng/article/details/9405743 作为一名程序员,如果说沉迷一门编程语言算作一种乐趣的话,那么与此同时反过 ...

  3. C语言printf()函数:格式化输出函数

    C语言printf()函数:格式化输出函数 头文件:#include <stdio.h> printf()函数是最常用的格式化输出函数,其原型为:     int printf( char ...

  4. 漫谈C语言及如何学习C语言

    抄自:http://my.oschina.net/apeng/blog/137911 目录:[ - ] 为什么要学习C语言? C语言学习方法 1,参考书籍 2,动手实验环境搭建 3,网络资源 附录 一 ...

  5. C语言 goto, return等跳转

    C语言 goto, return等跳转 Please don't fall into the trap of believing that I am terribly dogmatical about ...

  6. [转贴]漫谈C语言及如何学习C语言

    抄自http://my.oschina.net/apeng/blog/137911,觉得很有用,收藏它 目录:[ - ] 为什么要学习C语言? C语言学习方法 1,参考书籍 2,动手实验环境搭建 3, ...

  7. 文本挖掘预处理之向量化与Hash Trick

    在文本挖掘的分词原理中,我们讲到了文本挖掘的预处理的关键一步:"分词",而在做了分词后,如果我们是做文本分类聚类,则后面关键的特征预处理步骤有向量化或向量化的特例Hash Tric ...

  8. 基于python语言的tensorflow的‘端到端’的字符型验证码识别源码整理(github源码分享)

    基于python语言的tensorflow的‘端到端’的字符型验证码识别 1   Abstract 验证码(CAPTCHA)的诞生本身是为了自动区分 自然人 和 机器人 的一套公开方法, 但是近几年的 ...

  9. C语言函数实现的另类方法

    在前面看过那个BT的Javascript程序后,我们来看一个C语言的,相信大家还记得输出从1到1000的数最后的那个示例,本站还有很多这样的示例,如:变态的hello word,如何教新手编程,还有恐 ...

随机推荐

  1. web 页面上纯js实现按钮倒计数功能

    需求构思:本功能想实现的是,一个按钮在页面载入就显示提醒续费,,,倒数60秒后,完成提醒功能,可以按另外一个页面跳转到主页. 参考网上的大神,实现如下:Button2倒数,Button3跳转,在页面上 ...

  2. window下安装jupyter

    1.Install [Anaconda](https://docs.continuum.io/anaconda/install#anaconda-install) 实际上安装了anaconda就已经安 ...

  3. 第十章 嵌入式Linux的调试技术

    对调试工具进行简介.Linux中提供了一类工具,通过这些工具可以逐行跟踪程序的代码,用于测试用户空间程序的gdb.gdbserver和调试内核空间程序的kgdb. 用gdb调试用户空间程序:gdb可跟 ...

  4. lucene5学习 - 索引基本操作(创建,查询,更新,删除,分页)

    package lucene5; import java.io.IOException; import java.nio.file.Paths; import java.text.SimpleDate ...

  5. javascript学习之【new操作符】

    首先请大家思考这么一段代码,如下: <script>var jquery=function(){     console.log(this);};jquery();new jquery() ...

  6. html基础01

    一.HTML 基础 1.HTML基础标签:<head> <bady> <tittle>XXX<tittle>:为标签 2.HTML标题 <h1&g ...

  7. TCPCopy使用

      http://www.thinkingbar.com/2014/04/17/tcpcopy使用/ 主题 技术 一.应用背景 主要用于系统的稳定性测试.它可以复制线上服务器的请求,通过修改TCP/I ...

  8. oracle xmltype导入并解析Excel数据 (三)解析Excel数据

    包声明 create or replace package PKG_EXCEL_UTILS is -- Author: zkongbai-- Create at: 2016-07-06-- Actio ...

  9. 关于JAVA的数据转换总结

    数据转换在编程里面是十分常用的,将平常可能用到的数据转换类型总结起来会在以后码代码的过程中有很大帮助. 在数据转换之前,需要明白的是基础数据类型的自动转换和强制转换.接下来就先从数据类型的容量讲起. ...

  10. jQuery.pager无刷新分页

    刚刚学习前端的时候,需要一个无刷新的分页功能,找了一个不错的,大家也有很大分享,在这里写一个自己的部分代码,前后端都有,需要的小伙伴可以参考一下,代码不是完整的. 直接上伪代码<样式代码省略,部 ...