<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type='text/xsl' href='http://superding.spaces.live.com/mmm2008-07-24_12.50/rsspretty.aspx?rssquery=en-US;http%3a%2f%2fsuperding.spaces.live.com%2fcategory%2f%e7%bc%96%e7%a8%8b%2ffeed.rss' version='1.0'?><rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:msn="http://schemas.microsoft.com/msn/spaces/2005/rss" xmlns:live="http://schemas.microsoft.com/live/spaces/2006/rss" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>猪哥的Blog: 编程</title><description /><link>http://superding.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&amp;_c=BlogPart&amp;partqs=cat%25E7%25BC%2596%25E7%25A8%258B</link><language>en-US</language><pubDate>Sat, 16 Aug 2008 06:59:20 GMT</pubDate><lastBuildDate>Sat, 16 Aug 2008 06:59:20 GMT</lastBuildDate><generator>Microsoft Spaces v1.1</generator><docs>http://www.rssboard.org/rss-specification</docs><ttl>60</ttl><cf:parentRSS>http://superding.spaces.live.com/blog/feed.rss</cf:parentRSS><live:type>blogcategory</live:type><live:identity><live:id>-8509478205381187897</live:id><live:alias>superding</live:alias></live:identity><cf:listinfo><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="typelabel" label="Type" /><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="tag" label="Tag" /><cf:group element="category" label="Category" /><cf:sort element="pubDate" label="Date" data-type="date" default="true" /><cf:sort element="title" label="Title" data-type="string" /><cf:sort ns="http://purl.org/rss/1.0/modules/slash/" element="comments" label="Comments" data-type="number" /></cf:listinfo><item><title>Megatops BinCalc日后的发布地址</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1632.entry</link><description>因为GooglePages看上去没啥解封的希望，所以我把转正了的BinCalc提交到Softpedia去了。不过这个Softpedia确实挺赞的，反应迅速，并且真的把东西跑了一把有检查过。至少上面的截图不是我提交的那个是他们自己跑了截的。&lt;br&gt;
&lt;br&gt;
试验了一下，国内能正常访问和下载：&lt;a target="_blank" href="http://www.softpedia.com/get/Science-CAD/Megatops-BinCalc.shtml"&gt;http://www.softpedia.com/get/Science-CAD/Megatops-BinCalc.shtml&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
另外，100％ Clean！&lt;br&gt;
&lt;a href="http://www.softpedia.com/progClean/Megatops-BinCalc-Clean-106862.html"&gt;&lt;img src="http://www.softpedia.com/images/spyward/softpedia_clean_award_f.gif" alt=""&gt;&lt;/a&gt; &lt;br&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+Megatops+BinCalc%e6%97%a5%e5%90%8e%e7%9a%84%e5%8f%91%e5%b8%83%e5%9c%b0%e5%9d%80&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1632.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1632.entry</guid><pubDate>Sat, 16 Aug 2008 06:58:08 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1632/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1632.entry#comment</wfw:comment><dcterms:modified>2008-08-16T06:59:20Z</dcterms:modified></item><item><title>Megatops BinCalc 1.0.0正式版发布</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1626.entry</link><description>随着最后一个IPv4地址显示功能的加入，我的Megatops BinCalc终于完整实现了我最初写在Feature List里的所有功能。因此我决定从这个版本开始为BinCalc转正，正式设置版本号为1.0.0。&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm4.static.flickr.com/3207/2749259908_feb9b3c954_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;相对于上次发布的v0.2f版的改进主要有：&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
位指示器增加了2^n提示功能。显示位的Tool-tip的时候除了显示位序号还同时显示对应的2^n值。在设置一些基址寄存器或者调试CPU的MMU TLB表项的时候这个功能很方便：&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm4.static.flickr.com/3178/2749260054_f12fc753d1_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
ASCII字符显示增加输入功能。原本我增加ASCII Char显示功能纯粹是因为界面里面右边那块实在是太空了不知道该放点什么，还以为不可能有人用这种功能的。不过前几天有个鬼佬强烈建议俺增加ASCII输入功能，因为他居然用BinCalc来调试某种基于字节流的通讯应用(￣口￣)!!。所以俺想了想估计那些经常做串口之类驱动的有可能还需要这个功能，于是就一块加上了。使用Tab键或者双击ASCII显示可以将输入焦点（黄色背景高亮）转移过去，然后敲键盘就可以了。因为是面向字节流调试的，所以Char输入是这个计算器里面唯一不在溢出时阻止输入的地方。你可以连续不断地往里面敲字母，BinCalc将字节输入按照FIFO原则处理。&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm4.static.flickr.com/3134/2748424163_75d2327f24_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
最后增加的一个功能就是IPv4地址显示和输入。在界面设计的时候我真是绞尽脑汁，最终使用了复用二进制数显示区的办法来硬是挤进了这个功能（这个功能迟迟没有弄主要是因为界面原因）。因为根据我个人经验，如果你要算得是IP掩码那用位指示器就已经足够了，根本懒得去看那一大串0和1。&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm4.static.flickr.com/3112/2749260016_7e8b0ab690_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
IP地址的输入方式也很伤脑筋，因为我很不想用Windows标准的那种文本框输入。最终我设计和实现的这个输入方式还是与计算器的输入方式统一了：输入的时候IP地址从低位往高位涨。IP地址只能用键盘输入，使用感觉与BinCalc其他进制的输入方式统一，用起来感觉挺好的也不会觉得怪怪的。&lt;br&gt;
&lt;br&gt;
IP操作主要是用于IP报文解析调试或者是计算IP地址掩码的时候。但是我自己用了一阵子后很快就用IP显示取代了原来的二进制数显示了：因为IPv4地址点分十进制的显示方式正好直观地显示了32bit整型中每个字节的十进制形式，结合右边的ASCII字符显示可以让你直接看到每个字符的十进制Code。&lt;br&gt;
&lt;br&gt;
在我的盒子里面可以找到最新版本的下载。另外我也给BinCalc做了个官方主页：&lt;a href="http://bincalc.googlepages.com"&gt;http://bincalc.googlepages.com&lt;/a&gt;。主页是鸟语的，没打算做中文版。因为Google Pages被GFW捂得十分严实，中文版做了也白做～～ &lt;br&gt;&lt;br&gt;&lt;span style="color:rgb(192, 0, 0)"&gt;★ 2008年8月11日星期一：发现之前上传盒子的版本弄错了，盒子上的不是最终版本。最终版本版本号为：1.0.0.166。已经下载了的麻烦再检查一下。&lt;/span&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+Megatops+BinCalc+1.0.0%e6%ad%a3%e5%bc%8f%e7%89%88%e5%8f%91%e5%b8%83&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1626.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1626.entry</guid><pubDate>Sun, 10 Aug 2008 08:45:14 GMT</pubDate><slash:comments>2</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1626/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1626.entry#comment</wfw:comment><dcterms:modified>2008-08-11T05:16:58Z</dcterms:modified></item><item><title>长得很Win的gVIM</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1492.entry</link><description>今晚配置了一把Windows版的gVIM，现在长得很Modern了～～&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm4.static.flickr.com/3113/2641438238_45416b8365_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
看起来已经彻底像是个Windows下的编辑器了吧(#￣▽￣#) &lt;br&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+%e9%95%bf%e5%be%97%e5%be%88Win%e7%9a%84gVIM&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1492.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1492.entry</guid><pubDate>Sat, 05 Jul 2008 16:20:49 GMT</pubDate><slash:comments>6</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1492/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1492.entry#comment</wfw:comment><dcterms:modified>2008-07-06T05:07:56Z</dcterms:modified></item><item><title>几款TTF等宽字体秀</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1407.entry</link><description>今天整理字体，翻出了俺收藏的这些等宽TTF矢量字体（点阵字俺一直用俺的DIY作品，无视其他(￣^￣)）。大家有兴趣可以看看弄来试试。以下都是SlickEdit 2008中11pt字号的显示效果，按照字母顺序排序。字体都是Google来的，自己可以找到。&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm4.static.flickr.com/3274/2555584972_a3b4fc3984_o.png" alt=""&gt;&lt;br&gt;&lt;br&gt;&lt;img src="http://farm4.static.flickr.com/3059/2555585108_1ed1126d3e_o.png" alt=""&gt;&lt;br&gt;&lt;br&gt;
 &lt;img src="http://farm4.static.flickr.com/3053/2554759259_84fd3a1af2_o.png" alt=""&gt;&lt;br&gt;&lt;br&gt;&lt;img src="http://farm4.static.flickr.com/3263/2555585246_41df59b1e4_o.png" alt=""&gt;&lt;br&gt;&lt;br&gt;
&lt;img src="http://farm4.static.flickr.com/3091/2555584830_e9cb40e25a_o.png" alt=""&gt;&lt;br&gt;&lt;br&gt;
&lt;img src="http://farm4.static.flickr.com/3151/2554955057_f56573beb9_o.png" alt=""&gt;&lt;br&gt;&lt;br&gt;
&lt;img src="http://farm4.static.flickr.com/3155/2555585386_4a29d4e28a_o.png" alt=""&gt;&lt;br&gt;&lt;br&gt;
&lt;img src="http://farm4.static.flickr.com/3095/2554759495_d9bfba1b8c_o.png" alt=""&gt;&lt;br&gt;&lt;br&gt;&lt;img src="http://farm4.static.flickr.com/3257/2555585486_1a909236e5_o.png" alt=""&gt; &lt;br&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+%e5%87%a0%e6%ac%beTTF%e7%ad%89%e5%ae%bd%e5%ad%97%e4%bd%93%e7%a7%80&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1407.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1407.entry</guid><pubDate>Fri, 06 Jun 2008 05:16:12 GMT</pubDate><slash:comments>6</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1407/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1407.entry#comment</wfw:comment><dcterms:modified>2008-06-06T07:33:24Z</dcterms:modified></item><item><title>Megatops ProCoder Font字体主页上线</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1154.entry</link><description>文字部分以前就写好了，今晚终于下定决定放到Google Pages上去了。不过这不意味着我接着会开始积极更新这套字体了——相反，新的开发任务又要开始，我这只是赶着最后一个清闲的晚上，把最后还没放上来的东西放上来罢了(╯﹏╰)。估计在之后的好几个月，可能都不会再有什么空闲时间来维护更新这套字体了。如果各位有什么不满意的地方，就先忍着吧～～忍个半年等我缓过劲来了，俺就会回来更新了～～&lt;br&gt;
&lt;br&gt;
页面位置：&lt;a href="http://zhaojie.ding.googlepages.com/megatopsprocoderfont"&gt;http://zhaojie.ding.googlepages.com/megatopsprocoderfont&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
感谢简单好用的Google Pages，在我的个人主页空间没掉4年以后让我再次有了向网上挂页面的动力～～&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+Megatops+ProCoder+Font%e5%ad%97%e4%bd%93%e4%b8%bb%e9%a1%b5%e4%b8%8a%e7%ba%bf&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1154.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1154.entry</guid><pubDate>Tue, 04 Mar 2008 16:14:20 GMT</pubDate><slash:comments>3</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1154/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1154.entry#comment</wfw:comment><dcterms:modified>2008-03-04T16:14:20Z</dcterms:modified></item><item><title>猪哥的Megatops ProCoder 1.0字体新品发布</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1141.entry</link><description>因为自己时不时也用用Ultraedit、EmEditor、EditPlus这样的编辑器，发现原来的ProCoder字体覆盖了128－255编码范围和中文字体冲突在这些不能正确计算宽度的编辑器里面确实还是挺麻烦的。所以简单裁剪了一个仅包含0－127范围的Lite版Megatops ProCoder字体。可以正常调用宋体显示全角引号、单引号、省略号等。当然，128及以上的西欧字符被裁掉了，所以这个版本无法正确显示德文和法文。如果你有这种需要就得使用没有裁过的完整版。所以我是建议你两个版本都安装，在类似于EmEditor这种能够为不同字符集指定字体的编辑器里面就可以无痛切换。&lt;br&gt;
&lt;br&gt;
以下是在EditPlus中Lite版本的显示效果，因为已经完全裁掉了0x7F以上的字符，所以全角符号完全由中文宋体支持：&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm3.static.flickr.com/2037/2293181653_2ea8077dee_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
和原来的Full版可以共存，直接安装即可。点击&lt;a href="http://zhaojie.ding.googlepages.com/MegatopsProCoder1.0Lite.fon"&gt;这里下载&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color="#333333"&gt;★ Megatops ProCoder正如其名：仅仅面向有长时间编码或屏幕代码阅读需求的专业程序员设计，不明白其设计目的的麻烦绕行～～&lt;/font&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+%e7%8c%aa%e5%93%a5%e7%9a%84Megatops+ProCoder+1.0%e5%ad%97%e4%bd%93%e6%96%b0%e5%93%81%e5%8f%91%e5%b8%83&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1141.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1141.entry</guid><pubDate>Tue, 26 Feb 2008 13:41:33 GMT</pubDate><slash:comments>8</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1141/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1141.entry#comment</wfw:comment><dcterms:modified>2008-02-26T13:41:33Z</dcterms:modified></item><item><title>C语言的inline</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1137.entry</link><description>&lt;div&gt;
&lt;div&gt;转以前我用Docbook写的一篇关于C语言inline关键字使用的文章。唉，要是能用docbook直接写Blog就好了。用得越多发现Docbook这个东西真是越好用啊～～&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;本文介绍了GCC和C99标准中inline使用上的不同之处。inline属性在使用的时候，要注意以下两点：&lt;/div&gt;
&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;inline关键字在GCC参考文档中仅有对其使用在函数定义（Definition）上的描述，而没有提到其是否能用于函数声明（Declare）。
&lt;p&gt;从inline的作用来看，其放置于函数声明中应当也是毫无作用的：inline只会影响函数在translation unit（可以简单理解为C源码文件）内的编译行为，只要超出了这个范围inline属性就没有任何作用了。所以inline关键字不应该出现在函数声明中，没有任何作用不说，有时还可能造成编译错误（在包含了sys/compiler.h的情况下，声明中出现inline关键字的部分通常无法编译通过）；
&lt;li&gt;
&lt;p&gt;inline关键字仅仅是&lt;span&gt;&lt;strong&gt;建议&lt;/strong&gt;&lt;/span&gt;编译器做内联展开处理，而不是强制。在gcc编译器中，如果编译优化设置为-O0，即使是inline函数也不会被内联展开，除非设置了强制内联（&lt;code&gt;__attribute__((always_inline))&lt;/code&gt;）属性。&lt;/ol&gt;&lt;/div&gt;
&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3&gt;&lt;a&gt;&lt;/a&gt;1. GCC的inline&lt;/h3&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;gcc对C语言的inline做了自己的扩展，其行为与C99标准中的inline有较大的不同。
&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4&gt;&lt;a&gt;&lt;/a&gt;1.1. static inline&lt;/h4&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;GCC的static inline定义很容易理解：你可以把它认为是一个static的函数，加上了inline的属性。这个函数大部分表现和普通的static函数一样，只不过在调用这种函数的时候，gcc会在其调用处将其汇编码展开编译而不为这个函数生成独立的汇编码。除了以下几种情况外：
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;函数的地址被使用的时候。如通过函数指针对函数进行了间接调用。这种情况下就不得不为static inline函数生成独立的汇编码，否则它没有自己的地址。
&lt;li&gt;
&lt;p&gt;其他一些无法展开的情况，比如函数本身有递归调用自身的行为等。&lt;/ul&gt;&lt;/div&gt;
&lt;p&gt;static inline函数和static函数一样，其定义的范围是local的，即可以在程序内有多个同名的定义（只要不位于同一个文件内即可）。
&lt;div style="margin-left:0.5in;margin-right:0.5in"&gt;
&lt;table summary=Note border=0&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=top align=middle width=25 rowspan=2&gt;
&lt;th align=left&gt;注意
&lt;tr&gt;
&lt;td valign=top align=left&gt;
&lt;p&gt;gcc的static inline的表现行为和C99标准的static inline是一致的。所以这种定义可以放心使用而没有兼容性问题。
&lt;p&gt;&lt;span&gt;&lt;strong&gt;要点：&lt;/strong&gt;&lt;/span&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;gcc的static inline相对于static函数来说只是在调用时建议编译器进行内联展开；
&lt;li&gt;
&lt;p&gt;gcc不会特意为static inline函数生成独立的汇编码，除非出现了必须生成不可的情况（如通过函数指针调用和递归调用）；
&lt;li&gt;
&lt;p&gt;gcc的static inline函数仅能作用于文件范围内。&lt;/ul&gt;&lt;/div&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4&gt;&lt;a&gt;&lt;/a&gt;1.2. inline&lt;/h4&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;相对于C99的inline来说，GCC的inline更容易理解：可以认为它是一个普通全局函数加上了inline的属性。即在其定义所在文件内，它的表现和static inline一致：在能展开的时候会被内联展开编译。但是为了能够在文件外调用它，gcc一定会为它生成一份独立的汇编码，以便在外部进行调用。即从文件外部看来，它和一个普通的extern的函数无异。举个例子：&lt;pre&gt;foo.c:

/* 这里定义了一个inline的函数foo() */
inline foo() {
    ...;   &amp;lt;- 编译器会像非inline函数一样为foo()生成独立的汇编码
}

void func1() {
    foo(); &amp;lt;- 同文件内foo()可能被编译器内联展开编译而不是直接call上面生成的汇编码
}&lt;/pre&gt;
&lt;p&gt;而在另一个文件里调用foo()的时候，则直接call的是上面文件内生成的汇编码：&lt;pre&gt;bar.c:

extern foo(); &amp;lt;- 声明foo()，注意不能在声明内带inline关键字

void func2() {
    foo();    &amp;lt;- 这里就是直接call在foo.c内为foo()函数生成的汇编码了
}&lt;/pre&gt;
&lt;div style="margin-left:0.5in;margin-right:0.5in"&gt;
&lt;table summary=Important border=0&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=top align=middle width=25 rowspan=2&gt;
&lt;th align=left&gt;重要
&lt;tr&gt;
&lt;td valign=top align=left&gt;
&lt;p&gt;虽然gcc的inline函数的行为很好理解，但是它和C99的inline是有很大差别的。请注意看后面对C99 inline的描述（&lt;a title="12.3.2.2. inline" href="http://superding.spaces.live.com/mmm2008-02-07_16.56/sect.tips.develop.inline.html#sect.tips.develop.inline.c99.inline"&gt;&lt;u&gt;&lt;font color="#0000ff"&gt;第 2.2 节 “inline”&lt;/font&gt;&lt;/u&gt;&lt;/a&gt;），以及如何以兼顾GCC和C99的方式使用inline函数。
&lt;p&gt;&lt;span&gt;&lt;strong&gt;要点：&lt;/strong&gt;&lt;/span&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;gcc的inline函数相对于普通extern函数来说只是在同一个文件内调用时建议编译器进行内联展开；
&lt;li&gt;
&lt;p&gt;gcc一定会为inline函数生成一份独立的汇编码，以便其在本文件之外被调用。在别的文件内看来，这个inline函数和普通的extern函数无异；
&lt;li&gt;
&lt;p&gt;gcc的inline函数是全局性的：在文件内可以作为一个内联函数被内联展开，而在文件外可以调用它。&lt;/ul&gt;&lt;/div&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4&gt;&lt;a&gt;&lt;/a&gt;1.3. extern inline&lt;/h4&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;GCC的static inline和inline都很好理解：看起来都像是对普通函数添加了可内联的属性。但是这个extern inline就千万不能想当然地理解成就是一个extern的函数+inline属性了。实际上gcc的extern inline十分古怪：一个extern inline的函数&lt;span&gt;&lt;strong&gt;只会被内联进去，而绝对不会生成独立的汇编码&lt;/strong&gt;&lt;/span&gt;！即使是通过指针应用或者是递归调用也不会让编译器为它生成汇编码，在这种时候对此函数的调用会被处理成一个外部引用。另外，extern inline的函数允许和外部函数重名，即在存在一个外部定义的全局库函数的情况下，再定义一个同名的extern inline函数也是合法的。以下用例子具体说明一下extern inline的特点：&lt;pre&gt;foo.c:

extern inline
int foo(int a)
{
    return (-a);
}

void func1()
{
    ...;
    a = foo(a);   ①
    p_foo = foo;  ②
    b = p_foo(b); ③
}&lt;/pre&gt;
&lt;p&gt;在这个文件内，gcc不会生成foo函数的汇编码。在func1中的调用点①，编译器会将上面定义的foo函数在这里内联展开编译，其表现类似于普通inline函数。因为这样的调用是能够进行内联处理的。而在②处，引用了foo函数的地址。但是注意：编译器是绝对不会为extern inline函数生成独立汇编码的！所以在这种非要个函数地址不可的情况下，编译器不得不将其处理为外部引用，在链接的时候链接到外部的foo函数去（填写外部函数的地址）。这时如果外部没有再定义全局的foo函数的话就会在链接时产生foo函数未定义的错误。
&lt;p&gt;假设在另一个文件里面也定义了一个全局函数foo：&lt;pre&gt;foo2.c:

int foo(int a)
{
    return (a);
}&lt;/pre&gt;
&lt;p&gt;那么在上面那个例子里面，后面一个对foo函数地址的引用就会在链接时被指到这个foo2.c中定义的foo函数去。也就是说：①调用foo函数的结果是a=-a，因为其内联了foo.c内的foo函数；而③调用的结果则是b=b，因为其实际上调用的是foo2.c里面的foo函数！
&lt;p&gt;extern inline的用法很奇怪也很少见，但是还是有其实用价值的。第一：它可以表现得像宏一样，可以在文件内用extern inline版本的定义取代外部定义的库函数（前提是文件内对其的调用不能出现无法内联的情况）；第二：它可以让一个库函数在能够被内联的时候尽量被内联使用。举个例子：
&lt;p&gt;在一个库函数的c文件内，定义一个普通版本的库函数libfunc：&lt;pre&gt;lib.c:

void libfunc()
{
    ...;
}&lt;/pre&gt;
&lt;p&gt;然后再在其头文件内，定义（注意不是声明！）一个实现相同的exterin inline的版本：&lt;pre&gt;lib.h:

extern inline libfunc()
{
    ...;
}&lt;/pre&gt;
&lt;p&gt;那么在别的文件要使用这个库函数的时候，只要include了lib.h，在能内联展开的地方，编译器都会使用头文件内extern inline的版本来展开。而在无法展开的时候（函数指针引用等情况），编译器就会引用lib.c中的那个独立编译的普通版本。即看起来似乎是个可以在外部被内联的函数一样，所以这应该是gcc的extern inline意义的由来。
&lt;p&gt;但是注意这样的使用是有代价的：c文件中的全局函数的实现必须和头文件内extern inline版本的实现完全相同。否则就会出现前面所举例子中直接内联和间接调用时函数表现不一致的问题。
&lt;div style="margin-left:0.5in;margin-right:0.5in"&gt;
&lt;table summary=Important border=0&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=top align=middle width=25 rowspan=2&gt;
&lt;th align=left&gt;重要
&lt;tr&gt;
&lt;td valign=top align=left&gt;
&lt;p&gt;gcc的extern inline函数的用法相当奇怪，使用的范围也非常狭窄：几乎没有什么情况会需要用它。
&lt;p&gt;在C99中，也没有关于extern inline这样的描述，所以不建议大家使用extern inline，除非你明确理解了这种用法的意义并且有充足的理由使用它！
&lt;p&gt;&lt;span&gt;&lt;strong&gt;要点：&lt;/strong&gt;&lt;/span&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;gcc绝对不会为extern inline的函数生成独立汇编码
&lt;li&gt;
&lt;p&gt;extern inline函数允许和全局函数重名，可以在文件范围内替代外部定义的全局函数
&lt;li&gt;
&lt;p&gt;extern inline函数的应用范围十分狭窄，而且行为比较奇怪，不建议使用&lt;/ul&gt;&lt;/div&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3&gt;&lt;a&gt;&lt;/a&gt;2. C99的inline&lt;/h3&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;以下主要描述C99的inline与Gcc不同的部分。对于相同的部分请参考GCC inline的说明。
&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4&gt;&lt;a&gt;&lt;/a&gt;2.1. static inline&lt;/h4&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;同GCC的static inline（&lt;a title="12.3.1.1. static inline" href="http://superding.spaces.live.com/mmm2008-02-07_16.56/sect.tips.develop.inline.html#sect.tips.develop.inline.gcc.static"&gt;&lt;u&gt;&lt;font color="#0000ff"&gt;第 1.1 节 “static inline”&lt;/font&gt;&lt;/u&gt;&lt;/a&gt;）。&lt;/div&gt;
&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4&gt;&lt;a&gt;&lt;/a&gt;2.2. inline&lt;/h4&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;C99的inline的使用相当令人费解。当一个定义为inline的函数没有被声明为extern的时候，其表现有点类似于gcc中extern inline那样（C99里面这段描述有点晦涩，原文如下）：
&lt;div&gt;
&lt;blockquote&gt;
&lt;p&gt;If all of the file scope declarations for a function in a translation unit include the &lt;code&gt;inline&lt;/code&gt; function specifier without &lt;code&gt;extern&lt;/code&gt;, then the definition in that translation unit is an &lt;span&gt;&lt;em&gt;inline definition&lt;/em&gt;&lt;/span&gt;. An inline definition does not provide an external definition for the function, and does not forbid an external definition in another translation unit. An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition.&lt;/blockquote&gt;&lt;/div&gt;
&lt;p&gt;即如果一个inline函数在文件范围内没有被声明为extern的话，这个函数在文件内的表现就和gcc的extern inline相似：在本文件内调用时允许编译器使用本文件内定义的这个内联版本，但同时也允许外部存在同名的全局函数。只是比较奇怪的是C99居然没有指定编译器是否必须在本文件内使用这个inline的版本而是让编译器厂家自己来决定，相当模糊的定义。
&lt;p&gt;如果在文件内把这个inline函数声明为extern，则这个inline函数的表现就和gcc的inline一致了：这个函数即成为一个“external definition”（可以简单理解为全局函数）：可以在外部被调用，并且在程序内仅能存在一个这样名字的定义。
&lt;p&gt;下面举例说明C99中inline的特性：&lt;pre&gt;inline double fahr(double t)
{
    return (9.0 * t) / 5.0 + 32.0;
}

inline double cels(double t)
{
    return (5.0 * (t - 32.0)) / 9.0;
}

extern double fahr(double);   ①

double convert(int is_fahr, double temp)
{
    return is_fahr ? cels(temp) : fahr(temp);   ②
}&lt;/pre&gt;
&lt;p&gt;在上面这个例子里，函数fahr是个全局函数：因为在①处将fahr声明为extern，因此在②处调用fahr的时候使用的一定是这个文件内所定义的版本（只不过编译器可以将这里的调用进行内联展开）。在文件外部也可以调用这个函数（说明像gcc的inline一样，编译器在这种情况下会为fahr生成独立的汇编码）。
&lt;p&gt;而cels函数因为没有在文件范围内被声明为extern，因此它就是前面所说的“inline definition”，这时候它实际上仅能作用于本文件范围（就像一个static的函数一样），外部也可能存在一个名字也为cels的同名全局函数。在②处调用cels的时候编译器可能选择用本文件内的inline版本，也有可能跑去调用外部定义的cels函数（C99没有规定此时的行为，不过编译器肯定都会尽量使用文件内定义的inline版本，要不然inline函数就没有存在的意义了）。从这里的表现上看C99中未被声明为extern的inline函数已经和gcc的extern inline十分相似了：本文件内的inline函数可以作为外部库函数的替代。
&lt;div style="margin-left:0.5in;margin-right:0.5in"&gt;
&lt;table summary=Important border=0&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=top align=middle width=25 rowspan=2&gt;
&lt;th align=left&gt;重要
&lt;tr&gt;
&lt;td valign=top align=left&gt;
&lt;p&gt;C99标准中的inline函数行为定义的比较模糊，并且inline函数有没有在文件范围内被声明为extern的其表现有本质不同。如果和gcc的inline函数比较的话，一个被声明为extern的inline函数基本等价于GCC的&lt;a title="12.3.1.2. inline" href="http://superding.spaces.live.com/mmm2008-02-07_16.56/sect.tips.develop.inline.html#sect.tips.develop.inline.gcc.inline"&gt;&lt;u&gt;&lt;font color="#0000ff"&gt;普通inline函数&lt;/font&gt;&lt;/u&gt;&lt;/a&gt;；而一个没有被声明为extern的inline函数基本等价于GCC的&lt;a title="12.3.1.3. extern inline" href="http://superding.spaces.live.com/mmm2008-02-07_16.56/sect.tips.develop.inline.html#sect.tips.develop.inline.gcc.extern"&gt;&lt;u&gt;&lt;font color="#0000ff"&gt;extern inline函数&lt;/font&gt;&lt;/u&gt;&lt;/a&gt;。
&lt;p&gt;因为C99的inline函数如此古怪，所以在使用的时候，建议为所有的inline函数都在头文件中创建extern的声明：&lt;pre&gt;foo.h:

extern foo();&lt;/pre&gt;
&lt;p&gt;而在定义inline函数的c文件内include这个头文件：&lt;pre&gt;foo.c:

#include &amp;quot;foo.h&amp;quot;

inline void foo()
{
    ...;
}&lt;/pre&gt;
&lt;p&gt;这样无论是用gcc的inline规则还是C99的，都能得到完全相同的结果：foo函数会在foo.c文件内被内联使用，而在外部又可以像普通全局函数一样直接调用。&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4&gt;&lt;a&gt;&lt;/a&gt;2.3. extern inline&lt;/h4&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;C99没有见到extern inline的用法。&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+C%e8%af%ad%e8%a8%80%e7%9a%84inline&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1137.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1137.entry</guid><pubDate>Fri, 15 Feb 2008 08:50:32 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1137/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1137.entry#comment</wfw:comment><dcterms:modified>2008-02-15T08:50:32Z</dcterms:modified></item><item><title>猪哥牌TFTP Server出炉</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1116.entry</link><description>猪哥的TFTP Server终于处于实用状态了，基本上没啥大问题，放出来下载。&lt;br&gt;
&lt;br&gt;
为了避免不明用处的人瞎下载，这里说明一下下载对象：&lt;br&gt;
&lt;ol&gt;&lt;li&gt;知道TFTP Server和FTP Server就像牛和马一样是两码事的，且&lt;li&gt;经常需要通过TFTP协议往开发板子上面下装程序的，且&lt;li&gt;TFTP Server通常仅仅跑在自己的机子上自己用，不会被一堆人共同蹂躏的，且&lt;br&gt;
&lt;li&gt;很讨厌复杂操作，只想要个点开就能跑的Server程序的，且&lt;li&gt;除了要求TFTP Server能提供上传下载以外不希望再有其他什么花哨功能的，且&lt;li&gt;经常要在最常用的几个root目录之间切换的，且&lt;li&gt;对于自己现用的TFTP Server觉得有点不爽的&lt;br&gt;
&lt;/ol&gt;如果你满足以上所有条件，那么你就可以下载我的TFTP Server试试看了。我的TFTP Server就是以最简界面，最简功能，最简操作的思想设计的。提供的功能如下：&lt;br&gt;
&lt;ul&gt;&lt;li&gt;无需配置即可用，运行后即在69端口侦听，默认根目录为程序运行的目录&lt;br&gt;
&lt;li&gt;多路径保存：最多保存8个常用根目录满足通常调试需要。通过Tab快速切换，右键单击Tab可以重命名&lt;li&gt;双击地址栏可以在资源管理器内打开Server根目录&lt;li&gt;带有历史记录的地址栏，支持20个历史地址，历史地址输入时支持自动完成&lt;li&gt;支持最小化到系统托盘，用气泡提示传输开始和结束&lt;li&gt;彩色的分色服务器Log显示，凸显失败的传输&lt;li&gt;实时传输进度显示（已传输字节数和百分比），下载时看起来比较有成就感:)&lt;li&gt;支持多线程上传和下载，支持RFC 1350、RFC 1782、RFC 1783&lt;/ul&gt;Megatops TFTP Server界面截图如下：&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm3.static.flickr.com/2261/2221901469_1e9f8b9cc4_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
&lt;a href="http://zhaojie.ding.googlepages.com/TFTPSvr.rar"&gt;此处下载&lt;/a&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+%e7%8c%aa%e5%93%a5%e7%89%8cTFTP+Server%e5%87%ba%e7%82%89&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1116.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1116.entry</guid><pubDate>Sun, 27 Jan 2008 07:48:41 GMT</pubDate><slash:comments>8</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1116/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1116.entry#comment</wfw:comment><dcterms:modified>2008-01-27T07:48:41Z</dcterms:modified></item><item><title>Megatops ProCoder编程用等宽字体更新</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1107.entry</link><description>稍微更新了一下，小修订如下：&lt;br&gt;
&lt;ul&gt;&lt;li&gt;增加了Vv和Uu的区分度&lt;li&gt;6、9、@、?字形细微调整&lt;li&gt;7×14字号j、&amp;amp;细微调整&lt;li&gt;8×16字号“J”加衬线，粗体“$”字形细微调整&lt;li&gt;ASCII编码显示下部留白边实现纵向分隔&lt;/ul&gt;更新方法：&lt;br&gt;
&lt;ul&gt;&lt;li&gt;关闭所有正在使用此字体的编辑器&lt;li&gt;删除Megatops ProCoder 1.0字体。如果发现删除后硬盘开始不停工作那就稍等一下，等到它停了为止。Windows对Raster字体的处理比较特殊和TTF不同&lt;li&gt;安装新的字体，OK&lt;/ul&gt;补充SourceInsight下面的设置方法（看来这垃圾玩意的用户还是不少～～）：&lt;br&gt;
&lt;ul&gt;&lt;li&gt;Document Options-&amp;gt;Screen Fonts：Megatops ProCoder 1.0&lt;li&gt;Preferences-&amp;gt;Display-&amp;gt;Spacing...-&amp;gt;去掉Smaller line heights&lt;/ul&gt;&lt;a href="http://zhaojie.ding.googlepages.com/MegatopsProCoder1.0.fon"&gt;此处下载&lt;/a&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+Megatops+ProCoder%e7%bc%96%e7%a8%8b%e7%94%a8%e7%ad%89%e5%ae%bd%e5%ad%97%e4%bd%93%e6%9b%b4%e6%96%b0&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1107.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1107.entry</guid><pubDate>Wed, 16 Jan 2008 02:04:24 GMT</pubDate><slash:comments>7</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1107/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1107.entry#comment</wfw:comment><dcterms:modified>2008-01-16T02:04:24Z</dcterms:modified></item><item><title>好文推荐：Real Programmers Don't Use Pascal</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1105.entry</link><description>这篇相当著名的文章和我的年龄一样大。现在看看第一代老程序员的生活确实是很有意思。文章所处的技术背景可能对只玩过上层web或者应用程序开发的人来说有些困难。至少推荐给我的一个做J2EE的同学以后得到的回答是看不懂(─.─||)。不过如何你是做嵌入式写驱动和内核的，会和这篇老古董产生一定的共鸣。&lt;br&gt;
&lt;br&gt;
文章的地址在：&lt;a href="http://www.pbm.com/~lindahl/real.programmers.html"&gt;http://www.pbm.com/~lindahl/real.programmers.html&lt;/a&gt;。作者的语气讽刺幽默也有些偏激。下面摘录一些觉得十分经典的句子：&lt;br&gt;
&lt;br&gt;
&lt;b&gt;语言和技术相关：&lt;br&gt;
&lt;/b&gt;&lt;br&gt;
“If you can't do it in Fortran, do it in assembly language.  If you can't do it in assembly language, it isn't worth doing.”&lt;br&gt;
&lt;br&gt;
“God forbid-- CP/M, after all, is basically a toy operating system.  Even little old ladies and grade school students can understand and use CP/M.”&lt;br&gt;
DOS基本抄袭CP/M，如果哪位还不会用DOS～～那就还不如little old ladies啦哈哈&lt;br&gt;
&lt;br&gt;
“People don't do Serious Work on Unix systems: they send jokes around the world on UUCP-net and write Adventure games and research papers.”&lt;br&gt;
&lt;br&gt;
“A truly outstanding programmer can find bugs buried in a 6 megabyte core dump without using a hex calculator.  (I have actually seen this done.)” &lt;br&gt;
(￣口￣)!! 果然神人&lt;br&gt;
&lt;br&gt;
“……EMACS and VI being two.  The problem with these editors is that Real Programmers consider &amp;quot;what you see is what you get&amp;quot; to be just as bad a concept in Text Editors as it is in Women.  No, the Real Programmer wants a &amp;quot;you asked for it, you got it&amp;quot; text editor-- complicated, cryptic, powerful, unforgiving, dangerous.”&lt;br&gt;
&lt;br&gt;
“There are several Real Programmers building video games at Atari, for example.  (But not playing them-- a Real Programmer knows how to beat the machine every time: no challenge in that.)”&lt;br&gt;
呃，打游戏我基本靠秘笈 (╯﹏╰)&lt;br&gt;
&lt;br&gt;
“College graduates these days are soft-- protected from the realities of programming by source level debuggers, text editors that count parentheses, and &amp;quot;user friendly&amp;quot; operating systems.  Worst of all, some of these alleged &amp;quot;computer scientists&amp;quot; manage to get degrees without ever learning Fortran!”&lt;br&gt;
其实我在学校见过用记事本写Java的人……&lt;br&gt;
&lt;br&gt;
“If you ignore the fact that it's &amp;quot;structured&amp;quot;, even 'C' programming can be appreciated by the Real Programmer: after all, there's no type checking, variable names are seven (ten? eight?) characters long, and the added bonus of the Pointer data type is thrown in-- like having the best parts of Fortran and assembly language in one place.  (Not to mention some of the more creative uses for #define.)”&lt;br&gt;
喔耶～～幸好我最终用的是C (#￣▽￣#)。可惜初一的时候学的第一门语言还是Pascal，属于“Quiche Eaters”出身 (╥﹏╥)&lt;br&gt;
&lt;br&gt;
&lt;strong&gt;性格和生活相关：&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
“At a party, the Real Programmers are the ones in the     corner talking about operating system security and how to get     around it.”&lt;br&gt;
&lt;br&gt;
“At the beach, the Real Programmer is the one drawing     flowcharts in the sand.”&lt;br&gt;
&lt;br&gt;
“The Real Programmer is capable of working 30, 40, even 50 hours at a stretch, under intense pressure.  In fact, he prefers it that way.  Bad response time doesn't bother the Real Programmer-- it gives him a chance to catch a little sleep between compiles.”&lt;br&gt;
&lt;br&gt;
“No Real Programmer works 9 to 5.  (Unless it's the ones at     night.)”&lt;br&gt;
这个……会被老板fire的 (⊙﹏⊙)&lt;br&gt;
&lt;br&gt;
“Real Programmers don't wear neckties.”&lt;br&gt;
Yahh～～长这么大还真是没有戴过～～&lt;br&gt;
&lt;br&gt;
“Real Programmers arrive at work in time for lunch.”&lt;br&gt;
鬼佬是几点吃午饭来着的？怎么和前面的时间对不上？&lt;br&gt;
&lt;br&gt;
“A Real Programmer might or might not know his wife's name.     He does, however, know the entire ASCII (or EBCDIC) code     table.”&lt;br&gt;
&lt;br&gt;
“Real Programmers don't know how to cook.  Grocery stores     aren't open at three in the morning.  Real Programmers survive     on Twinkies and coffee.”&lt;br&gt;
关于这个传说中的Twinkies，大家可以去Answers.com查查～～看起来不怎么好吃的样子(─.─||)&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+%e5%a5%bd%e6%96%87%e6%8e%a8%e8%8d%90%ef%bc%9aReal+Programmers+Don't+Use+Pascal&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1105.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1105.entry</guid><pubDate>Tue, 15 Jan 2008 05:27:14 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1105/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1105.entry#comment</wfw:comment><dcterms:modified>2008-01-15T05:27:14Z</dcterms:modified></item><item><title>无耻的SourceInsight中文网站</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1080.entry</link><description>今天朋友提到说在SourceInsight网站看到上面挂了个中文处理的宏很像我以前写的那个SuperBackspace。遂好奇上去看了看。结果发现还真是，唯一不同的是把我原来放在注释内的作者信息给删除了。其余部分一点不落全贴在上面，我在代码中的两句骂SourceInsight是&lt;strong&gt;stupid &amp;amp; buggy&lt;/strong&gt;还有&lt;strong&gt;idiot&lt;/strong&gt;的牢骚竟然也还在！后面还跟着不知是哪位从我的宏里面mod来的另外几个宏，也是一律没有作者信息。&lt;br&gt;
&lt;br&gt;
虽然我这个处理中文删除时半个汉字问题的宏是以GPL发表的。但是在原封不动转用的时候删除人家的作者信息也实在是很不厚道，至少说明人品很有问题。再看SI中文网站挂出来的另外几篇技巧文章，相同的特点就是统统没有标明出处和原作者，并且我能发现至少有两篇绝对是别人写的和SI官方没有任何关系！实在是令人唾弃的卑鄙行为。盗亦有道，私自转载就算了连作者名字也擦掉，实在是做得太过分了。&lt;br&gt;
&lt;br&gt;
另外提醒一下，似乎在SI出了3.5.0.35版本之后我原来那个宏似乎跑起来有问题。当时简单跟踪的结果是SI莫名其妙地修改了一个函数的处理行为，而且文档也没有提及这个修改。不过后来我也没有再跟踪，因为SourceInsight在装了最新Slickedit之后变成纯属多余的垃圾，所以在去年的一次系统重装后这玩意就从我的本子里面消失了。现在也一直懒得去跟踪这个问题。&lt;br&gt;
&lt;br&gt;
说到SourceInsight不免还想多牢骚几句。除了它长久以来不思进取死不更新以外，还有一点觉得它相当烂的就是它的macro机制。做得真是太垃圾了，功能极其有限。和Slickedit的Slick-C与Emacs的LISP根本毫无可比性，简直是没有什么二次开发能力。宏弱智也就算了，也没有提供一套插件机制来允许扩展，实在是难用至极。&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+%e6%97%a0%e8%80%bb%e7%9a%84SourceInsight%e4%b8%ad%e6%96%87%e7%bd%91%e7%ab%99&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1080.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1080.entry</guid><pubDate>Sun, 06 Jan 2008 16:02:07 GMT</pubDate><slash:comments>3</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1080/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1080.entry#comment</wfw:comment><dcterms:modified>2008-01-06T16:02:07Z</dcterms:modified></item><item><title>Megatops ProCoder字体发布</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1059.entry</link><description>这个专用于编写代码的字体很早就做好了，我用了有两个月。现在觉得1是没有原则性大问题，2是我自己已经懒得再修改了。所以现在作为正式版发布出来。&lt;br&gt;
&lt;br&gt;
这个字体是一个完全的点阵字体，有清晰锐利的显示效果。我之所以不喜欢用TTF字体编程是因为：1.没有打开Cleartype支持的TTF字体实在是太丑陋了；2.打开了Cleartype的TTF在使用深色背景浅色前景的时候显示效果实在是太糟糕了。在试用了几乎所有能找到的等宽字体编程以后我发现至少对我个人来说，最适合长时间阅读的还是边缘分明的点阵字。TTF+Cleartype虽然用在界面上很美丽，但是看久了常常有眼睛模糊的感觉。尤其是在连续工作10小时以后……&lt;br&gt;
&lt;br&gt;
字体效果预览：&lt;br&gt;
&lt;br&gt;
&lt;font color="#000099"&gt;&lt;strong&gt;Megatops ProCoder Font 1.0 7x14&lt;/strong&gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm3.static.flickr.com/2370/2166232100_2c79583e7f_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
&lt;b&gt;&lt;font color="#000099"&gt;Megatops ProCoder Font 1.0 8x16&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm3.static.flickr.com/2335/2166282880_5717ed01a1_o.png" alt=""&gt;&lt;br&gt;
&lt;/b&gt;&lt;b&gt;&lt;br&gt;
&lt;/b&gt;字体的主要特点是：&lt;br&gt;
&lt;ol&gt;&lt;li&gt;严格等宽，并且支持粗体。字体的粗体版本的宽度和正常版本是完全相同的。所以你可以放心打开编辑器的粗体显示关键字功能，而不用担心会损坏你完美的代码排版。实际上XP和之前版本的Windows自带的字体里面，仅有Courier New字体才能做到支持粗体等宽。其他诸如Terminal、Fixedsys、新宋体、Lucida Console这些“等宽”字体都是不完全等宽，只要打开粗体混显就露馅了。Vista内增加了Consolas，这个是很好的全等宽字体，也是我目前觉得最美观的一套TTF等宽字体。我在用超大字号（18pt以上）看RFC文档的时候就是用它。但是Consolas小字号非粗体的效果实在是有点难受，看久了很累。&lt;li&gt;和汉字也保持严格等宽：每个字符的高度严格为宽度的2倍。这样配合点阵汉字显示的时候也能保证绝对的等宽对齐。在使用Courier New或者Consolas时看到被拉扁的汉字实际上就是因为这些字体宽高比不是1：2的缘故。和汉字等宽是我设计这套字体的主要目的之一，因为能和汉字等宽又支持粗体等宽的字体很罕见。&lt;li&gt;有7×14，8×16两个大小（对应宋体的10pt和12pt）。8×16适合在现在主流的1280*1024以上分辨率的显示器上作为编码字体（这也是点阵汉字能支持的最大字号），而7*14适合于显示上下文窗口等希望能显示多行的地方。至于6*12（对应9pt宋体），考虑了很久以后发现是无法实现粗体等宽支持的，制作了也没有价值。况且对于高分辨率的显示起来说这个字号也太小了。&lt;li&gt;对易混字符有高区分度：“１Ｉｌｉ”和“０Ｏｏ”都有区分。对比常常被误以为是编程字体的Courier New和新宋体：它们在这上面就做得很不好：０Ｏ等难以分辨，以编程字体的要求来看这些都不能算作是编程字体。相比起来Fixedsys就要好得多。&lt;li&gt;非可见字符显示为字符的ASCII码值。这样在出现乱码的时候，起码能看出比黑块多一些的信息来。以下是使用我的ProCoder字体和用Fixedsys字体看乱码的对比：&lt;br&gt;
&lt;strong&gt;Fixedsys：&lt;/strong&gt;&lt;br&gt;
&lt;img src="http://farm3.static.flickr.com/2156/2166341440_d0f352f8ff_o.png" alt=""&gt;&lt;br&gt;
&lt;strong&gt;Megatops ProCoder 1.0：&lt;/strong&gt;&lt;br&gt;
&lt;img src="http://farm3.static.flickr.com/2247/2166341508_833dc5751a_o.png" alt=""&gt;&lt;br&gt;
&lt;/ol&gt;除了主要特点以外，还有一些可能很多人觉得是鸡毛蒜皮的考虑：&lt;br&gt;
&lt;ol&gt;&lt;li&gt;针对C/C++程序的特点，凸显了分号和逗点等符号。这点做得最差的可能是新宋体了：新宋体的分号是我所见过的最丑陋最不醒目的。&lt;li&gt;尖括号&amp;lt;&amp;gt;是90°角的。我不喜欢太尖的尖括号，太尖的话在写诸如p_struct-&amp;gt;member的时候会让“-&amp;gt;”显得不好看。Linux下面常用的Bitstream Vesa Sans Mono字体里面觉得比较不爽的也就是太短的减号和太尖的尖括号的搭配。&lt;li&gt;“#”是横平竖直不是斜的。很多字体的“#”是斜体，弄得我每次在写宏定义的时候都觉得很怪。&lt;li&gt;星号“*”和字符的中线平齐。绝大多数的字体的“*”都是高高在上的，在写四则运算算式的时候会觉得乘号难看极了：所有的符号都是和数字中线平齐，唯独乘号冒出来破坏整齐的美感。已有的字体中只有新宋体和Fixedsys的乘号是居中的，其他都不同程度的偏上，觉得比较奇怪是不是老美的习惯问题。&lt;li&gt;波浪线“～”也是居中，理由同上。&lt;/ol&gt;没有实现也绝不会打算做的：&lt;br&gt;
&lt;ol&gt;&lt;li&gt;6x12支持：理由前面已经说了；&lt;li&gt;8x16以上的大字体：这个字号以外已经脱离了点阵中文字体的地盘，在没有点阵中文支持的情况下～～还是用TTF+Cleartype吧。大号点阵字体的效果远不如平滑的矢量字体来的好看；&lt;br&gt;
&lt;li&gt;斜体支持，我厌恶看起来支离破碎的点阵斜体；&lt;li&gt;TTF支持：把点阵字体弄成内嵌点阵的伪TTF字体可能只有在那些不支持点阵字体的Java写的如jEdit之类的编辑器上才有价值。但是1.我基本不会去用慢得要死的基于Java的编辑器，2.Eclipse是支持使用点阵字体的。&lt;/ol&gt;&lt;br&gt;
&lt;a href="http://zhaojie.ding.googlepages.com/MegatopsProCoder1.0.fon"&gt;【点此下载】&lt;/a&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+Megatops+ProCoder%e5%ad%97%e4%bd%93%e5%8f%91%e5%b8%83&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1059.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1059.entry</guid><pubDate>Fri, 04 Jan 2008 15:43:37 GMT</pubDate><slash:comments>10</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1059/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1059.entry#comment</wfw:comment><dcterms:modified>2008-01-04T15:43:37Z</dcterms:modified></item><item><title>自制TFTP Server</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1047.entry</link><description>&lt;p&gt;很早就想做个用起来比较顺手的TFTP Server。因为完全是用来下装程序调试用的，所以只想要个界面足够弱智，操作方便的TFTP Server。
&lt;p&gt;试过一些TFTP Server，要么就过于弱智，打开来只能换个目录其他什么也不能动。但是实际上调程序的时候经常要切换编译目录下载不同版本的bin，这个就用起来有点郁闷。再要么用一些支持设置多文件夹切换的，又太麻烦：非要用界面点开来选择目录，不能直接Ctrl+V一个路径进去，操作不够直接干脆。在要么就是做得如FTP Server一般界面吓人配置复杂的那种，作为中心服务器可能不错，但是个人拿来调试就太复杂了。
&lt;p&gt;昨晚花了俺整整一个晚上折腾出来一个勉强可用的版本，界面如下：
&lt;p&gt;&lt;img alt="" src="http://farm3.static.flickr.com/2155/2114538030_d933943ee7_o.png"&gt;
&lt;p&gt;这玩意的主要特点如下：
&lt;ul&gt;
&lt;li&gt;界面要足够弱智。我这个点开马上就在当前目录下建立Server，任何配置都是多余。 
&lt;li&gt;虽然界面弱智，功能也不能太弱。所以设计了6个收藏夹可以存储多个服务器根目录，只要简单点Tab就能快速切换。收藏夹保存在ini文件内。这样切换服务器目录非常方便。 
&lt;li&gt;所有的路径输入都能支持直接粘贴。这样从Explorer或者是命令行Copy过来的路径直接贴进去就好了免得必须用鼠标选很烦。当然也支持用对话框选择。 
&lt;li&gt;任务列表用红色标出失败的传输。 
&lt;li&gt;支持最小化的系统托盘，并在最小化以后用Balloon提示状态信息，Ballon在3秒后自动消失：&lt;br&gt;&lt;img alt="" src="http://farm3.static.flickr.com/2229/2112027327_276f91097e_o.png"&gt;&lt;/ul&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+%e8%87%aa%e5%88%b6TFTP+Server&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1047.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1047.entry</guid><pubDate>Sat, 15 Dec 2007 12:57:04 GMT</pubDate><slash:comments>2</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1047/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1047.entry#comment</wfw:comment><dcterms:modified>2007-12-16T05:38:38Z</dcterms:modified></item><item><title>BinCalc最新版本发布</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1031.entry</link><description>BinCalc最新版本正式发布啦，将近一年以来对Windows桌面版的第一次重要升级。目前的主要功能如下（+为本次升级新增）：&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;首创的3进制同屏无切换输入和高度优化的2进制输入输出界面（位指示器） 
&lt;li&gt;多种不同形式的结果导出（对应进制的显示框点右键） 
&lt;li&gt;Classic 4-Level RPN计算器，支持位运算和基本算术运算 
&lt;li&gt;优化的单目运算操作按钮，可以对任意一个栈寄存器进行单目运算
&lt;li&gt;多种形式的二进制位标号支持（位序号处点右键） 
&lt;li&gt;彻底优化的键盘输入支持(+) 
&lt;li&gt;10进制支持Signed/Unsigned类型，支持数字分组显示(+) 
&lt;li&gt;8进制支持和针对文件权限值优化的操作面板(+)&lt;/ul&gt;Palm OS版本没有升级，还是老样子。因为现在已经对做Palm OS软件没啥兴趣了——自己已经没有Palm可用啦。&lt;br&gt;Palm OS版本的基本功能如下：&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;首创的3进制同屏无切换输入和高度优化的2进制输入输出界面（位指示器） 
&lt;li&gt;简单算术顺序（ALG）计算器，支持位运算 
&lt;li&gt;多种形式的二进制位标号支持&lt;/ul&gt;
&lt;p&gt;如果不出意外的话，PalmOS版本应该是永远不会再有更新不会再维护了。不过一个软件能同时有PDA/智能手机版本和Windows PC版本，听起来也是很酷的事情(#￣▽￣#) 
&lt;p&gt;下载：&lt;a href="http://zhaojie.ding.googlepages.com/BinCalc.zip"&gt;本地下载&lt;/a&gt; 或者 &lt;a href="http://www.handango.com/PlatformProductDetail.jsp?osId=904&amp;amp;productId=217426" target="_blank"&gt;Handango.com&lt;/a&gt;
&lt;p&gt;英文版的功能图介： 
&lt;div align=center&gt;&lt;img alt="" src="http://farm3.static.flickr.com/2024/1949240336_d5449297b3_o.png"&gt;&lt;br&gt;&lt;/div&gt;&lt;br&gt;
&lt;div align=center&gt;&lt;img alt="" src="http://farm3.static.flickr.com/2056/1949241542_843234380a_o.png"&gt;&lt;br&gt;&lt;br&gt;&lt;img alt="" src="http://farm3.static.flickr.com/2387/1949243422_36f5206ddc_o.png"&gt;&lt;br&gt;&lt;br&gt;&lt;img alt="" src="http://farm3.static.flickr.com/2415/1948409619_a199335585_o.png"&gt;&lt;br&gt;&lt;br&gt;&lt;img alt="" src="http://farm3.static.flickr.com/2321/1950251186_3335810746_o.png"&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+BinCalc%e6%9c%80%e6%96%b0%e7%89%88%e6%9c%ac%e5%8f%91%e5%b8%83&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1031.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1031.entry</guid><pubDate>Fri, 09 Nov 2007 16:09:44 GMT</pubDate><slash:comments>3</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1031/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1031.entry#comment</wfw:comment><dcterms:modified>2008-01-10T16:43:25Z</dcterms:modified></item><item><title>BinCalc最终改进完成！</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1030.entry</link><description>昨晚终于想出了怎么完美支持键盘输入的界面以后，立马奋战1小时把它做出来了。现在我的BinCalc终于无论是键盘输入还是界面输入上都没有什么遗憾了。&lt;br&gt;
&lt;br&gt;
为了支持键盘输入，我不得不加入我一直非常抵制的进制切换开关。不过这个开关终于被不破相地引入了目前计算器的界面中（Flickr图片）：&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm3.static.flickr.com/2362/1903091240_116abc3372_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
粗看可能没发现啥，不过奥妙就在黄色高亮的显示框上面。键盘的进制用黄色高亮的显示框来标记，如果高亮位于10进制，那键盘输入的数字就是10进制的，依此类推。为了照顾色弱的用户（我一直偏好淡色调），在进制输入面板的标题上也会以“*”号来标明当前键盘的进制状态。这样就可以轻易使用键盘进行输入了。&lt;br&gt;
&lt;br&gt;
要切换键盘的进制，有两种方法：1是直接双击对应进制的显示框，这样可以直接选择进制。2是按键盘上面的Tab键，进制会按照顺时针在界面上循环。通过黄色高亮的显示框可以很容易分辨当前的键盘进制模式。&lt;br&gt;
&lt;br&gt;
目前支持的键盘按键如下：&lt;br&gt;
&lt;ul&gt;&lt;li&gt;Tab：切换键盘的进制&lt;li&gt;Esc：清空当前输入（CLx）&lt;li&gt;回车：Enter（压栈）&lt;li&gt;退格：Del（删除一位）&lt;li&gt;0－9，A－F：数字输入&lt;li&gt;+ - * /：算术计算&lt;li&gt;&amp;lt; &amp;gt;：左右移位（Shl，Shr）&lt;li&gt;~ % &amp;amp; | ^：和C语言意义相同的位运算&lt;li&gt;上下方向键：堆栈上下移动&lt;li&gt;左右方向键：当前值（x寄存器）左右移1位&lt;li&gt;Ctrl+C：将当前进制显示的数字复制到剪贴板&lt;li&gt;Ctrl+V：将剪贴板的内容粘贴到当前进制输入&lt;br&gt;
&lt;/ul&gt;键盘已经可以完成大部分的输入工作，包括进制切换和堆栈调整了（不过遗憾的是x&amp;lt;&amp;gt;y键还没有找到合适的按键映射，看来还是只能点界面上的按钮啦，不过很少用）。&lt;br&gt;
&lt;br&gt;
另外，RPN的堆栈也进行了修正。之前的版本T寄存器的表现和惠普计算器的表现行为不一致（不会随着堆栈的下移而保留），考虑到凡是用RPN的必然是HP计算器的粉丝，所以还是修改修改让XYZT寄存器能和惠普计算器用起来一样。&lt;br&gt;
&lt;br&gt;
这次大升级完成了8进制支持和键盘输入支持，基本完成啦！本周内即可发布！&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+BinCalc%e6%9c%80%e7%bb%88%e6%94%b9%e8%bf%9b%e5%ae%8c%e6%88%90%ef%bc%81&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1030.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1030.entry</guid><pubDate>Wed, 07 Nov 2007 14:10:27 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1030/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1030.entry#comment</wfw:comment><dcterms:modified>2007-11-07T14:10:27Z</dcterms:modified></item><item><title>BinCalc无敌二进制计算器再次修改</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1029.entry</link><description>&lt;p&gt;今晚除了几个我的BinCalc的BUG，并且添加了构想中的八进制（Octal）换算功能。之所以说只是换算，是因为我真的从来没有用8进制计算过（FIXME：还有哪些地方会用到8进制计算？），所以在RPN的4个寄存器里面依然只能支持HEX和DEC显示。
&lt;p&gt;八进制的换算跟我昨天说的一样，完全为换算文件权限位优化的：带有专门的位指示器来设置低9位的u、g、o权限值。这个界面昨天就想好了，只是今晚抽空把它做了出来：&lt;br&gt;（依然是Flickr图片，看不到的请用Access Flickr扩展。不过多嘴一句：Flickr似乎切到Farm3了？！GFW只和谐掉Farm1和2，昨晚试了试似乎最近贴在Farm3的图片还是能直接在国内看到的～～）
&lt;p&gt;&lt;img alt="" src="http://farm3.static.flickr.com/2342/1874755722_becbda9a7e_o.png"&gt;
&lt;p&gt;8进制的Copy菜单也增加了拷贝成文件权限字符串的形式：
&lt;p&gt;&lt;img alt="" src="http://farm3.static.flickr.com/2281/1873930665_dc426ac068_o.png"&gt;
&lt;p&gt;8进制面板和16进制是互相切换的。这个打破了我尽力避免的进制切换设计思想。不过要做到塞进8进制来也无需切换，那界面实在是太难设计了（俺设计界面可不专业的说～～哪位专业的可以想想怎么直接塞进8进制面板？）。幸好8进制是非常少用的，用的时候切一下应该也能忍受。
&lt;p&gt;关于键盘支持上，目前还是没有办法：依然想不出怎么自动识别按下的键是什么进制的（界面没有进制切换开关，是三进制同屏的）。不过这个计算器的主要目的是作为进制转换和置位计算，我自己在使用中基本没有过要手工输入数据的需求（要么是从别的地方Copy，要么是直接置位反算出16进制模式）。所以支持键盘这个俺不打算再想了，头疼～～
&lt;p&gt;目前这个计算器基本达到我最初的设计要求了：成为一个界面上足以吓住计算机麻瓜的，只有程序员才看得懂、懂得用和用的上的计算器(#￣▽￣#)。
&lt;p&gt;8进制部分依然还要测试，等测试完以后发布～～&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+BinCalc%e6%97%a0%e6%95%8c%e4%ba%8c%e8%bf%9b%e5%88%b6%e8%ae%a1%e7%ae%97%e5%99%a8%e5%86%8d%e6%ac%a1%e4%bf%ae%e6%94%b9&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1029.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1029.entry</guid><pubDate>Mon, 05 Nov 2007 15:45:25 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1029/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1029.entry#comment</wfw:comment><dcterms:modified>2007-11-05T15:55:01Z</dcterms:modified></item><item><title>BinCalc无敌二进制计算器小修改</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1026.entry</link><description>今晚对我的BinCalc二进制计算器的Windows版本做了些小修订，目前自己正在测试，测试完成后再发布：&lt;br&gt;
&lt;br&gt;
主要的修改如下（Flickr图片，请用Access Flickr扩展观看！）：&lt;br&gt;
&lt;br&gt;
1. 功能上增加了无符号整型计算已经移位运算的支持。无符号整型计算是以前觉得没啥用所以没做，不过后来发现还是有点用的，就加上了。移位运算之前没有添加的原因完全是因为界面上面塞不下（已经排得很密了）。所以今晚痛苦地调整了半天控件，硬生生把那两个按钮挤下去了(#￣▽￣#)&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm3.static.flickr.com/2048/1857559003_0e6a93a8e0_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
在RPN计算面板中，只有+-*/是个按钮是支持带符号整型的。其他的位运算和取模移位什么的全是仅支持无符号整型。理论上移位应该是要支持带符号的，但是我们在实际使用中好像从来没有过带符号移位的需要吧（都是算算掩码什么的似乎）。倒是害怕无意中做了带符号右移，把符号位扩展了得到不想要的结果就郁闷了。所以移位我就和位运算放在一块作为不带符号扩展的纯位操作运算符了。&lt;br&gt;
&lt;br&gt;
2. Copy菜单里面添加了效果预览。以前有人问过我里面的0x####是代表啥(─.─||)，这回有预览了应该没问题了吧：&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm3.static.flickr.com/2137/1857562307_6a6b61c865_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
3. 二进制位指示器的标尺切换改成右键菜单界面。因为原来的切换方式实在是藏匿得太深了我自己经常都忘记怎么切了。这样就直观多了：&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm3.static.flickr.com/2095/1858383396_3e9d1ce5a1_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
4. 最后，十进制Copy里面增加了G/M/K容量表示形式的格式。这个主要是我经常要通过一个指针算算大概是在内存的哪个地方，脑子里面去除1024除不清楚。还是直接加上的了：&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm3.static.flickr.com/2416/1857560023_525ca6b5f3_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
后面的功能计划是添加8进制（Oct）计算面板。准备和16进制的面板叠在一起，用的时候再切出来（因为8进制实在是很少用）。用到8进制的地方似乎除了设置文件权限以外就基本没了？不管别人怎样，起码我只有在写文件权限的时候用到了，所以8进制的操作面板将会专门针对文件权限位计算设计～～完成时间～～看看啥时候还有几小时的闲功夫了。&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+BinCalc%e6%97%a0%e6%95%8c%e4%ba%8c%e8%bf%9b%e5%88%b6%e8%ae%a1%e7%ae%97%e5%99%a8%e5%b0%8f%e4%bf%ae%e6%94%b9&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1026.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1026.entry</guid><pubDate>Sun, 04 Nov 2007 16:30:01 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1026/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1026.entry#comment</wfw:comment><dcterms:modified>2007-11-04T16:30:01Z</dcterms:modified></item><item><title>Volatile的陷阱</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1019.entry</link><description>&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;最近写的关于在嵌入式开发中常遇到的关于volatile关键字使用的短文，都是些通用的技术，贴上来share。另外，禁止转载。 &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;/div&gt;
&lt;div&gt;对于volatile关键字，大部分的C语言教材都是一笔带过，并没有做太过深入的分析，所以这里简单整理了一些关于volatile的使用注意事项。实际上从语法上来看volatile和const是一样的，但是如果const用错，几乎不会有什么问题；而volatile用错，后果可能很严重。所以在volatile的使用上，建议大家还是尽量求稳，少用一些没有切实把握的技巧。&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3&gt;&lt;a&gt;&lt;/a&gt;注意volatile修饰的是谁&lt;/h3&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;首先来看下面两个定义的区别：&lt;pre&gt;uchar * volatile reg;&lt;/pre&gt;
&lt;p&gt;这行代码里volatile修饰的是reg这个变量。所以这里实际上是定义了一个uchar类型的指针，并且这个指针变量本身是volatile 的。但是指针所指的内容并不是volatile的！在实际使用的时候，编译器对代码中指针变量reg本身的操作不会进行优化，但是对reg所指的内容 *reg却会作为non-volatile内容处理，对*reg的操作还是会被优化。通常这种写法一般用在对共享指针的声明上，即这个指针变量有可能会被中断等函数修改。将其定义为volatile以后，编译器每次取指针变量的值的时候都会从内存中载入，这样即使这个变量已经被别的程序修改了当前函数用的时候也能得到修改后的值（否则通常只在函数开始取一次放在寄存器里，以后就一直使用寄存器内的副本）。&lt;pre&gt;volatile uchar *reg;&lt;/pre&gt;
&lt;p&gt;这行代码里volatile修饰的是指针所指的内容。所以这里定义了一个uchar类型的指针，并且这个指针指向的是一个volatile的对象。但是指针变量本身并不是volatile的。如果对指针变量reg本身进行计算或者赋值等操作，是可能会被编译器优化的。但是对reg所指向的内容 *reg的引用却禁止编译器优化。因为这个指针所指的是一个volatile的对象，所以编译器必须保证对*reg的操作都不被优化。通常在驱动程序的开发中，对硬件寄存器指针的定义，都应该采用这种形式。&lt;pre&gt;volatile uchar * volatile reg;&lt;/pre&gt;
&lt;p&gt;这样定义出来的指针就本身是个volatile的变量，又指向了volatile的数据内容。&lt;/div&gt;
&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3&gt;&lt;a&gt;&lt;/a&gt;volatile与const的合用&lt;/h3&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;从字面上看，volatile和const似乎是一个对象的两个对立属性，是互斥的。但是实际上，两者是有可能一起修饰同一个对象的。看看下面这行声明：&lt;pre&gt;extern const volatile unsigned int rt_clock;&lt;/pre&gt;
&lt;p&gt;这是在RTOS系统内核中常见的一种声明：rt_clock通常是指系统时钟，它经常被时钟中断进行更新。所以它是volatile，易变的。因此在用的时候，要让编译器每次从内存里面取值。而rt_clock通常只有一个写者（时钟中断），其他地方对其的使用通常都是只读的。所以将其声明为 const，表示这里不应该修改这个变量。所以volatile和const是两个不矛盾的东西，并且一个对象同时具备这两种属性也是有实际意义的。 
&lt;div style="margin-left:0.5in;margin-right:0.5in"&gt;
&lt;table summary=Note border=0&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=top align=middle width=25 rowspan=2&gt;
&lt;th align=left&gt;注意 
&lt;tr&gt;
&lt;td valign=top align=left&gt;
&lt;p&gt;在上面这个例子里面，要注意声明和定义时对const的使用： 
&lt;p&gt;在需要读写rt_clock变量的中断处理程序里面，应该如下定义（define）此变量：&lt;pre&gt;volatile unsigned int rt_clock;&lt;/pre&gt;
&lt;p&gt;而在提供给外部用户使用的头文件里面，可以将此变量声明（declare）为：&lt;pre&gt;extern const volatile unsigned int rt_clock;&lt;/pre&gt;
&lt;p&gt;这样是没有问题的。但是切记一定不能反过来，即定义一个const的变量：&lt;pre&gt;const unsigned int a;&lt;/pre&gt;
&lt;p&gt;但是却声明为非const变量：&lt;pre&gt;extern unsigned int a;&lt;/pre&gt;
&lt;p&gt;这样万一在用户函数里面对a进行了写操作，结果是Undefined。&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;再看另一个例子：&lt;pre&gt;volatile struct devregs * const dvp = DEVADDR;&lt;/pre&gt;
&lt;p&gt;这里的volatile和const实际上是分别修饰了两个不同的对象：volatile修饰的是指针dvp所指的类型为struct devregs的数据结构，这个结构对应者设备的硬件寄存器，所以是易变的，不能被优化的；而后面的const修饰的是指针变量dvp。因为硬件寄存器的地址是一个常量，所以将这个指针变量定义成const的，不能被修改。&lt;/div&gt;
&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3&gt;&lt;a&gt;&lt;/a&gt;危险的volatile用法&lt;/h3&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;下面将列举几种对volatile的不当使用和可能导致的非预期的结果。 
&lt;div&gt;&lt;a&gt;&lt;/a&gt;
&lt;p&gt;&lt;b&gt;例：定义为volatile的结构体成员&lt;/b&gt; 
&lt;p&gt;考察下面对一个设备硬件寄存器结构类型的定义：&lt;pre&gt;struct devregs{
    unsigned short volatile csr;
    unsigned short const volatile data;
};&lt;/pre&gt;
&lt;p&gt;我们的原意是希望声明一个设备的硬件寄存器组。其中有一个16bit的CSR控制/状态寄存器，这个寄存器可以由程序向设备写入控制字，也可以由硬件设备设置反映其工作状态。另外还有一个16bit的DATA数据寄存器，这个寄存器只会由硬件来设置，由程序进行读入。 
&lt;p&gt;看起来，这个结构的定义没有什么问题，也相当符合实际情况。但是如果执行下面这样的代码时，会发生什么情况呢？&lt;pre&gt;struct devregs * const dvp = DEVADDR;

while ((dvp-&amp;gt;csr &amp;amp; (READY | ERROR)) == 0)
    ; /* NULL - wait till done */&lt;/pre&gt;
&lt;p&gt;通过一个non-volatile的结构体指针，去访问被定义为volatile的结构体成员，编译器将如何处理？答案是：&lt;span&gt;&lt;strong&gt;Undefined&lt;/strong&gt;&lt;/span&gt;！C99 标准没有对编译器在这种情况下的行为做规定。所以编译器有可能正确地将dvp-&amp;gt;csr作为volatile的变量来处理，使程序运行正常；也有可能就将dvp-&amp;gt;csr作为普通的non-volatile变量来处理，在while当中优化为只有开始的时候取值一次，以后每次循环始终使用第一次取来的值而不再从硬件寄存器里读取，这样上面的代码就有可能陷入死循环！！ 
&lt;p&gt;如果你使用一个volatile的指针来指向一个非volatile的对象。比如将一个non-volatile的结构体地址赋给一个 volatile的指针，这样对volatile指针所指结构体的使用都会被编译器认为是volatile的，即使原本那个对象没有被声明为 volatile。然而反过来，如果将一个volatile对象的地址赋给一个non-volatile的普通指针，通过这个指针访问volatile对象的结果是undefined，是危险的。 
&lt;p&gt;所以对于本例中的代码，我们应该修改成这样：&lt;pre&gt;struct devregs{
    unsigned short csr;
    unsigned short data;
};

volatile struct devregs * const dvp = DEVADDR;&lt;/pre&gt;
&lt;p&gt;这样我们才能保证通过dvp指针去访问结构体成员的时候，都是作为volatile来处理的。&lt;/div&gt;
&lt;div&gt;&lt;a&gt;&lt;/a&gt;
&lt;p&gt;&lt;b&gt;例：定义为volatile的结构体类型&lt;/b&gt; 
&lt;p&gt;考察如下代码：&lt;pre&gt;volatile struct devregs{
    /* stuff */
} dev1;
......;
struct devregs dev2;&lt;/pre&gt;
&lt;p&gt;作者的目的也许是希望定义一个volatile的结构体类型，然后顺便定义一个这样的volatile结构体变量dev1。后来又需要一个这种类型的变量，因此又定义了一个dev2。然而，第二次所定义的dev2变量实际上是non-volatile的！！因为实际上在定义结构体类型时的那个 volatile关键字，修饰的是dev1这个变量而不是struct devregs类型的结构体！！ 
&lt;p&gt;所以这个代码应该改写成这样：&lt;pre&gt;typeof volatile struct devregs{
    /* stuff */
} devregs_t;

devregs_t dev1;
......;
devregs_t dev2;&lt;/pre&gt;
&lt;p&gt;这样我们才能得到两个volatile的结构体变量。&lt;/div&gt;
&lt;div&gt;&lt;a&gt;&lt;/a&gt;
&lt;p&gt;&lt;b&gt;例：多次的间接指针引用&lt;/b&gt; 
&lt;p&gt;考察如下代码：&lt;pre&gt;/* DMA buffer descriptor */
struct bd{
    unsigned int state;
    unsigned char *data_buff;
};

struct devregs{
    unsigned int csr;
    struct bd *tx_bd;
    struct bd *rx_bd;
};

volatile struct devregs * const dvp = DEVADDR;

/* send buffer */
dvp-&amp;gt;tx_bd-&amp;gt;state = READY;

while((dvp-&amp;gt;tx_bd-&amp;gt;state &amp;amp; (EMPTY | ERROR)) == 0)
    ; /* NULL - wait till done */&lt;/pre&gt;
&lt;p&gt;这样的代码常用在对一些DMA设备的发送Buffer处理上。通常这些Buffer Descriptor（BD）当中的状态会由硬件进行设置以告诉软件Buffer是否完成发送或接收。但是请注意，上面的代码中对dvp-&amp;gt; tx_bd-&amp;gt;state的操作实际上是non-volatile的！这样的操作有可能因为编译器对其读取的优化而导致后面陷入死循环。 
&lt;p&gt;因为虽然dvp已经被定义为volatile的指针了，但是也只有其指向的devregs结构才属于volatile object的范围。也就是说，将dvp声明为指向volatile数据的指针可以保障其所指的volatile object之内的tx_bd这个结构体成员自身是volatile变量，但是并不能保障这个指针变量所指的数据也是volatile的（因为这个指针并没有被声明为指向volatile数据的指针）。 
&lt;p&gt;要让上面的代码正常工作，可以将数据结构的定义修改成这样：&lt;pre&gt;struct devregs{
    unsigned int csr;
    volatile struct bd *tx_bd;
    volatile struct bd *rx_bd;
};&lt;/pre&gt;
&lt;p&gt;这样可以保证对state成员的处理也是volatile的。不过最为稳妥和清晰的办法还是这样：&lt;pre&gt;volatile struct devregs * const dvp = DEVADDR;
volatile struct bd *tx_bd = dvp-&amp;gt;tx_bd;

tx_bd-&amp;gt;state = READY;

while((tx_bd-&amp;gt;state &amp;amp; (EMPTY | ERROR)) == 0)
    ; /* NULL - wait till done */&lt;/pre&gt;
&lt;p&gt;这样在代码里面能绝对保证数据结构的易变性，即使数据结构里面没有定义好也不会有关系。而且对于日后的维护也有好处：因为这样从代码里一眼就能看出哪些数据结构的访问是必须保证volatile的。
&lt;p&gt;&lt;b&gt;例：到底哪个volatile可能无效&lt;/b&gt;
&lt;div&gt;
&lt;p&gt;就在你看过前面几个例子，感觉自己可能已经都弄明白了的时候，请看最后这个例子：&lt;pre&gt;struct hw_bd {
    ......;
    volatile unsigned char * volatile buffer;
};

struct hw_bd *bdp;

......;
bdp-&amp;gt;buffer = ...; ①
bdp-&amp;gt;buffer[i] = ...; ②&lt;/pre&gt;
&lt;p&gt;请问上面标记了①和②的两行代码，哪个是确实在访问volatile对象，而哪个又是undefined的结果？
&lt;p&gt;答案是：②是volatile的，①是undefined。来看本例的数据结构示意图：&lt;pre&gt;        (non-volatile)
bdp --&amp;gt;+-------------+
       |             |
       |   ... ...   |
       |             |
       +-------------+    (volatile)   
       |    buffer   |--&amp;gt;+------------+
       +-------------+   |            |
                         |            |
                         |            |
                         +------------+
                         |  buffer[i] |
                         +------------+
                         |            |
                         |            |
                         +------------+&lt;/pre&gt;
&lt;p&gt;buffer成员本身是通过一个non-volatile的指针bdp访问的，按照C99标准的定义，这就属于undefined的情况，因此对bdp-&amp;gt;buffer的访问编译器不一定能保证是volatile的；
&lt;p&gt;虽然buffer成员本身可能不是volatile的变量，但是buffer成员是一个指向volatile对象的指针。因此对buffer成员所指对象的访问编译器可以保证是volatile的，所以bdp-&amp;gt;buffer[i]是volatile的。
&lt;p&gt;所以，看似简单的volatile关键字，用起来还是有非常多的讲究在里面的，大家一定要引起重视。&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+Volatile%e7%9a%84%e9%99%b7%e9%98%b1&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1019.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1019.entry</guid><pubDate>Thu, 25 Oct 2007 15:50:19 GMT</pubDate><slash:comments>3</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1019/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1019.entry#comment</wfw:comment><dcterms:modified>2007-10-26T01:34:48Z</dcterms:modified></item><item><title>乱序执行和内存屏障</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1017.entry</link><description>&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;div&gt;最近写的一些关于在驱动程序开发中会遇到的关于乱序执行问题的短文，都是些通用的技术，贴上来share。另外，禁止转载。 &lt;/div&gt;
&lt;div&gt;ps：这玩意原本是用Docbook写得，转过来还真是麻烦～～&lt;/div&gt;
&lt;h3&gt;处理器的乱序和并发执行&lt;/h3&gt;&lt;/div&gt;
&lt;div lang=zh-cn&gt;
&lt;div lang=zh-cn&gt;
&lt;p&gt;目前的高级处理器，为了提高内部逻辑元件的利用率以提高运行速度，通常会采用多指令发射、乱序执行等各种措施。现在普遍使用的一些超标量处理器通常能够在一个指令周期内并发执行多条指令。处理器从L1 I-Cache预取了一批指令后，就会分析找出那些互相没有关联可以并发执行的指令，然后送到几个独立的执行单元进行并发执行。比如下面这样的代码（假定编译器不做优化）： &lt;pre&gt;z = x + y;&lt;br&gt;p = m + n;&lt;/pre&gt;
&lt;p&gt;CPU就有可能将这两行无关代码分别送到两个算术单元去同时执行。像Freescale的MPC8541这种嵌入式处理器一个指令周期能够加载4条指令、发射2条指令到流水线、用5个独立的执行单元来并发执行。 
&lt;p&gt;通常来说访存指令（由LSU单元执行）所需要的指令周期可能很多（可能要几十甚至上百个周期），而一般的算术指令通常在一个指令周期就搞定。所以有 可能代码中的访存指令耗费了多个周期完成执行后，其他几个执行单元可能已经把后面有多条逻辑上无关的算术指令都执行完了，这就产生了乱序。 
&lt;p&gt;另外访存指令之间也存在乱序的问题。高级的CPU可以根据自己Cache的组织特性，将访存指令重新排序执行。访问一些连续地址的可能会先执行，因 为这时候Cache命中率高。有的还允许访存的Non-blocking，即如果前面一条访存指令因为Cache不命中，造成长延时的存储访问时，后面的 访存指令可以先执行以便从Cache取数。对写指令的访存乱序有可能造成的错误后果，所以处理器通常有专门的机制（通常是做了个缓冲）保证在出现异常或者 错误的时候，可以丢弃异常点后面的写指令的结果不做写入。 
&lt;p&gt;处理器的分支预测功能也能引起并发执行。处理器的分支预测单元有可能直接把两条分支的指令都预取来一块并发执行掉。等到分支判断的结果出来以后，再丢弃错误分支的计算结果。这样在很多情况下可以实现0周期跳转。比如这样的代码（假定编译器不做优化）： &lt;pre&gt;z = x + y; &lt;br&gt;if (z &amp;gt; 0) then&lt;br&gt;    p = m + n;&lt;br&gt;else&lt;br&gt;    p = m - n;&lt;/pre&gt;
&lt;p&gt;看上去如果z不计算出来是无法继续的。但是实际上CPU有可能先把三个加法都同时进行计算，然后根据z=x+y的结果直接挑选正确的p值。 
&lt;p&gt;因此，即使是从汇编上看顺序正确的指令，其执行的顺序也是不可预知的。处理器能够保证并发和乱序执行不会得到错误结果，但是如果是对一些硬件寄存器 的操作不能允许乱序的话，程序员就必须把这个情况告诉CPU。告诉的方法就是通过CPU提供的一组同步指令实现，通常在CPU的文档里面有对同步指令的使 用说明。系统函数库里面的内存屏障（rmb/wmb/mb）实际上也是通过这些同步指令实现的。因此在C编码的时候，只要设置好内存屏障，就能告诉CPU 哪些代码是不能乱序的。 &lt;/div&gt;
&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3&gt;&lt;a&gt;&lt;/a&gt;编译器的乱序优化&lt;/h3&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;受到处理器预取单元的能力限制，处理器每次只能分析一小块指令的并发性，如果指令相隔比较远就无能为力了。但是从编译器的角度来看，编译器能够对很 大一个范围的代码进行分析，能够从更大的范围内分辨出可以并发的指令，并将其尽量靠近排列让处理器更容易预取和并发执行，充分利用处理器的乱序并发功能。 所以现代的高性能编译器在目标码优化上都具备对指令进行乱序优化的能力。并且可以对访存的指令进行进一步的乱序，减少逻辑上不必要的访存，以及尽量提高 Cache命中率和CPU的LSU（load/store unit）的工作效率。所以在打开编译器优化以后，看到生成的汇编码并不严格按照代码的逻辑顺序是正常的。和处理器一样，如果想要告诉编译器不要去对某些 指令乱序优化，也要通过一些方式来告诉编译器。通常可以通过volatile关键字来抑制（注意，不是禁止）编译器对相关变量的访问优化。举个例子： &lt;pre&gt;int *p, *q; &lt;br&gt;......; &lt;br&gt;*p = 1; &lt;br&gt;*p = 2; &lt;br&gt;*q = *p;&lt;/pre&gt;
&lt;p&gt;这样，编译器通常会优化掉前面一个对*p的写入（逻辑上冗余），仅对*p写入2。而对*q赋值的时候，编译器认为此时*q的结果就应该是上次*p的值，会优化掉从*p取数的过程，直接把在寄存器中保存的*p的值给*q（PowrPC汇编）： &lt;pre&gt;（假设r3=p，r4=q） &lt;br&gt;li   r5, 2      // r5赋值2 &lt;br&gt;stw  r5, 0(r3)  // 把r5写到*p &lt;br&gt;stw  r5, 0(r4)  // 把r5写到*q&lt;/pre&gt;
&lt;p&gt;但是如果为p指针加上了volatile关键字，情况就不同了： &lt;pre&gt;volatile int *p; &lt;br&gt;int *q; &lt;br&gt;......; &lt;br&gt;*p = 1; &lt;br&gt;*p = 2; &lt;br&gt;*q = *p;&lt;/pre&gt;
&lt;p&gt;在这种情况下，编译器看见*p是volatile的时候，就会： 
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;不对*p操作生成乱序指令（通常如此，具体请看后面的解释） 
&lt;li&gt;
&lt;p&gt;每次从*p取数据的时候，一定会进行一次访存操作，哪怕前面不久才取过*p的值放在寄存器里。 
&lt;li&gt;
&lt;p&gt;不合并对*p的写操作（也只是通常如此，解释见后）&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;所以这回的结果如下（PowrPC汇编）： &lt;pre&gt;（假设r3=p，r4=q） &lt;br&gt;li   r5, 1      // r5赋值1 &lt;br&gt;stw  r5, 0(r3)  // 把r5写到*p &lt;br&gt;li   r5, 2      // r5赋值2 &lt;br&gt;stw  r5, 0(r3)  // 把r5写到*p &lt;br&gt;lwz  r5, 0(r3)  // 从*p取值到r5 &lt;br&gt;stw  r5, 0(r4)  // 把r5写到*q&lt;/pre&gt;
&lt;p&gt;这样编译器会在汇编码级别保证指令有序和不优化掉访存操作。通常简单地使用volatile关键字就可以解决编译器的乱序问题，但是这些指令到了处理器执行的时候，仍然可能被乱序。对于处理器乱序执行的避免就需要用到一组内存屏障函数（barrier）了。 
&lt;div style="margin-left:0.5in;margin-right:0.5in"&gt;
&lt;table summary=Important border=0&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=top align=middle width=25 rowspan=2&gt;
&lt;th align=left&gt;重要 
&lt;tr&gt;
&lt;td valign=top align=left&gt;
&lt;p&gt;绝大多数的编译器，通常不会优化掉对volatile对象的访问，并且通常保持同一个volatile对象的一系列读写操作是有序的（但是不能保证不同的volatile对象之间有序）。 
&lt;p&gt;但是，这不是绝对的。因为ANSI C99标准关于对volatile对象访问时编译器是否要绝对保证禁止乱序（reorder）和禁止访问合并（combine access）并没有做任何规定！仅仅是鼓励编译器最好不要去优化对volatile对象的访问，而唯一的强制要求仅仅是要求编译器保证对volatile对象的访问优化不会跨越“sequence point”即可（所谓sequence point是指一些诸如外部函数调用、条件或循环跳转等关键点，具体定义请查阅C99标准内的详细说明）。 
&lt;p&gt;这就是说，如果一个编译器在两个sequence point之间像对待普通变量一样去优化volatile变量，也是完全符合C99标准的！比如：&lt;pre&gt;volatile int a;

if (...) { ... }  // sequence point
a = 1;
a = 2;
a = 3;
printk(&amp;quot;...&amp;quot;);    // sequence point&lt;/pre&gt;
&lt;p&gt;在两个sequence point之间，要是有编译器对a的赋值操作合并（即仅写入3）或者乱序（如写1和写2对调），都是完全符合C99标准的。所以，我们在使用的时候，不能指望用了volatile以后绝对能生成有序的完整的汇编码，即不要指望volatile来保证访存有序。实质上 volatile最大的作用主要还是在保证每次使用从内存中取值，而并不能保证编译器不做其他任何优化（毕竟volatile从字面上看意思是“易变”而不是“有序”。编译器只保证对volatile对象即时更新但不保证访问有序也不是说不过去的）。
&lt;p&gt;从另一个角度看，即使是编译器生成的汇编码有序，处理器也不一定能保证有序。就算编译器生成了有序的汇编码，到了处理器那里也拿不准是不是会按照代码顺序执行。所以就算编译器保证有序了，程序员也还是要往代码里面加内存屏障才能保证绝对访存有序，这倒不如编译器干脆不管算了，因为内存屏障本身就是一个sequence point，加入后已经能够保证编译器也有序。 
&lt;p&gt;因此，对于切实是需要保障访存顺序的代码，就算当前使用的编译器能够编译出有序的目标码来，我们也还是必须通过设置内存屏障的方式来保证有序，否则都是不严谨，有隐患的。&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3&gt;&lt;a&gt;&lt;/a&gt;Barrier屏障函数&lt;/h3&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Barrier函数可以在代码中设置屏障，这个屏障可以阻挡编译器的优化，也可以阻挡处理器的优化。 
&lt;p&gt;对于编译器来说，设置任何一个屏障都可以保证： 
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;编译器的乱序优化不会跨越屏障，即屏障前后的代码不会乱序； 
&lt;li&gt;
&lt;p&gt;在屏障后所有对变量或者地址的操作，都会重新从内存中取值（相当于刷新寄存器中的变量副本）。&lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;而对于处理器来说，根据不同的屏障有不同的表现（以下仅仅列举3种最简单的屏障）： 
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;&lt;strong&gt;读屏障rmb()&lt;/strong&gt;&lt;/span&gt; &lt;br&gt;处理器对读屏障前后的取数指令（LOAD）能保证有序，但是不一定能保证其他算术指令或者是写指令的有序。对于读指令的执行完成时间也不能保证，即它不能保证在屏障之前的读指令一定都执行完成，只能保证屏障之前的读指令一定能在屏障之后的读指令之前完成。 
&lt;li&gt;
&lt;p&gt;&lt;span&gt;&lt;strong&gt;写屏障wmb()&lt;/strong&gt;&lt;/span&gt; &lt;br&gt;处理器对屏障前后的写指令（STORE）能保证有序，但是不一定能保证其他算术指令或者是读指令的有序。对于写指令的执行完成时间也不能保证，即它不能保证在屏障之前的写指令一定都执行完成，只能保证屏障之前的写指令一定能在屏障之后的写指令之前完成。 
&lt;li&gt;
&lt;p&gt;&lt;span&gt;&lt;strong&gt;通用内存屏障mb()&lt;/strong&gt;&lt;/span&gt; &lt;br&gt;处理器保障只有屏障之前的访存操作（包括读写）都完成以后才会执行屏障之后的访存操作。即可以保障读写之间的有序（但是同样无法保证指令完成的时 间）。这种屏障对处理器的执行单元效率产生的负面影响要比单纯用读屏障或者写屏障来的大。比如对于PowerPC来说这种通用屏障通常是使用sync指令实现的，在这种情况下处理器会丢弃所有预取的指令并清空流水线。所以频繁使用内存屏障会降低处理器执行单元的效率。 &lt;/ol&gt;&lt;/div&gt;
&lt;p&gt;对于驱动开发者来说，一些对设备寄存器的操作，通常是必须保证有序的。在绝大部分情况下，一般都是写操作。对于有序的写操作，必须设置写屏障（wmb）： 
&lt;div&gt;&lt;a&gt;&lt;/a&gt;
&lt;p&gt;&lt;strong&gt;例：在驱动中使用写屏障&lt;/strong&gt; &lt;pre&gt;/* Mask out everything */ &lt;br&gt;im_intctl-&amp;gt;ic_simrh = 0x00000000; &lt;br&gt;im_intctl-&amp;gt;ic_simrl = 0x00000000;&lt;/pre&gt;&lt;pre&gt;wmb();  &lt;/pre&gt;&lt;pre&gt;/* Ack everything */ &lt;br&gt;im_intctl-&amp;gt;ic_sipnrh = 0xffffffff;
im_intctl-&amp;gt;ic_sipnrl = 0xffffffff;&lt;/pre&gt;
&lt;p&gt;这是一个对中断控制器操作的例子。在设置两个mask寄存器的值的时候，这两个写操作没有顺序要求，因此可以不加屏障。但是对ack寄存器的设置必须在mask寄存器完成设置以后，所以在中间要加入写屏障wmb()以保证对两组寄存器的写有序。 &lt;/div&gt;
&lt;p&gt;同样的，对于一系列的只读操作，也可以简单使用rmb()来保证有序。 
&lt;div style="margin-left:0.5in;margin-right:0.5in"&gt;
&lt;table summary=Note border=0&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=top align=middle width=25 rowspan=2&gt;&lt;br&gt;
&lt;th align=left&gt;注意 
&lt;tr&gt;
&lt;td valign=top align=left&gt;
&lt;p&gt;任何一个rmb()或者wmb()都是可以被替换成mb()的。但是因为上面提到过的mb()的效率问题，所以应该只有在同时需要读屏障和写屏障的时候，才建议使用mb()。否则应该根据实际情况来选择合适的屏障。当然，在设备初始化的时候，即使是使用mb()也不会对性能带来什么影响，因为设备一般只会初始化一次。但是在发生很频繁的设备操作（比如网口的收发帧中断等）时，应该考虑到mb()对性能的影响。 &lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;如果驱动不仅仅需要在单纯的读指令或者写指令之间有序，还需要保证读写指令之间有序的时候，就需要设置mb()屏障了。下面将演示一个这样的例子： 
&lt;div&gt;&lt;a&gt;&lt;/a&gt;
&lt;p&gt;&lt;strong&gt;例：使用mb()屏障保证读写有序&lt;/strong&gt; 
&lt;p&gt;我们假设有一个设备，在读取设备信息时需要依次对REG1～3这三个寄存器进行写入操作（写入设备读取命令），然后才能依次读取REG4和REG5取得设备返回的信息。 &lt;pre&gt;REG1 = a; &lt;br&gt;wmb();  // 保证REG1和REG2的写有序&lt;br&gt;
REG2 = b; &lt;br&gt;wmb();  // 保证REG2和REG3的写有序&lt;br&gt;
REG3 = c;&lt;br&gt;
mb();   // 保证在对设备读之前，前面的配置操作都完成（读写之间有序）&lt;br&gt;
*d = REG4; &lt;br&gt;rmb();  // 保证REG4和REG5的读有序&lt;br&gt;
*e = REG5;&lt;br&gt;
mb();   // 保证与未来对设备的操作有序 &lt;br&gt;return;&lt;/pre&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;对于REG1～3的写入，可以通过设置写屏障来保证有序； 
&lt;li&gt;
&lt;p&gt;在进行REG4和5的读取之前，因为得保证前面的寄存器写操作都执行完才能读，所以需要设置一个内存屏障mb()来保证前面对寄存器的写都完成，以保障读写指令之间的有序； 
&lt;li&gt;
&lt;p&gt;后面两个读操作之间就可以通过设置读屏障来保证有序了； 
&lt;li&gt;
&lt;p&gt;最后通常在从设备操作函数返回之前，我们一般需要保证对设备的操作都执行完毕了。这样下次对设备进行操作的时候我们可以保证设备已经完成了上次操作，避免反复调用设备操作函数带来的函数间的乱序问题。所以在最后设置一个内存屏障mb()，保障和未来对设备的其他访问有序。&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div lang=zh-cn&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3&gt;&lt;a&gt;&lt;/a&gt;进一步阅读&lt;/h3&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;如果还想进一步了解内存屏障的有关信息，特别是关于多处理器系统中的内存屏障，可以阅读： 
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Linux内核源码附带的《LINUX KERNEL MEMORY BARRIERS&lt;a&gt;&lt;/a&gt;》by &lt;span&gt;&lt;em&gt;David Howells&lt;/em&gt;&lt;/span&gt; &lt;code&gt;&amp;lt;&lt;a href="mailto:dhowells@redhat.com"&gt;dhowells@redhat.com&lt;/a&gt;&amp;gt;&lt;/code&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+%e4%b9%b1%e5%ba%8f%e6%89%a7%e8%a1%8c%e5%92%8c%e5%86%85%e5%ad%98%e5%b1%8f%e9%9a%9c&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1017.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1017.entry</guid><pubDate>Thu, 25 Oct 2007 15:13:24 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1017/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!1017.entry#comment</wfw:comment><dcterms:modified>2007-10-26T12:54:19Z</dcterms:modified></item><item><title>自己打造的等宽字体99.9％完成，和Slickedit 12.0.3发布</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!968.entry</link><description>周末终于下狠心弄了一个下午，完成了我的等宽编程字体的所有可见字符的绘制，对于不可见字符也画成显示其HEX编码的样子方便查看。&lt;br&gt;
目前的字体字符如下图（Flickr!图片），有7×14、8×16正常和粗体总共4套：&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm2.static.flickr.com/1243/1238255351_aaaaed51ce_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
字体是Sans Serif的，我一直比较喜欢这种类型。现在是完全的光栅字体（Raster Font），在某些Java程序里面不能用。有空研究研究没准能弄一个嵌入点阵的TTF字体解决这个问题。不过目前我用的编辑器全部都支持FON光栅字体，所以也没什么迫切需求。对于自己没需求的东西，做起来一向是很拖拉很懒得弄的，就象这个字体的非ANSI字符部分就拖拖拉拉磨了一个多月才做好。&lt;br&gt;
&lt;br&gt;
另外昨晚顺便将Slickedit升级到最新的12.0.3。本来以为又要重新恢复我的自定义菜单什么的准备大干一场，结果装好以后发现自定义菜单居然破天荒地没有丢！！唯一丢掉的配置是我的Workspace分类，很快就还原了。不知道是SE有了改进还是这次的升级实在是太minor的缘故。如果是SE真的解决升级丢自定义菜单的问题那就太棒了！&lt;br&gt;
&lt;br&gt;
说到12.0.3这个版本，倒是还真没发现有啥更新的，至少看不出来。不过在我合并我对SE源码的修改的时候发现那个Buggy的Code Annotations倒是有很多修改，还有Files Toolbar什么的。估计这次可能纯粹是一个Bug Fix的升级，猜测这应该就是SE 2007的终极版本了，下一个版本可能就要到SE v13啦！&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+%e8%87%aa%e5%b7%b1%e6%89%93%e9%80%a0%e7%9a%84%e7%ad%89%e5%ae%bd%e5%ad%97%e4%bd%9399.9%ef%bc%85%e5%ae%8c%e6%88%90%ef%bc%8c%e5%92%8cSlickedit+12.0.3%e5%8f%91%e5%b8%83&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!968.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!968.entry</guid><pubDate>Sun, 26 Aug 2007 09:41:44 GMT</pubDate><slash:comments>8</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!968/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!968.entry#comment</wfw:comment><dcterms:modified>2007-08-26T09:41:44Z</dcterms:modified></item><item><title>自己打造的编程字体完成95％</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!955.entry</link><description>周末在家狂画，已经完成了ASCII码0x21～0x7E范围内的所有字符，包括7×14点阵和8×16点阵的粗体和细体各一套。&lt;br&gt;
&lt;br&gt;
现在自己正在使用这套字体暗爽，并且在使用中不断地对字符进行微调。字体在粗体和细体状态下都是绝对等宽的，因此在使用粗体混显高亮的时候也能得到精确的等宽效果。并且字符点阵完全控制在标准点阵汉字的一半，所以和汉字混显也能保证精确保持和双字节字符的宽度关系。&lt;br&gt;
&lt;br&gt;
在Slickedit下的效果如下，小的是7×14点阵，大的是8×16点阵。观看图片需要Firefox ＋ Access Flickr!。&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm2.static.flickr.com/1145/869403607_a8dd6cc099_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm2.static.flickr.com/1297/869403871_dbee113d2f_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
这个字体完全是为了在高分辨率显示器上进行长时间编码并且有中文和粗体混显需求的应用设计的。因此不会有6×12的版本，也不会有8×16以上的版本（这尺寸以上字体太大且没有对应的点阵中文）。&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+%e8%87%aa%e5%b7%b1%e6%89%93%e9%80%a0%e7%9a%84%e7%bc%96%e7%a8%8b%e5%ad%97%e4%bd%93%e5%ae%8c%e6%88%9095%ef%bc%85&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!955.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!955.entry</guid><pubDate>Sun, 22 Jul 2007 14:36:38 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!955/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!955.entry#comment</wfw:comment><dcterms:modified>2007-07-22T14:36:38Z</dcterms:modified></item><item><title>开始打造自己的编程用等宽字体</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!954.entry</link><description>寻觅了几乎所有的等宽字体，都没有找到完全满意的。目前只有在8×16和6×12两个点阵上有比较合适的等宽点阵字体的选择，但是在两者中间的7×14尺寸上还没有看到什么合适的。&lt;br&gt;
&lt;br&gt;
我对编程字体的要求如下：&lt;br&gt;
&lt;ol&gt;&lt;li&gt;必须是点阵字体，至少是内嵌点阵。我比较喜欢中等大小的字体，也就是介于9pt到12pt之间的10－11pt左右的字号。在这个字号上面，纯TTF字体在打开Cleartype以后笔划都变得不是很锐利和醒目。长时间看了觉得疲劳。还是原始的干净锐利的点阵字体最适合长时间工作。&lt;li&gt;宽度必须是高度的一半，这样才能和中文完美配合显示。这个要求就将很多8×14这种尺寸的优秀字体拒之门外。因为我们美丽的中文的特殊性，如果不能满足这种长宽比，中文显示就会支离破碎非常难看令人无法忍受。而且，中文点阵应该只有12px，14px和16px。所以这就把可选的英文字号选择限定死在6×12，7×14和8×16上。&lt;li&gt;必须支持同等宽度的粗体。这个我实际做了才知道，6×12是没有可能完成英文粗体的。典型就是英文字母“M”和“m”。因为在6px的宽度里面，还要扣掉字符间间距的1px（否则字符全部会黏在一块），所以可用的宽度只有5px。而“m”的三竖加上之间的两道空白，就正好吃掉了完整的5px。没有任何余地进行加粗处理。所以6×12粗体要做到可以接受和识别的程度是没有办法的。&lt;li&gt;对于编码时候容易混淆的符号，必须能清晰区分。典型的问题就是字符：Ｉｌ１，０Ｏ这类容易混淆字符。看到几个字符不好区分的（比如新宋体），立马是丢掉的。&lt;li&gt;要是非衬线字体（Sans Serif）。出于不知名的原因，我讨厌Serif类字体，比如Courier系列和新宋体。而喜欢Sans Serif类字体，比如Arial，Verdana等。&lt;br&gt;
&lt;li&gt;{}[]()的显示要好看，最好要够醒目。对于C/C++/Java程序员来说，如果所使用的代码编辑器不能提供对括号加粗的功能的话，太细的括号不够醒目，在阅读代码的时候很容易疲劳出错。我曾经看一段嵌了很多括号的表达式，如果括号无法加粗的话，一眼看上去真是要吐血。&lt;li&gt;分号“；”要够显眼，理由同上。太细的分号在写C/C++/Java的时候总是容易被忽略。&lt;li&gt;附加要求：星号“*”要和其他字母的中间对齐。我真的是很讨厌那种*比较高位于字符上半部的那种字体设计。实在是很讨厌，在写取指针值或者是写乘法的时候高高的星号令我厌恶，看了就觉得代码不整齐。&lt;/ol&gt;目前能够满足上面绝大部分的要求，在6×12上是零（如果去掉粗体的要求，则有几个非常棒的选择，比如ProFont和Terminus 12n），而且我没法做（因为粗体的缘故）。再则，这个字号实在是太小了，可能我以前用1024×768这种低分辨率的显示器的时候还能用（那时候我就是用ProFont），现在上了IBM的高分屏，14寸1400×1050，看一眼就要昏倒了。在7×14上基本是零，因为粗体的缘故，大部分字体都是做成8×14（做7×14处理粗体M，m，W，w实在是非常困难，我也只能尽量做到看上去不觉得太怪），和中文配合都没法很好地显示。至于8×16，就比较多选择了：Raize，Terminus 16n/b都是非常棒的8×16等宽点阵字体。&lt;br&gt;
&lt;br&gt;
因此，我决定先从7×14这个尺寸入手，填上这个空白。而且我个人也比较喜欢这种字号，不大不小一个屏幕能显示足够多行，但是又不至于太小到要眯着眼看。至于8×16的，Raize和Terminus已经非常好了，不用浪费太多时间弄。&lt;br&gt;
&lt;br&gt;
目前我已经完成了一个初步可用的7×14字体，目前只是在做MmWw粗体上遇到了麻烦（因为实际可用点阵只有6×14，基本塞不下这类具有3个竖笔划的字体～～），不过已经尽力用我可以接受的方式处理了。由于是Fon点阵字体，因此不能支持jEdit等用Java开发的编辑器（不过Eclipse可以）。在Eclipse和gVIM下的效果如下：&lt;br&gt;
&lt;strong&gt;&lt;font color="#ff0000"&gt;（要看图片请使用Firefox ＋ Access Flickr!）&lt;/font&gt;&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;
在Eclipse下的粗体混显显示效果（注意，中文实际上Eclipse显示有点问题没有等宽。实际上在除了Eclipse以外的软件都是用14×14的点阵中文显示的）：&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm2.static.flickr.com/1228/852850252_3514d2e07a_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
在gVIM下的粗体混显显示效果。在这个例子里面，我没有打开{}()[]和;号的加粗显示。图中这些字符的加粗效果都是字体本身做的，即使是在正常非粗体状态下也会被显示成粗体，程序员专用。&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm2.static.flickr.com/1199/851987315_06ffd238ed_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
目前俺的字体还在精雕细琢中，等到搞定了7×14，再弄个与之相配的8×16的，那就完美了～～&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+%e5%bc%80%e5%a7%8b%e6%89%93%e9%80%a0%e8%87%aa%e5%b7%b1%e7%9a%84%e7%bc%96%e7%a8%8b%e7%94%a8%e7%ad%89%e5%ae%bd%e5%ad%97%e4%bd%93&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!954.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!954.entry</guid><pubDate>Thu, 19 Jul 2007 16:32:09 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!954/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!954.entry#comment</wfw:comment><dcterms:modified>2007-07-19T16:32:09Z</dcterms:modified></item><item><title>Megatops BinCalc Desktops正式发布</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!806.entry</link><description>我的BinCalc已经正式发布了，可以在PalmGear下载。&lt;br&gt;
&lt;br&gt;
相比上次的预发布版，主要做了如下修改：&lt;br&gt;
&lt;ul&gt;&lt;li&gt;版本号改成了和PalmOS版本相同的版本号以便统一&lt;li&gt;三个进制的显示部分增加了右键菜单可以从剪贴板粘贴和以多种格式Copy出来，方便分析调试输出的结果&lt;/ul&gt;最终版界面如下：&lt;br&gt;
&lt;br&gt;
&lt;img src="http://farm1.static.flickr.com/176/385327875_8bc5737330_o.png" alt=""&gt;&lt;br&gt;
&lt;br&gt;
下载地址：&lt;a href="http://www.palmgear.com/index.cfm?fuseaction=software.showsoftware&amp;amp;PartnerREF=&amp;amp;siteid=1&amp;amp;prodID=117429"&gt;PalmGear&lt;/a&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=-8509478205381187897&amp;page=RSS%3a+Megatops+BinCalc+Desktops%e6%ad%a3%e5%bc%8f%e5%8f%91%e5%b8%83&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=superding.spaces.live.com&amp;amp;GT1=superding"&gt;</description><comments>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!806.entry#comment</comments><guid isPermaLink="true">http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!806.entry</guid><pubDate>Sat, 10 Feb 2007 09:30:16 GMT</pubDate><slash:comments>3</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://superding.spaces.live.com/blog/cns!89E842A8485366C7!806/comments/feed.rss</wfw:commentRss><wfw:comment>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!806.entry#comment</wfw:comment><dcterms:modified>2007-02-10T09:30:16Z</dcterms:modified></item><item><title>BinCalc Desktop版基本开发完成</title><link>http://superding.spaces.live.com/Blog/cns!89E842A8485366C7!803.entry</link><description>又经过一个晚上的折腾，我的BinCalc Desktop（相对于我去年的手机版BinCalc而言）基本完成了，目前我自己已经用上了。我设计的BinCalc是个功能非常专一（二进制计算和显示）、面向的用户群非常狭小（基本上只有底层软硬件开发者才会感兴趣）、界面非常另类的计算器。基本上是专门为我自己定制的特殊的计算器。相对于最初的PalmOS手机版，桌面版的BinCalc做了一些改进：&lt;br&gt;
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;增强的位指示器：&lt;/strong&gt;&lt;ul&gt;&lt;li&gt;位指示器的标尺有8种（PalmOS版本只做了2种，因为PalmOS上面做起来非常麻烦）：&lt;br&gt;
&lt;ul&gt;&lt;li&gt;31－0标记的经典方式（一般Intel的32bit寄存器采用的标记方式）；&lt;li&gt;16－0，16－0的标记方式。用于看16bit的寄存器文档（多用于开发PCI设备驱动）；&lt;li&gt;8－0，8－0，8－0，8－0的标记方式，用于看8bit寄存器文档（单片机或者串口、I2C之类的驱动）；&lt;li&gt;63－32标记的方式。可能很少接触过，但是我看过的一些BookE处理器的文档就是使用这种变态的标注方式（因为这些寄存器是64bit兼容的）。当然还有一种BT无敌的用法就是打开两个BinCalc，共同来看一个64bit的寄存器～～&lt;li&gt;以上方式的倒序版本（即0－31，倒过来），这个是因为FreeScale的处理器文档里面喜欢用0－31这样MSB标0，LSB标高的方式来表示Big-Endian字节序的寄存器；用MSB标高，LSB标0（和Intel的标记方式差不多）的方式来表示Little-Endian的寄存器。我主要是和FreeScale的PowerPC/BookE处理器打交道，里面基本上全是用0－31或者32－63的标记方式来标记位。&lt;/ul&gt;&lt;li&gt;每个位的Hint（即鼠标放上去以后显示的提示）表示的是在当前标注方式下的位序号。所以只要鼠标放上去立马知道这个位的序号，无敌方便脑子都不用动。&lt;li&gt;二进制显示以Nibble为单位分段显示，看起来好读多了。PalmOS版本挤在一块是因为160像素的宽度能挤32个1010下去我已经觉得非常神奇了，不能奢望还能在里面插入空格。&lt;li&gt;增加了Char显示，实际上实在是个无聊的很的功能，但是我实在不知道右边这块还能做什么用，只好加上。原来PalmOS版本的时候一开始也是有类似这样的字符显示功能的。但是在我为那块空间找到用处以后很快就把这个功能扔掉了～～&lt;/ul&gt;&lt;li&gt;&lt;strong&gt;增强的单目位操作：&lt;/strong&gt;&lt;br&gt;
对于所有的RPN寄存器（XYZT）都能直接进行左右移位和取反（翻转）等单目位操作。这样有什么好处呢：&lt;ol&gt;&lt;li&gt;俺的界面设计问题：如果不把这些左右移位和取反的按钮加上去，会空出来很多地方很难看也很难对齐(＞﹏＜)；&lt;li&gt;实际使用的方便：如果你一边看文档一边算掩码，可能你在对着文档数掩码的时候还不能知道等下这个掩码到底是要取反and还是要直接or甚至可能要shift几个Field再来计算。所以我给了一个可以在进行计算的最后关头做决定的机会：在最终进行计算之前你可以根据需要直接把掩码做处理以后再来算&lt;/ol&gt;&lt;li&gt;&lt;strong&gt;增强的双目计算：&lt;/strong&gt;&lt;ul&gt;&lt;li&gt;支持算术计算（+-*/）：&lt;br&gt;
Palm版本不能支持的原因完全是因为界面上面实在是无法再挤进再多一个按钮了，根本没有地方给+-/*。PC的版本就没有这种问题，没理由不加。当然要支持更多的运算操作自然也没有问题，但是对于底层开发来说毫无意义：实际上+-/*都几乎用不到，主要还是用&amp;amp;^|位运算和mod取模。&lt;li&gt;改用逆波兰表达式计算器：&lt;br&gt;
Palm的版本用的还是常见的顺序表达式输入方式。但是桌面版我改成逆波兰（RPN）计算了，因为实际上好处是非常多的：&lt;ol&gt;&lt;li&gt;在你不需要用RPN计算功能的时候，4个寄存器的RPN栈还能当作记忆存储器使：你可以输入一个数Push进去，再输入一个再Push……就当作暂存器用了，省的记在草稿纸或者记事本里面。&lt;li&gt;在看文档的时候，RPN计算真的很方便。如果你几乎没有用过RPN表达式可能完全不会赞同我的观点。但是回想看处理器文档的时候，经常是你先有了准备进行计算的数字（或掩码），最后才能判断出需要做什么计算操作。也就是说很经常是先知道了X，Y以后才知道到底是要X | Y还是X &amp;amp; ～Y。如果这时候你用顺序表达式的话，很可能得先找个地方记录两个数然后等到你知道了需要的操作以后才能整个表达式输入进行计算。用RPN就没有这个问题：想到一个数就先Push进去，等到数字都Push进去了，再决定需要的运算操作就好了。而且在运算前，我的BT的无处不在的单目计算按钮还能让你对操作数进行一些位处理。当然如果在你已经知道了完整的的表达式仅仅是急于计算结果的时候，RPN就很难用了——不过既然这样了你还用我这个BinCalc做什么～～这个本来就是帮助你看文档和思考的，而不主要是帮你计算。计算问题交给Windows自带的计算器就足够了～～&lt;/ol&gt;&lt;li&gt;RPN栈增加了上下移动的操作：&lt;br&gt;
正常情况下RPN计算器一般是不能让你随便去调整堆栈顺序的。最多Swap XY寄存器的位置。不过我想了想，增加这个功能大有好处：增加了上下移动堆栈结合XY Swap功能以后，你可以把堆栈里面的任意两个数字调换到X，Y处进行计算。所以在你思考的时候压入堆栈的数字任意两个都能拉出来开刀。而且我把RPN计算器的栈设计的很小（只有最最经典的4个，实际上对于位运算来已经绰绰有余了），所以进行调整实际上是非常简单的只需要很少的操作（当然如果只有3个寄存器那是最简单了，4个稍微复杂一丁点，不过调整起来和玩数字拼图游戏有点类似，还是蛮有意思的）。除了对寄存器的顺序进行调整以