modified: _posts/2015-11-17-my-oaths.md
[GalaxyBlog.git] / _posts / 2012-11-06-typechecking-macros.md
blob961f7433a929ea7ac78bf02054f61ddb3bd0a18d
1 ---\r
2 layout: post\r
3 title: "Typechecking tricks using macros in C"\r
4 tagline:\r
5 description: ""\r
6 category: Coding\r
7 tags: [C, ZT]\r
8 comments: true\r
9 ---\r
10 {% include JB/setup %}\r
12 短笔记一篇嗯…\r
14 事发于豆瓣上的学习型友邻A Liutos君在前晚提出一个话题"要是C的宏对参数也有类型要求就好了", 然后学习型友邻B Fleuria叔果断告知了"Linux内核里的宏许多都加有类型检查的tricks". 然后菜逼小弟就在跟帖里学习涨姿势了= =….\r
16 在Linux内核的[kernel.h](http://lxr.free-electrons.com/source/include/linux/kernel.h#L568)里的`min(x, y)`就用到了类型检查的tricks:\r
18         #define min(x, y) ({                                \\r
19                 typeof(x) _min1 = (x);                  \\r
20                 typeof(y) _min2 = (y);                  \\r
21                 (void) (&_min1 == &_min2);              \\r
22                 _min1 < _min2 ? _min1 : _min2; })\r
24 需要注意的的地方是:\r
26 - typeof 是gcc extensions的特性,并不属于c标准. 这不禁让我很好奇如果用别的Non-gcc编译器(例如Intel C)来编译Linux kernel到底有多轻松/麻烦…\r
27 - 第三行里的trick是,如果代码里尝试將两个不同类型的指针进行比较,编译器会输出一条warning. 例如gcc就会输出`warning: comparison of distinct pointer types lacks a cast`. \r
29 假如你很确定不需要严格的检查类型,就可以用[kernel.h](http://lxr.free-electrons.com/source/include/linux/kernel.h#L632)里_t结尾的macro,自己指定参数的类型\r
31         #define min_t(type, x, y) ({                        \\r
32                 type __min1 = (x);                      \\r
33                 type __min2 = (y);                      \\r
34                 __min1 < __min2 ? __min1: __min2; })\r
36 文本替换就是方便…\r
38 最后就随手帖拯救懒人嗯…(disqus, jekyll和gist间的相性貌似很差的赶脚= =)\r
39 [source link](https://gist.github.com/ZephyrSL/4022951#file-typechecking_macros-c)\r
40 {% highlight C %}\r
41 #include <stdio.h>\r
43 #define min_t(type, x, y) ({                        \\r
44         type __min1 = (x);                      \\r
45         type __min2 = (y);                      \\r
46         __min1 < __min2 ? __min1: __min2; })\r
48 /* generate warning if the types are unmatched: "comparison of distinct pointer types lacks a cast" */\r
49 #define min(x, y) ({                                \\r
50         typeof(x) _min1 = (x);                  \\r
51         typeof(y) _min2 = (y);                  \\r
52         void) (&_min1 == &_min2);              \ \r
53         _min1 < _min2 ? _min1 : _min2; })\r
56 int main(int argc, char const *argv[])\r
57 {\r
58   int a = 12;\r
59   unsigned b = 14;\r
60   printf("min_t: %d\n", min_t(int, a, b));\r
61   printf("min: %d\n", min(a, b));\r
62   return 0;\r
63 }\r
64 {% endhighlight %}\r
66 EOF\r