关于C语言的一些trick
很多东西已经记不起来了,想到一点写一点,碰到一点写一点,慢慢累积。
关于#
#在宏定义中用于替换传入变量的字符,例如: #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的更多相关文章
- 编写高质量代码 改善Python程序的91个建议 (读后 小记)
此书是自己好久之前买的,当时总觉得Python语言中有各种trick, 总是要自己猝不及防的掉入到陷阱之中, 看了一些资料后发现了这本书,感觉很是不错,不过可惜自己平时总是杂事太多,总是找不到整块的时 ...
- C语言全局变量那些事儿
转自:http://blog.csdn.net/bingqingsuimeng/article/details/9405743 作为一名程序员,如果说沉迷一门编程语言算作一种乐趣的话,那么与此同时反过 ...
- C语言printf()函数:格式化输出函数
C语言printf()函数:格式化输出函数 头文件:#include <stdio.h> printf()函数是最常用的格式化输出函数,其原型为: int printf( char ...
- 漫谈C语言及如何学习C语言
抄自:http://my.oschina.net/apeng/blog/137911 目录:[ - ] 为什么要学习C语言? C语言学习方法 1,参考书籍 2,动手实验环境搭建 3,网络资源 附录 一 ...
- C语言 goto, return等跳转
C语言 goto, return等跳转 Please don't fall into the trap of believing that I am terribly dogmatical about ...
- [转贴]漫谈C语言及如何学习C语言
抄自http://my.oschina.net/apeng/blog/137911,觉得很有用,收藏它 目录:[ - ] 为什么要学习C语言? C语言学习方法 1,参考书籍 2,动手实验环境搭建 3, ...
- 文本挖掘预处理之向量化与Hash Trick
在文本挖掘的分词原理中,我们讲到了文本挖掘的预处理的关键一步:"分词",而在做了分词后,如果我们是做文本分类聚类,则后面关键的特征预处理步骤有向量化或向量化的特例Hash Tric ...
- 基于python语言的tensorflow的‘端到端’的字符型验证码识别源码整理(github源码分享)
基于python语言的tensorflow的‘端到端’的字符型验证码识别 1 Abstract 验证码(CAPTCHA)的诞生本身是为了自动区分 自然人 和 机器人 的一套公开方法, 但是近几年的 ...
- C语言函数实现的另类方法
在前面看过那个BT的Javascript程序后,我们来看一个C语言的,相信大家还记得输出从1到1000的数最后的那个示例,本站还有很多这样的示例,如:变态的hello word,如何教新手编程,还有恐 ...
随机推荐
- 初学mongodb笔记
先下载下mongodb,这里官网下载,https://www.mongodb.com/download-center?jmp=nav,根据自己的系统选择下载, 然后解压一下:会有这个文件夹\mongo ...
- String使用机制及string.equals()和==的区别(转)
http://904582819.blog.163.com/blog/static/11159282020127794456840/ equals方法和==的区别 首先大家知道,String既可以 ...
- JDK8+Dubbo2.5.2实践
几年前就听说过Dubbo的大名,今天由于工作需要,研究一下. 从网上找了一篇文章,非常靠谱,并且提供了简单的示例代码,基本上可以跑起来. 文章地址: http://www.cnblogs.com/Ja ...
- Android之如何使用JUnit进行单元测试
转的:http://www.blogjava.net/qileilove/archive/2014/05/19/413824.html Android中如何使用JUnit进行单元测试 在我们日常开发a ...
- .net dataGridView当鼠标经过时当前行背景色变色;然后【给GridView增加单击行事件,并获取单击行的数据填充到页面中的控件中】
1.首先在前台dataGridview属性中增加onRowDataBound属性事件 2.然后在后台Observing_RowDataBound事件中增加代码 protected void Obser ...
- Github注册过程
一 github注册过程: 1.首先百度github官网,进入官网页面 2.在该页面分别输入昵称,昵称需要不和别人的重复,而后输入邮箱地址,该邮箱不能注册过这个网站,最后输入密码,密码至少要有七个 ...
- iShare.js分享插件
iShare.js是一个小巧的分享插件,纯JS编写,不依赖任何第三方库,使用简便. 为啥写这个插件? 因为在搭建个人blog时(还没有搭建好(¯﹃¯)),对目前国内比较受欢迎的分享插件都不太满意,主要 ...
- 第10章 嵌入式Linux的调试技术
printk函数运行在内核空间,printf函数运行在用户空间.也就是说像Linux驱动这样的Linux内核程序只能使用printk函数输出调试信息.printk函数在控制台(也称终端)显示消息是通过 ...
- AJAX实现异步登录
//代码较为简单,只是测试所用 1.html登录页面代码 <table> <tr> <td>用户名:</td> <td><input ...
- @SuppressWarnings("finally")
@SuppressWarnings.该批注的作用是给编译器一条指令,告诉它对被批注的代码元素内部的某些警告保持静默. 批注允许您选择性地取消特定代码段(即,类或方法)中的警告.其中的想法是当您看到 ...