代码备忘, TODO宏实现
代码备忘, TODO宏实现
我们平时在开发过程中, 往往并非憋足气一股脑敲完所有代码。每一个模块, 每一个函数的实现总有个先后顺序。
又或者哪个部分须要做调整, 改动… 所以, 我们须要有一个东西, 来提醒我们, 起到代码备忘功能, 避免某个功能忘记实现, 也能让我们高速定位。 所以这篇文章, 就是要实现一个TODO宏, 来达到代码备忘功能。
效果例如以下:

以下来分析下怎样实现这个宏
在实现TODO之前, 已经自带了几个预处理指令来实现报警/报错:
#warning Colin
#error Colin
#pragma message "Colin"
#pragma GCC warning "Colin"
#pragma GCC error "Colin"
效果例如以下:

既然有了, 那为什么还须要自己实现这个TODO宏呢?
- error 和 warning所代表的意义已经深入猿心, 我们没有理由使用它来做备忘。
- 假设也使用warning, 在警告导航栏中, 我们非常难区分哪个才是我们手动打的标记, 哪个是程序本身的warning
- 带#的预处理指令是无法被#define的, 也就是没办法直接利用这个来定义我们的TODO
好在C99提供了一个 _Pragma 运算符能够把部分#pragma指令字符串化, 例如以下:
#pragma message "Colin"
// 等价于
_Pragma("message \"Colin\"") // 须要注意双引號的转义
// 或
_Pragma("message(\"Colin\")") // 须要注意双引號的转义
利用这个特性。我们就能够将warning定义成宏:
#define MY_WARNING _Pragma("message (\"警察临检, 男左女右!\")")
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
MY_WARNING
}
效果例如以下:

到这里, 大体有那么一个感觉。
只是我们提示的内容, 是define的, 也就是写死固定的, 不太合适。
所以我们希望这个宏能接受入參, 让它正常显示到warning中。
这就涉及了一些宏的基本使用方法。
#define STRINGIFY(S) #S
#define PRAGMA_MESSAGE(MSG) _Pragma(STRINGIFY(message(MSG)))
STRINGIFY(S) 将入參转化成字符串,省去了_Pragma中全串加转义字符的困扰。
效果例如以下:

