MACRO 和函数的故事 0
从前一直觉得 C 和 C-like 中的 MACRO 挺魔幻的,想着有空从更底层的层面看个明白。这学期在上单片机,用汇编讲的,课时还是蛮勤快地去上了好多节。stm8 的汇编虽然和 X86 还是有区别的,但是足够“触类旁通”了~
(涉猎甚浅,如有错误之处请一定指出,荣幸、谢谢 ^-^ )
预处理中的替换
It calls for a macro substitution of the simplest kind – subsequent occurrences of the token name will be replaced by the replacement text. — K&R
K&R 里面说了,MACRO 就是在预处理阶段的一种简单的文本替换,接下来里面举了个栗子:
#define max(A, B) ((A) > (B) ? (A) : (B))
这里定义一个取最大值的宏函数,是为 max(A, B)。
真如我们所知,预处理是在汇编之前,所以我们可以通过生成汇编来对比看下是怎么样的替换。
我把 max 写成了两个完整的程序,max.c 和 max_define.c:

然后用 gcc 编译,生成汇编,这里为了减少可能的复杂度关闭优化选项先:

最后用 diff 对比生成的两个汇编代码,可以发现二者确实没有差别,真如 K&R 所说的只是一种简单的文本替换。
在这个实例中,max_define.c 在预处理阶段,编译器发现有 “max(A,B)” 的地方便会把它套入 “((A)>(B)?(A):(B))” 这个模板上,然后变成一个完整的程序。
如果把编译器看成一个抄写员,那么 MACRO 的预处理就是你把 “max(A, B)” 这个 MACRO 定义好,在预处理阶段,抄写员他帮你去掉 MACRO 部分、把引用到 “max(A, B)” 的部分换成 “((A)>(B)?(A):(B))” 、把 A 和 B 替换成“真实”的数值,从而把 max_define.c 改写成为 max.c 的过程。
我们不妨看下生成的汇编码,事实证明 “max(A, B)” 并不是一个真正的函数,而整个 “_main” 中只调用了 “_printf” 这个函数:

函数呢
gcc max_function.c -S -O0
可以看到这里确实生成一个叫 “_max” 的函数,并且在 “_main” 中被调用了,这个过程比 MACRO 可要“复杂”不少呀:


MACRO 好么
这样看起来 MACRO 生成的汇编代码又少,甚至函数生成的二进制还要比 MACRO 生成的二进制大一些:

