代码备忘, TODO宏实现

我们平时在开发过程中, 往往并非憋足气一股脑敲完所有代码。每一个模块, 每一个函数的实现总有个先后顺序。

又或者哪个部分须要做调整, 改动… 所以, 我们须要有一个东西, 来提醒我们, 起到代码备忘功能, 避免某个功能忘记实现, 也能让我们高速定位。 所以这篇文章, 就是要实现一个TODO宏, 来达到代码备忘功能。

效果例如以下:



以下来分析下怎样实现这个宏


在实现TODO之前, 已经自带了几个预处理指令来实现报警/报错:

#warning Colin
#error Colin
#pragma message "Colin"
#pragma GCC warning "Colin"
#pragma GCC error "Colin"

效果例如以下:

既然有了, 那为什么还须要自己实现这个TODO宏呢?

  1. error 和 warning所代表的意义已经深入猿心, 我们没有理由使用它来做备忘。
  2. 假设也使用warning, 在警告导航栏中, 我们非常难区分哪个才是我们手动打的标记, 哪个是程序本身的warning
  3. 带#的预处理指令是无法被#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/

http://clang.llvm.org/docs/UsersManual.html

https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html

代码备忘, TODO宏实现的更多相关文章

  1. ffplay for mfc 代码备忘

    之前上传了一个开源播放器工程ffplay for mfc.它将ffmpeg项目中的ffplay播放器(ffplay.c)移植到了VC的环境下,并且使用MFC做了一套界面.它可以完成一个播放器播放视频的 ...

  2. TF版网络模型搭建常用代码备忘

    本文主要介绍如何搭建一个网络并训练 最近,我在写代码时经常碰到这样的情况,明明记得代码应该怎么写,在写出来的代码调试时,总是有些小错误.原因不是接口参数个数不对,就是位置不对.为了节约上网查找时间,现 ...

  3. ESlint 格式化代码 备忘

    vscode 代码格式化配置 vscode 菜单 文件->首选项->设置 --->进入扩展查找到ESlint,点击任一选项中的[在setting.json中配置],复制以下代码 { ...

  4. ASP.NET基础代码备忘

    使用ASP.NET原生的__doPostBack方法触发asp:Button //javaScript部分 __doPostBack('<%=btnAmountDivided.UniqueID ...

  5. Matlab代码备忘

    1.Matlab写入文件  set(hp1,'xdata',bbb(1,:),'ydata',bbb(2,:),'zdata',bbb(3,:)); M=size(bbb,2); name=strca ...

  6. CSS3 旋转代码备忘

    .Aclose { -webkit-transition-property: all; -webkit-transition-duration: .3s; -moz-transition-proper ...

  7. Qt Quick 简单教程 - 1 (代码备忘)

    qmlscene 未安装 由于出现上面的情况,我开始转战Windows 下学习,昨天安装好了Qt Sdk了,哟吼吼吼. mail.qml内容: import QtQuick 2.3 import Qt ...

  8. JS代码备忘

    function $(v) { if (typeof v === 'function') { window.onload = v; } else if (typeof v === 'string') ...

  9. Java线程池ExecutorService 代码备忘

    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5)创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待 p ...

随机推荐

  1. Java Date and Calendar examples

    Java Date and Calendar examples This tutorial shows you how to work with java.util.Date and java.uti ...

  2. 将逗号分隔的字符串与List互转

    将逗号分隔的字符串与List互转 方法 1: 利用JDK的Arrays类String str = "a,b,c";List<String> result = Array ...

  3. 我是跨域的JSONP

    1.出现原因:因为web中的同源策略(域名,协议,端口号)限制了跨域访问.   2.区别于json (个人理解)json是数据交换格式,jsonp是数据通信中的交互方式   3.jsonp的get与p ...

  4. U811.1接口EAI系列之五--材料出库--VB语言

    主要业务有:09其他出库单 11:材料出库单 32:销售出库单 主要业务代码: '材料出库生成XML Public Function xml_storeout(ds_head As MSHFlexGr ...

  5. 如何上传代码到github?

    如何上传代码到github? 首先你需要一个github账号,所有还没有的话先去注册吧! https://github.com/ 我们使用git需要先安装git工具,这里给出下载地址,下载后一路直接安 ...

  6. 大家来找茬:富连网今天中午抢购二手iPhone时网站无法访问的问题

    前几天在新闻区看到富士康卖二手iPhone的新闻,今天又看到说今天中午12点开抢.一大早就发现富连网无法访问了.前几天刚看到新闻的时候注册了个账号进去看了看,发现页面加载速度非常慢,今天中午基本无法打 ...

  7. 如何在 ASP.NET 中(服务器端)主动清除(HTTP内容响应时)浏览器中的 Cookies 数据

    这个 Cookies 设计的好坑...就不写进坑的过程了,直接贴最终解决代码: //清除 cookies 记录 foreach (var key in Request.Cookies.AllKeys) ...

  8. google云使用记录

    gcloud工具在win下安装十分不便,而且由于众所周知的原因,无法连接,我的解决办法就是安装另外一个vps(centos7系统),然后在那里安装gcloud工具,对google进行远程访问. 1.利 ...

  9. IOS UIView自动调整尺寸

    自动尺寸调整行为 当您改变视图的边框矩形时,其内嵌子视图的位置和尺寸往往也需要改变,以适应原始视图的新尺寸.如果视图的autoresizesSubviews属性声明被设置为YES,则其子视图会根据au ...

  10. HBase的Write Ahead Log (WAL) —— 整体架构、线程模型【转】

    转自:http://www.cnblogs.com/ohuang/p/5807543.html 解决的问题 HBase的Write Ahead Log (WAL)提供了一种高并发.持久化的日志保存与回 ...