这时,一个基本功能的TODO宏就完毕了,以下向当中增加额外的信息:
// 两个已有的宏
#define STRINGIFY(S) #S
#define PRAGMA_MESSAGE(MSG) _Pragma(STRINGIFY(message(MSG)))
// 延迟1次展开的宏
#define DEFER_STRINGIFY(S) STRINGIFY(S)
// 以下的宏在第一行用`\`折行
#define FORMATTED_MESSAGE(MSG) "[TODO-" DEFER_STRINGIFY(__COUNTER__) "] " MSG " \n" \
DEFER_STRINGIFY(__FILE__) " line " DEFER_STRINGIFY(__LINE__)
当中涉及到的知识:
- 两个常量字符串能够拼接成一个整串 “123””456” => “123456”
- 使用到3个提前定义宏,COUNTER宏展开次数的计数器。全局唯一;FILE当前文件完整文件夹字符串;LINE在当前文件第几行
- 在字符串中提前定义宏应延时展开,假设将上面的DEFER_STRINGIFY换成STRINGIFY的话,如LINE不能被正确展开成行数。而是成了一个常量字符串”LINE”
- 为了美化,warning message中能够使用\n换行
于是,使用FORMATTED_MESSAGE(MSG)宏就能够将带文件路径、序号、行数等信息增加到终于的warning中。
事实上到这步已经OK了,为了让这个宏更加抢眼,还能够借鉴RAC,把宏定义成前面加@的形式:
#define KEYWORDIFY try {} @catch (...) {}
终于版本号
// 转成字符串
#define STRINGIFY(S) #S
// 须要解两次才解开的宏
#define DEFER_STRINGIFY(S) STRINGIFY(S)
#define PRAGMA_MESSAGE(MSG) _Pragma(STRINGIFY(message(MSG)))
// 为warning增加很多其它信息
#define FORMATTED_MESSAGE(MSG) "[TODO-" DEFER_STRINGIFY(__COUNTER__) "] " MSG " \n" DEFER_STRINGIFY(__FILE__) " line " DEFER_STRINGIFY(__LINE__)
// 使宏前面能够加@
#define KEYWORDIFY try {} @catch (...) {}
// 终于使用的宏
#define TODO(MSG) KEYWORDIFY PRAGMA_MESSAGE(FORMATTED_MESSAGE(MSG))
References
http://blog.sunnyxx.com/2015/03/01/todo-macro/
代码备忘, TODO宏实现的更多相关文章
- ffplay for mfc 代码备忘
之前上传了一个开源播放器工程ffplay for mfc.它将ffmpeg项目中的ffplay播放器(ffplay.c)移植到了VC的环境下,并且使用MFC做了一套界面.它可以完成一个播放器播放视频的 ...
- TF版网络模型搭建常用代码备忘
本文主要介绍如何搭建一个网络并训练 最近,我在写代码时经常碰到这样的情况,明明记得代码应该怎么写,在写出来的代码调试时,总是有些小错误.原因不是接口参数个数不对,就是位置不对.为了节约上网查找时间,现 ...
- ESlint 格式化代码 备忘
vscode 代码格式化配置 vscode 菜单 文件->首选项->设置 --->进入扩展查找到ESlint,点击任一选项中的[在setting.json中配置],复制以下代码 { ...
- ASP.NET基础代码备忘
使用ASP.NET原生的__doPostBack方法触发asp:Button //javaScript部分 __doPostBack('<%=btnAmountDivided.UniqueID ...
- Matlab代码备忘
1.Matlab写入文件 set(hp1,'xdata',bbb(1,:),'ydata',bbb(2,:),'zdata',bbb(3,:)); M=size(bbb,2); name=strca ...
- CSS3 旋转代码备忘
.Aclose { -webkit-transition-property: all; -webkit-transition-duration: .3s; -moz-transition-proper ...
- Qt Quick 简单教程 - 1 (代码备忘)
qmlscene 未安装 由于出现上面的情况,我开始转战Windows 下学习,昨天安装好了Qt Sdk了,哟吼吼吼. mail.qml内容: import QtQuick 2.3 import Qt ...
- JS代码备忘
function $(v) { if (typeof v === 'function') { window.onload = v; } else if (typeof v === 'string') ...
- Java线程池ExecutorService 代码备忘
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5)创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待 p ...
随机推荐
- How to compare dates in Java
How to compare dates in JavaBy mkyong | January 18, 2010 | Updated : November 15, 2016 | Viewed : 93 ...
- ReactNative 环境的搭建和启动(安卓版)
一.JAVA环境 下载 JDK 8.0 添加 %JAVA_HOME% 变量 添加 PATH:%JAVA_HOME%\bin 二.Android环境 下载 Android SDK 修复 SDK Mana ...
- zookeeper 的监控指标
一 应用场景描述 在目前公司的业务中,没有太多使用ZooKeeper作为协同服务的场景.但是我们将使用Codis作为Redis的集群部署方案,Codis依赖ZooKeeper来存储配置信息.所以做好Z ...
- linux杀掉tomcat应用进程。停止tomcat应用
ps -ef |grep tomcat |grep -v grep |awk '{print $2}' |xrags kill -9
- 复习下C 链表操作(单向循环链表、查找循环节点)
循环链表 稍复杂点. 肯能会有0 或 6 字型的单向循环链表. 接下来创建 单向循环链表 并 查找单向循环链表中的循环节点. 这里已6字型单向循环链表为例. //创建 循环链表 Student * ...
- 呃,如何使 .NET 程序,在 64位 系统 中,以 32位 模式运行。
其实最简单的方法就是在解决方案中,把平台设为 x86 就好了哈~ 但是今天遇到一个第三方的软件,它调用的一个 dll 是 32位 的,可能它没有测试过在 64位 系统下运行的情况,它在编译时是按默 ...
- 行为类模式(七):观察者(Observer)
定义 定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新. UML 优点 观察者和被观察者之间是松耦合的,分别可以各自独立改变. Subject在发送 ...
- RHEL7 富规则删除
1. 查看已经创建好的富规则 firewall-cmd --list-rich-rules 2. 删除富规则(******代表已经创建好的完整富规则内容) firewall-cmd --remove- ...
- iOS开发之二维码扫描
二维码扫描 01-导入系统库 02 新建继承自UIView的 LHQPreView 2.1导入系统库头文件 #import <AVFoundation/AVFoundation.h> 2. ...
- Is there a way to get a Cursor from a GreenDao Query object?
转:http://stackoverflow.com/questions/13584876/is-there-a-way-to-get-a-cursor-from-a-greendao-query-o ...