但是,“Everything has its price.”
摘《十日谈》
回家前那几天一直在伯父在住,没有网络,所以只能把看书来浪费时间,一口气把《十日谈》给看了。好久都没看这种故事书了,感觉很过瘾,书中也有不少值得思考的东西,并且由于写男女情爱较多,所以有些句子男士们不妨可以摘录下以后哄女生吼! ^_^
用爱解放人性,这是我对这书暂时的理解了。
摘
……
我犯的无非是与青春俱来的错,要免除这种过错,就得把青春一并免除。再说,如果老年人想起他们也有过年轻的时候,看到别人的缺点时也想想自己的缺点
……
青春之错青春偿之。
我们常见到这种情形:希望越是渺茫,爱情越是高涨,那个可怜的马夫也是如此。—— 第三天之二
好虐……
那些教会中人多半很蠢,不通人情世故,却自以为高人一等,什么事情都比别人懂得多,其实差得很远,因为他们的乐趣比一般人少,只能像猪一样把欲望限于吃喝。—— 第三天之三
“尊敬的夫人,你是明白人,一定早就看出你绝世的美貌使我景慕不已,神驰向往。你华贵的仪态和高尚的品德使任何男人折服,我的爱慕之情比任何男人更深切,更炽热,不是言语所能表达。只要我一息尚存,支持着这副躯壳,我的爱情不会泯灭。我死后,如果另一个世界也有男女情爱,我也将永远爱你。你可以相信,我的全部身心和我所有的一切都归你支配,世上一切事物,无论贵贱,只要是你想望的,我无不办到。凡是我能为你效劳的地方,你只消吩咐一声,或是由我自己去做,或是派人去做,我都把它当作莫大的恩惠。”—— 第三天之五
嗯嗯,摘录起来先~
我之骗你并没有害你之心,而是出于我对你的强烈爱情。—— 第三天之六
不管怎么样,还是骗了……
“爱情的力量不是我们所能抗拒的。”—— 第四天之一
啊,幸福的灵魂,你们在同一天里结束了炽热的爱情和尘世的生命。如果你们在同一个地方重新会聚就会更加幸福。如果另一个世界里也有爱情,如果你们像在人间那样在那里相亲相爱,那就无比幸福了!—— 第四天之七
夫人反驳道:“我的好兄弟,你们说的情况我很清楚,不过我嫁的是人,我宁愿要一个没有财富的男子汉而不要没有男子汉的财富。”—— 第五天之九
壮哉! -________-”
一般人爱嘲笑别人的丑事而不赞美别人的善行,尤其在那种丑事或善行和我们关系不大的时候。—— 第五天之十
因此,两位左右世界的女神常常把她们最好的东西隐藏在通常认为最卑贱的行业的阴影里,那些东西到了需要的时候才脱颖而出,显得更加光彩夺目。—— 第六天之二
你们都清楚,只要两厢情愿,事情很少有不成功的。—— 第七天之六
我们都了解,男人们总是得寸进尺,欲望永远没有满足的时候,沉湎于爱情的人尤其是这样。————第十天之四
人们虽然希望亲戚众多,兄弟兴旺,儿女成群,财产和仆役有增无已,可是稍有风吹草动,遇到一点小危险就会抛弃父母兄弟或主人,让他们陷于大难而不顾。但是好朋友之间却不会有背信弃义的情况。————第十天之八
在我见过的女人中间,无论从谈吐、举止、风度来说,她是最值得赞扬的,且不说美丽,因为美丽像鲜花,终究有凋谢的时候。————第十天之九
2B青年欢乐多
书中最好玩的故事都是发生在一个叫卡兰德里诺的画师身上的,一共讲了四个他的故事,都是被愚弄,而且由于他自己的愚昧而弄出不少笑话,用2B青年欢乐多形容这个人一点不为过…… o(*≧▽≦)ツ
比如他又一次被另外两个朋友和一个医生串通愚弄,从而相信了自己怀孕了(他是男滴……),然后脱口而出指责他的妻子:“这怎么得了!泰莎,全怪你,你总是喜欢趴在上面。我早就对你说过,要坏事的。”……咳咳,所以好玩的男青年们注意了……-________-”
绅士
书中可以称得上绅士的,真蒂尔.德.卡里森迪必须是第一个!他爱慕着一位地方长官夫人,但是由于他出身望族且品德高尚所以没有做成什么出格的事情。不幸的是不久那位夫人生了急性病去死了,去世的时候还有身孕。这位绅士出于对那位夫人的爱恋,在夜里就悄悄来到墓地里,居然发现夫人还有心跳,于是背回家好心照料,夫人居然复活了并且不久之后生下了宝宝。在人们都以为他会把夫人占为己有的时候,他却已把夫人当做自己的妹妹来照顾,并且坦然地把夫人送回了地方长官那里而得到人们的赞美。
本来这个事情放到现在也许没什么,但是这个故事被安排在第十天,而按照前面那些故事的“逻辑”,绅士把爱慕的夫人留下并不奇怪,所以故事的结果也算出人意料。也许这是作者在呼唤人性回归、解放的同时也期望美德吧。
[翻译]30周30位Linux 内核开发者——James Bottomley
James Bottomley是我们“30周30位Linux开发者”的第26位。他和我们分享了他的日常工作,他为什么对SCSI 邮件列表的人保持质疑,和为什么贝尔实验室(Bell Labs)的IT 部门最终同意他抛弃Windows 机器而使用Linux 。
姓名
James Bottomley
你在社区扮演什么角色,或者说你做哪一个子系统(subsystem)的工作?
我主要责职是SCSI 子系统的维护者。自从NCR voyager 系统以后我还有一个副职就是(维护)被淘汰和不为人爱的架构,这使我看起来像是PARISC 架构的维护者。
你的收入来源在哪呢?
Parallels。我是虚拟化(Server Virtualization)的CTO,所以我的日常工作和内核工作密切相关(我帮Parallels 将他们的容器技术(container technology))集成进内核。当然也涉及一些其他范围的开源(open source)。
你居住在哪里?为什么选择那呢?
伦敦(这是在英国,某人也时常回去美国)。因为我的妻子喜欢伦敦,而且它离莫斯科的路途较近,相对我以前住在芝加哥而说。
在软件开发方面你最喜欢的生产力工具(productivity tools)有哪些呢?你日常使用什么?
我想是git 和emacs ,用于代码开发。我使用Slitex 或者OpenOffice 的其中一个用于演示稿(slides)(我想我会有一个要用到投影仪的项目,尽管我还没有碰到)。我的桌面是openSUSE + Xfce
你是如何参与到Linux 内核开发的?
当我读研的时候我就开始关注它了。我们使用的SPARC 工作站(SPARC stations)价格是PC 的十倍,我想如果我们用一台SPARC 的价格去买10台Linux 系统(的机器)那我可以得到一台(那是在1993年,SlackWare 使用10张软盘来安装)。
我的第一个内核补丁实在 0.99.15 的时候:我们的分布式家庭环境(distributed home environment)使用了NFS,Linux 内核有一个NFS 的bug 会导致卡死(hang),我和同事修好了它。稍后我修改了用户空间内核模块加载程序(userspace kernel module loader),使它可以和ELF 工作,来帮助从a.out 到ELF 的过渡。我一直使用Linux 作为桌面(从1993年开始),除了在贝尔实验室(那里强制使用Windows)的几个星期。我经常在那使我的Windows 桌面崩溃,系统管理员才同意让我安装Linux 并以我不再不停呼叫他们为前提。我在内核开发上全面发力(serious foray)是在1998年,那时我移植Linux 到一个Voyager SMP 系统上,重写了x86 硬件访问层(x86 Hardware Access Layer)让它可以不依赖APICs 而工作。
是什么让你对此保持兴趣的?
事实是,那里经常有一些有趣的事情和一些在我日常技术领域之外、但是我感兴趣的东西冒出来(例如云存储(Containers in the cloud)或UEFI 安全启动(UEFI secure boot))。
在协同开发的过程中(collaborative development process)最让你感到欢乐的是什么?(嘴炮,蠢代码被提交,惊人的成就)?
对于协作开发过程既是优点也是缺点的就是任何人都可以做……甚至是一些没有丰富经验的人(甚至是常识)。为了使人信任,你得发出权威的声音。我曾经被用错误信息诠释权威的各色人等逗乐。然而,由于曾经有一个近乎糟糕(错误/困境)的情况在SCSI 的列表发生,一个不成熟(fledgling)的光纤通道(fibre channel)驱动严重出错(derailed),就因为作者听从了那些人的其中一个,(所以)我一直保持高度警惕、质疑他们。我在内核开发的演示中也有一个关于如何在邮件列表中鉴定一个人的话是否值得一听或者得忽略的部分。
对于入门开发者你有何建议?
找到一个困扰你的bug 并修好它。事实上,很多开发者就是这样开始的。秘诀就是找到对你来说重要的。找到那些对别人来说重要的通常不会有结果,因为你将不会对它有必要的激情和热爱(这是为什么我不完全信任TODO lists……如果对某人来说真的至关重要,那它已经被实现了)。
你写代码的时候都听什么?
《The sound of silence》。当我做一些不必思考的事情时(比如提交git patches 申请)我会听BBC 播客的《Radio 4》,但是我发现当我思考编程问题时,广播节目经常会使我分神。
你常去什么邮件列表(mailing list)或者 IRC 频道人们可以找到你的?会议呢?
oftc 上的#parisc 和 #storage 加上Vger上的linux-scsi 邮件列表。我完全不看Linux 内核邮件列表(LKML),所以不要只发送你的SCSI 补丁到那。过去五年,我去过的会议太多了,都是经过认真思考裁剪到最少的了……我参加的会议数量一直在增加……我想我需要帮助。
[翻译]30周30位Linux 内核开发者——Chris Mason
当我们即将结束“30周30位Linux 内核开发者”系列的时候,我们采访了Linux 内核开发者及Btrfs 维护者 Chris Mason。Chris 详谈了他的桌面和生产力工具,他喜爱的“超级嘴炮”和分享了他对参加内核开发的一些建议。
姓名
Chris Mason
你在社区扮演什么角色,或者说你做哪一个子系统(subsystem)的工作?
我维护着Btrfs 文件系统(filesystem),大多数工作是在文件系统或其他一些代码的IO 通道(IO paths)上。
你的收入来源在哪呢?
Fusion-io。
你居住在哪里?为什么选择那呢?
我住在纽约州罗切斯特(Rochester NY)。这是我上大学和从事Linux 方面工作的地方,我从来没打算离开。
在软件开发方面你最喜欢的生产力工具(productivity tools)有哪些呢?你日常使用什么?
我使用Arch Linux,最大的原因是滚动升级模式对日常主要工作(working against mainline)来说堪称完美。我使用awesome 作为窗口管理器而不是桌面环境。这对于管理大量窗口来说是个明智的做法。
我的开发工具都很基础,譬如vi 和 make。浏览内核代码方面,我还没有找到比cscope更好的,但我一直希望能有人集成一个实时更新(live uodating)的cscope 风格数据库(database)到vi 里面去。
我使用着mutt 来收发email,但我曾经同时或者逐个尝试过了所有的图形界面程序(gui programs)。他们都各有特色,但是mutt-kz 对notmuch 的整合为索引(index)和收发邮件提供了一个美好的解决方案。
Git是内核生产力中很大的一部分,并且你不能低估git 和内核工作流程(workflow)中有多少是围绕彼此设计的。每当我完成对一个git 新手的辅导时我都重新意识到所有各部分的活动是一个多么复杂的过程。
为了文件系统的分析(filesystem analysis),我写了一个叫seekwatcher 的工具。它使用了来自blktrace 的traces 来可视化地表现磁盘(disk)上正在发生什么,使找到(track)性能问题变得更容易。
我最近用C 代替Python 重写并作为一个叫iowatcher 的新工具,我希望加入所有可以监控闪存设备(flash devies)的新特性。
你是如何参与到Linux 内核开发的?
准确说不是内核开发,但在1994年,我开始为不被支持的显卡(graphics card)提供驱动。让自己的硬件工作那感觉很棒,我甚至还保留着SUSE 送出的作为给贡献者奖励的发行版CD (distro CDs)。
一些年以后,我成了一个系统管理员(systems administrator),我想在我们的数据中心(data center)使用Linux 。在哪个时候,Linux并没有一个日志文件系统(journaled filesystem),这是我在产品中使用Linux 不可或缺的。在此之前,我并没有存储设备(storage)或者内核的工作经历,所以搞定(figured out)这一些对我来说有一点艰难。
但是这是众望所归的特性之一,并且一路上我得到了很大的鼓励和帮助。在哪之后,我全职投入了内核开发。
是什么让你对此保持兴趣的?
我能够直接和用户交流,这意味着我可以及时在新特性(new features)上得到反馈并对此做出修正(fixes)。参加会议的时候,我经常遇到新的使用Linux 或者用Linux 工作的人。这是不断改进的创意和动力的不竭来源。
Linux 被不厌其烦地用于各种用途。
在协同开发的过程中(collaborative development process)最让你感到欢乐的是什么?(嘴炮,蠢代码被提交,惊人的成就)?
在外面的人看来,嘴炮似乎是件疯狂的事情。但是有时候,这些是修正(fixing)一些东西的重要一部分。经过长时间的争论,我们可以容易地发现导致问题的地方,坐下并做一个测试。测试结果让我们感到惊奇,以后我仍然会跑那个测试。如果不是因为特别想在争论中获胜,我也许不会花时间在测试上。
我最喜欢的绝对是关于O_PONIES 的嘴炮。甚至有人做了一件t-shirt 纪念它。我知道我没法在这里公正地阐述它,但是这一个很好的例子表明了,在开发者做出了难以达成的期望后我们应该做多大的妥协。
对于入门开发者你有何建议?
我的第一个建议是选择你自己喜欢使用(enjoy using)的一个项目。内核有一个曲直的学习曲线,并且很难按照你所想那样进入开发组(development group)。如果你喜欢你做的事情,你更有可能坚持下去。
然后,修bugs (fixing bugs)是了解代码的最快方法。选择你可以搞定(trigger reliably)的部分,这可以很容易就被找到。一遍又一遍如此循环,直到你对代码的了解足够你去检查(review)别人的补丁(patches)。届时你将对社区(community)有很好的了解,并引申到其他很多方面。
你写代码的时候都听什么?
我通常喜欢房间保持安静。
你常去什么邮件列表(mailing list)或者 IRC 频道人们可以找到你的?会议呢?
在freenode 上的#btrfs。会议呢,每年春天Linux Filesystem,Storage and MM 高层会议(the Linux Filesystem, Storage and MM Summit)都充满了有趣的话题。Linux 基金会(The Linux Foundation)在会议这方面一直做得很棒,在和我的日程没有冲突的情况下,我会尽量参加它们。
慢节奏生活
作为一个对装逼事业孜孜追求的人,有时经常要做出一个逆主流的姿态,于是最近我开始思考如何把当下遍地都是浮躁从我身上赶掉,思来想去,作为一个本来就有点急躁的人,想做到这点实在不易,于是只能从表面功夫做起,并希望以此最终达到目的,于是就有了“慢节奏生活”(或者说“慢生活”)这个伪命题。
以下我将从几个方面来阐述我对慢生活的理解和如何慢生活:
食
细嚼慢咽,应该是一个标准的慢生活中吃方面的表现。
我认为呢,慢吃首先得从食物的种类入手,像“快餐”这么反动的东西就不要提了,一餐食物的种类最好不要少于两种,应该要有汤。根据本人的经验,打菜是个麻烦的行为,经常要拘泥于“两个菜太少三个菜太多”的问题,菜的种类太少呢,总觉得不想是在吃饭,更别说是慢慢地、享受着地吃饭了。菜的种类要合适也并不是说一定要有肉有鱼什么的,全素菜也是可以的,但是两个蔬菜的种类、做法一定要不同,比如说一个是炒的,一个是煮的,一个是青菜,一个是瓜果类的。
至于要有汤呢,我觉得,好像在家吃饭都是这样的,这样吃也才能尽可能模拟出在家吃饭的感觉。当然,有烫的一餐饭是很不错的!
然后还有怎么吃,慢吃,那当然要慢慢吃。不能因为赶着做某事而狼吞虎咽。所以宁可早起10分钟,也要把早餐优雅地吃掉。吃饭的时候要集中精神(毕竟食堂提供的东西并不是装到你盆里就都是能吃的),想看电视这种事情最好不要,如果非要顺便做点娱乐,听下音乐不错,顺便把周围嘈杂的环境给忽略掉。吃饭时聊天呢,要看对象,最好就是那种喜欢说的,而不用你多说什么,而且说的话题你也愿意听的,也就是说你只需要做一个倾听者。
饮料方面呢,咖啡这种东西最好能不要就不要,咖啡在我身上表现的作用为即时提神。我只要和一点点地咖啡就会马上不犯困,这个和茶是不同的,我认为咖啡是“快醒”,而茶是“慢醒”,“快醒”的感觉就像是人醒了,但魂不在。而茶的“慢醒”就有点类似与自然醒。如果不是为了提神的,牛奶是最好的选择,比如在晚上睡前看书、盯屏幕时伴随一杯牛奶,会是很不错的。
住
这个可以笼统地称为“慢居”。我认为适合慢居的首先必须是一个安静地地方。像大学城这里,在广州来说可以说是慢居的一个相对适合的地方了(可惜是在大学里面,安宁被扰乱了不少)。其实居住的环境要干净、整齐。很容易想象,一个凌乱不堪的地方肯定会导致急躁的心理,从而带来快速而混乱的行为。对于这点我也是深有体会,下面的两张图片分别是我一个月前和现在的桌面,我差不多花了一整星期来整理我的宿舍,尝试让它看起来是整齐的,效果不错,我开始会在宿舍集中精神地做某些事情,而之前为了这种状态,我不得不跑去教室或者图书馆工作。


行
出行的方法绝对是慢生活的一个重要方面。步行、骑单车、地铁依次是建议选择的方式。前两个合适短途出行,而地铁作为城市内的较远出行选择。为什么不是公交呢,我只能说公交的用户体验太差了,而地铁至少让人感觉是平稳而流畅地,环境也相对要好,如果是半小时以上的车程,还可以考虑顺带上一本书看下。也是差不多的原因,长途出行的首选当然是火车,对于我对火车出行的如何喜爱,我就不细说了。
说到长途出行,不得不说得就是在年轻人中颇为流行的旅行了。曾经我也是一个旅行的追随者,但是慢慢得体会到了这种方式的不好之处。比如我曾经问自己为什么旅行并且思考这个问题。我想我是对一地之文化、一地之风景、一地之人感兴趣,所以我才会去那里了解下。也因为如此,我们都知道“路遥知马力,日久见人心”,如果我们只是匆匆而来,又匆匆而出,怎么可能对一地有正确的了解和认识,并且因此产生正确的思想。所以我的建议是在条件允许的情况下,用旅居代替旅行。旅居意味着你要在那里带上一段时间,可以是一个月,三月,半年,也许你会爱上那里,在那里逗留更长的时间。或者你可以把旅行比作一夜情,把旅居当做真正的恋情。读懂一个地方和读懂一个人是差不多的道理,因为喜欢,所以我们会花上很多的时间去了解,然后我们发现我们爱上了一个地方或者一个人(当然也有可能是相反的情况)。这么看来,只有旅居是比较符合我个人出行目的的方式了,而旅行就显得有点太匆忙、太快了。
读书
读书方面,最重要的一点就是拒绝文化快餐,我最反感看网络小说这种行为。我还有一个习惯就是“反流行”读书,比如当人们都跑去读《百年孤独》时,我在看鲁迅杂文。但人们都在追莫言的作品时,我才开始看马尔克的作品。这个并不是我刻意表现的标新立异,而是我认为,当很多人在追捧一种东西的时候,社会上肯定又各种嘈杂得声音,而这些声音会不可避免地影响你的阅读和思考,所以我选择反流行阅读。
还有一个就是多读经典,就我个人经常阅读的种类,一个是计算机方面的,一个是文学类的,那些经典的作品,可以说都是经得起时间考验的,不管什么时候都值得一读,并且可能以此受益更多,也就是说经典读物含金量较大,而且经过了流行到不流行的洗刷沉淀了下来。
通讯
这个从计算机上的说起,所以尽可能少用即时通讯,而用邮件代之,当然闲聊除外了。还有就是长资讯取代短资讯,像很流行的Twitter、微博这些都是短资讯的代表,资讯短,但信息量巨大,而且经常造成各种表达不明、不准确。而慢生活有一个追求就是慢而且有条不紊、做事按部就班。像微博这样的短资讯,经常给我们的生活带来大量无关的信息,不清无孔不入的信息经常打乱了我们的生活。而长资讯,常常能比较准确地表达作者的思想,比较适合有思考性、目的性的信息获取。
一个我觉得很值得提倡的就是,尽量用传统书信取代电子信息来和朋友交流。是不是现在的恋人都很少写情书了呢,这个我不是很清楚,但是不妨想象一下,当一份信被写下到寄出,肯定是作者经过了思考,在脑中形成思想,然后才用手写文字表达出来的,人的书写也是一种表达语言。当信被收到后,收信人也可以先不必即时给出答案,而往往是经过思考的,因为他们都知道一封信从寄出到被收取是要时间的,所以得尽量在每次通信中都包含尽可能多的有效性。类似地,这些也可以作为用电子邮件代替即时通讯的理由,特别是和别人讨论有价值的话题时。
顺便提一下书写这个事情,我觉得如果可能我甚至想尝试用回毛笔来书写日常的东西,顺便练回以前半途而废的书法。因为书法中对情感的表达绝对把普通的书写方式又提上了一个层面。
嗯,暂时我能想到和在做的关于慢节奏生活的就只有这些,或许仁者见仁、智者见智,但是不得不说地是,能听我啰嗦了这么多,看到这一行的朋友,应该不是急性子~
修改记录:
2012 年 12 月 8 日下午 10:02 首次发布

