| Profiel van 猪哥猪哥的BlogWeblogLijstenGastenboek | Help |
|
|
4-8-2009 Droid Sans Mono with Slashed Zero我有收藏各种等宽字体的嗜好,尤其稀饭Sans类等宽字体。不过看到有的等宽字体的0居然不带点或者斜杠就牙痒痒,非得改之而后快。 这个Android的Droid Sans Mono字体居然也有如此低级错误,0和O不分。所以俺就自己动手给它的0加上了一条华丽的斜杠,效果如下: 带了斜杠以后看上去就舒服多了。btw:我喜欢带斜杠的0(Slashed Zero),不喜欢带点的。做带点的0多半原因是因为简单,只要在中间瞎涂一个黑点就敷衍过去了。计划把我系统里所有0带点的Sans Mono类字体都搞成Slashed Zero(# ̄▽ ̄#)。 下载:Droid Sans Mono with Slashed Zero 17-7-2009 YaTFTPSvr 1.0正式版发布YaTFTPSvr 1.0正式版发布,自从上次预告以来没有再增加别的新功能。再次强调:这个工具仅仅面向社会上一小撮嵌入式或底层软件开发人员,广大不明真相的群众请无视之~~ 原本想做个气势磅礴的大盒子图片来配合本次发行,不过到后来也还是一直忙得焦头烂额没时间做了。所以这次就素颜裸发了,除了文字以外什么也没有,囧rz。反正对这个东西感兴趣的也一定关注过我以前关于这东西的文章了,该知道的应该也都知道了吧俺就不废话了。以后有空会像那个BinCalc那样给它立个转正后的专门页面,不过现在还是没时间折腾~~ 暂时可以从这里下载(盒子里也有):http://zhaojie.ding.googlepages.com/TFTPSvr.zip 12-7-2009 YaTFTPSvr将增加流量统计功能8-7-2009 YaTFTPSvr新版预告9-6-2009 拼音加加皮肤增强外挂AlphaJJ更新话说微软大爷最近生Bing,搞得我的Blog也被波及被伟大的网络人间奇迹GFW给ban了几天。经历了上次的Blog被Flickr封杀的事件后弄得俺是疑神疑鬼以为是不是俺的Blog又摸到了哪个大爷的逆鳞给ban了。不过后来发现所有人的Live Space都上不去以后俺才长吁一口气,等着MS做公关了。虽然MS做搜索比不过谷歌,但是公关却比谷歌强的多。谷歌的Blogger之类服务一被封杀就永无出头之日了,MS的却通常能在一周内解封。所以虽然MS Live Space有诸多不爽和恶心之处,我还是觉得抱着MS的水桶腰要比搂着谷歌的小蛮腰来的牢靠点。不过MS这几年做搜索还真是有耐心,跟东莞的那些山寨MP3厂似的一个品牌做烂了就换个马甲重新来。只不过从MS一贯的表现来看,每推出一次搜索服务,只不过多证明一次MS没有做好搜索的能力罢了。 上周末把我的拼音加加输入法的皮肤增强外挂:AlphaJJ给改进了。这回能支持如下两种效果(不能同时使用): 1. 输入栏半透明效果 ![]() 2. 不规则输入栏效果 ![]() 拼音加加这种老牌输入法皮肤不支持不规则不支持半透明真是令人发指啊,可能在所有的主流拼音输入法当中就属拼音加加的皮肤功能最差了。加了俺丑陋的小外挂后,看上去就好了点(不过我还是在用搜狗拼音,目前还没有换回拼音加加的念头)。 ![]() 东西在我的盒子里下载,Patches目录下。 21-2-2009 猪哥的无敌TFTP Server:YaTFTPSvr发布终于正式把名字给改掉了,正式改为YaTFTPSvr(Yet Another TFTP Server)。注意:除非你是做嵌入式或者底层开发,需要TFTP Server来往板子上下装Bootloader或者Firmware什么的。其余闲杂人等请无视这个小玩意。因为我这个东西的开发目的就是为了方便在调试的时候通过host端往target上下装程序,不面向网管维护等应用。 主要功能:
Virtual Folder: 这个功能加入的最主要理由是解决调试分布式设备时编译出来的Firmware散在不同的路径下,整机下装时需要频繁切换TFTP Server root的痛苦。最早我的0.1版本支持的Folder Tab书签其实就是为了要解决这个问题,但是解决的不够彻底(不过那时候我觉得每次能仅仅切换一下Tab就能更换root已经很爽了,可能现在用得要求又高了吧)。这回的Virtual Folder应该是可以把它彻底解决了。我自己用这个功能调试了一个多星期的内核,下装时明显安逸很多。 Virtual Folder的功能实际上很简单,就是可以把分散在不同路径下的文件拖到一个虚拟文件夹下,这样从TFTP Client端看来好像都在同一个root目录内可以直接下载。 如下启用Virtual folder功能:在根目录书签Tab处按右键弹出右键菜单,选Virtual folder模式(切换成Virtual folder以后原来此tab保存的Server root不会丢失,可以随时再切回来)。 ![]() 切换后会看到如下界面: ![]() 往虚拟文件夹添加文件有两种方法:
每次退出YaTFTPSvr的时候所有的配置都会自动保存到ini中,精心构造的Virtual folder列表不会丢失。 文件别名: 虚拟目录下的文件不允许重名。不过如果你需要把两个同名文件放在同一个虚拟目录下,可以给文件起个别名。另外一个用途是有些tool-chain配置的编译出来的文件名又臭又长,一辈子也记不住。所以可以给它起个简短的别名容易下载。 文件别名只能在Virtual folder模式下使用。单选一个虚拟文件项,右键菜单中就能找到Rename即可修改别名: ![]() 修改成功后Client端即可通过别名访问到对应的文件。 Server root书签预览: 书签预览增加了对Virtual folder模式的支持,鼠标指针放在处于Virtual folder模式的Tab上即显示其对应的虚拟文件夹的部分内容,方便寻找和切换自己需要的根目录配置: ![]() 文件拖拽支持: 使用拖拽功能可以快速设置根目录或像虚拟文件列表添加文件:
![]() 东西在我的盒子里面下载,老地方。 15-2-2009 TFTP Server更新时隔正好1年,又开始改进我的简陋的TFTP Server了。网上的TFTP Server一大堆,一直在考虑是不是要改个比较有个性的名字,比如叫Yet Another TFTP Server啥的,或者干脆叫YaTFTPSvr,看起来比较NB一点~~ 这次的改动源于我最近调试的痛苦。最近正在写一个OS内核,需要不断地往板子上下装编译好的内核以及需要在这个内核上加载运行的ELF文件。还有一个麻烦的是我用的BDI2000调试器正好又要通过TFTP获取配置文件和CPU初始化参数……这些文件都分布在不同的目录里。就算我原来的TFTP Server支持多Tab快速切换Server Root,也还是在调试时手忙脚乱切得眼花。所以这次终于下定决心加入了Virtual folder功能。 加入Virtual Folder功能后,正常情况下TFTP Server的界面和使用都没有任何变化。还是不需要任何配置的傻瓜用法。只是在Tab上右键单击的时候,可以将这个Tab切换到Virtual folder模式: ![]() 切换到Virtual folder模式后,服务器的Root就成了一个虚拟文件列表。把需要下载的文件通过Add或者直接拖拽丢到列表里面就可以了: ![]() 这样就可以把分散在不同地方的文件都拖进来,这样在通过TFTP Client下载的时候看上去就好像是位于同一个root目录下一样,方便。另外列表中的文件可以指定虚拟文件名。有时候Make出来的目标文件可能是一个很长很诡异的名字,下载的时候我总是要跳过去Copy一把文件名往Client端贴。有了重命名功能后,可以给名字又臭又长的文件指定一个简短好记的别名,比如我把第一个文件命名为abc,则Client端就可以通过abc这个名字来下载到test.c: ![]() 还在测试中~~未发布。不过也没几个人会用得着(﹀_﹀") 29-12-2008 Megatops ProCoder Font无敌编程字体粗体版在命令行界面的时候我喜欢粗笔画的字体显示(类似于用Fixedsys的那种感觉)。不过仅仅将终端软件的界面字体设置成粗体是不够的,因为如果中文也被显示成粗体的话看上去比较恶心不说,有的终端软件的字体宽度还会计算错掉(中文的粗体和非粗体并不等宽)。所以最终决定将Megatops ProCoder Font 1.0的GB2312版拿来修改,将标准体部分也替换成粗体字型。这样看上去的粗度就和Fixedsys的差不多了,不喜欢在终端里面用细字型的朋友,这回也没啥理由不用俺的无敌字体了吧哇哈哈。 在命令行界面中的使用效果如下:英文部分粗体显示,中文部分正常显示,所以中英文还是可以做到严格等宽。当然,如果有人习惯了在代码编辑器里面也用Fixedsys的,把这个字体放在代码编辑器里面用也是OK的。 ![]() 在我的盒子里面下载,老地方。也是需要导入里面的注册表后重启才能正常显示中文。 ps:这套字体的粗体部分被我锁了不准Windows自作主张将其伪加粗。想想Fixedsys在粗体时的表现吧…… 16-11-2008 关于Megatops BinCalc RPN计算器的说明最近收到几个好心人发来的邮件,指出我的BinCalc存在低级BUG,即1+1算出来不等于2~~鉴于存在这种误解的人之多,俺不得不爬出来澄清一下~~我的Megatops BinCalc当中的计算器是RPN Calculator!(同学们难道没有发现BinCalc的计算器没有等号嘛~~囧rz) 如果你是学软件出身的但是居然没有听说过RPN,那你一定是没听课也没做作业的了~~逆波兰表达式的概念最早出现在C圣经的课后习题里面。不过如果你学的是叹号强那本误人子弟的烂书……那也最迟会在编译原理里面看到它。如果你是学硬件出身的~~俺也不是很清楚硬件课程有没有提到RPN的,但是感觉应该没道理不提。 BinCalc的RPN计算器基本上是和惠普计算器的RPN操作相同的,是XYTZ 4寄存器的经典RPN(惠普的计算器有的型号多一个LASTx寄存器,但是换汤不换药)。和惠普的计算器相比,BinCalc的RPN计算器费了大力气硬是挤下了一个可视化的堆栈,用起来应该是比只有一行显示的那种HP计算器好用多了。RPN的原理极其简单,简述如下: BinCalc的RPN计算器有XYZT四个寄存器。在界面的多进制面板中显示和输入的都是X寄存器的内容;YZT三个寄存器可以看成是个堆栈,其中T是栈顶寄存器(可以作为常数寄存器来使用)。 按ENTER键是执行压栈操作~~不是当作等号用的啦(╯﹏╰),所以你1+1 ENTER~~结果当然不会是2~~
如上图,按了ENTER以后,X寄存器的内容会被压入堆栈(YZT),原来T寄存器的内容因为堆栈上溢而被挤出去丢掉了。每个寄存器都有一套自己的单目运算按钮,可以在不需要调整到X的前提下对每个寄存器直接进行算术移位和取反等操作(BinCalc无敌可视化堆栈的威力)。最右边三个按钮是用于调整堆栈的,从上到下分别是:寄存器循环上移(相当于HP的R↑键)、寄存器循环下移(HP的R↓键)、XY寄存器互换(HP的X<>Y键)。另外CLx是X寄存器清零,CLR是清空所有寄存器(HP的CLΣ键)。这几个都好理解,自己试试就明白。 做二元计算的时候,情况是这样的(比如做+计算):
整个计算的过程你可以看作是:按下双目算符后,就会从堆栈中弹出操作数Y,与X寄存器一块进行相应的计算,计算的结果放在X寄存器内。在退栈的时候可以看到T寄存器始终是保持不变的,所以实际使用的时候T寄存器可以当作常数寄存器来用。比如有时候经常要算XXX和几个1024相乘或者相除的结果。这时候就可以把1024一直压到T寄存器去,然后就能源源不断地从堆栈中弹出1024这个数进行计算了。 RPN的双目计算乍一看似乎很深奥的样子,实际上完全可以看作是竖式计算:
竖式计算好像小学1年级开始就玩得很熟了~~应该不用再废话。 另外,BinCalc在如下高亮位置有右键菜单,其他就再没有什么Readme没有提到的隐藏的机关了~~
最后~~贴一个史上最经典的程序员专用计算器:HP-16C。可惜HP的11/12/15/16这一系列计算器最终仅有12C活的滋润一直生产到现在(现在还能买到,基本成为金融计算器的工业标准了)。15和16都停产好久了~~现在被当作古董卖价格有点夸张了。
12-11-2008 无敌二进制计算器Megatops BinCalc更新更新到1.0.2,完全是BUG修订。之前的版本移位运算有问题:X寄存器相关的移位操作都是逻辑移位,而Y、Z、T寄存器的都是算术移位,不一致。这个版本将所有的移位操作都改为算术移位。另外修正了一个小小的ASCII Char焦点提示错误。 最新版本在我的文件盒子里下载,或者翻墙到BinCalc的主页:http://bincalc.googlepages.com/下载。Softpedia的因为我很懒得提交更新说明,所以还是旧版本。 ★ 2008年11月18日 今天提到Softpedia去了,可以下载了:http://www.softpedia.com/get/Science-CAD/Megatops-BinCalc.shtml 31-8-2008 Megatops ProCoder Font GB2312版本发现如果我的这个字体不支持GB2312编码的话,在不少软件里面用起来确实麻烦。比如:在SecureCRT里面用,Copy的时候无法把中文拷贝出来(这个问题能忍无所谓,反正我在终端里面从来不用中文);在Hex Workshop里面,不知道这个鬼佬的玩意为啥非得只能用支持GB2312字体;在Beyond Compare 3里面,如果不支持GB2312的用起来计算中文的宽度会出问题……主要是Beyond Compare 3的这个问题,令我忍无可忍,终于下决心改之。 最终的成品放到我的盒子里面了(不懂盒子的自己多翻翻我的blog~~),字体名为Megatops ProCoder Font 1.0 GB2312。用的时候必须要导入压缩包内的注册表,重启一把才行。重启后即可正常使用支持GB2312编码的无敌等宽字体了~~ ![]() btw:我盒子里面的SlickEdit宏已经更新到v13.0.2的版本,请有兴趣的在升级了SE以后down下来再Merge。 16-8-2008 Megatops BinCalc日后的发布地址因为GooglePages看上去没啥解封的希望,所以我把转正了的BinCalc提交到Softpedia去了。不过这个Softpedia确实挺赞的,反应迅速,并且真的把东西跑了一把有检查过。至少上面的截图不是我提交的那个是他们自己跑了截的。 试验了一下,国内能正常访问和下载:http://www.softpedia.com/get/Science-CAD/Megatops-BinCalc.shtml 另外,100% Clean! 10-8-2008 Megatops BinCalc 1.0.0正式版发布随着最后一个IPv4地址显示功能的加入,我的Megatops BinCalc终于完整实现了我最初写在Feature List里的所有功能。因此我决定从这个版本开始为BinCalc转正,正式设置版本号为1.0.0。 ![]() 相对于上次发布的v0.2f版的改进主要有: 位指示器增加了2^n提示功能。显示位的Tool-tip的时候除了显示位序号还同时显示对应的2^n值。在设置一些基址寄存器或者调试CPU的MMU TLB表项的时候这个功能很方便: ![]() ASCII字符显示增加输入功能。原本我增加ASCII Char显示功能纯粹是因为界面里面右边那块实在是太空了不知道该放点什么,还以为不可能有人用这种功能的。不过前几天有个鬼佬强烈建议俺增加ASCII输入功能,因为他居然用BinCalc来调试某种基于字节流的通讯应用( ̄口 ̄)!!。所以俺想了想估计那些经常做串口之类驱动的有可能还需要这个功能,于是就一块加上了。使用Tab键或者双击ASCII显示可以将输入焦点(黄色背景高亮)转移过去,然后敲键盘就可以了。因为是面向字节流调试的,所以Char输入是这个计算器里面唯一不在溢出时阻止输入的地方。你可以连续不断地往里面敲字母,BinCalc将字节输入按照FIFO原则处理。 ![]() 最后增加的一个功能就是IPv4地址显示和输入。在界面设计的时候我真是绞尽脑汁,最终使用了复用二进制数显示区的办法来硬是挤进了这个功能(这个功能迟迟没有弄主要是因为界面原因)。因为根据我个人经验,如果你要算得是IP掩码那用位指示器就已经足够了,根本懒得去看那一大串0和1。 ![]() IP地址的输入方式也很伤脑筋,因为我很不想用Windows标准的那种文本框输入。最终我设计和实现的这个输入方式还是与计算器的输入方式统一了:输入的时候IP地址从低位往高位涨。IP地址只能用键盘输入,使用感觉与BinCalc其他进制的输入方式统一,用起来感觉挺好的也不会觉得怪怪的。 IP操作主要是用于IP报文解析调试或者是计算IP地址掩码的时候。但是我自己用了一阵子后很快就用IP显示取代了原来的二进制数显示了:因为IPv4地址点分十进制的显示方式正好直观地显示了32bit整型中每个字节的十进制形式,结合右边的ASCII字符显示可以让你直接看到每个字符的十进制Code。 在我的盒子里面可以找到最新版本的下载。另外我也给BinCalc做了个官方主页:http://bincalc.googlepages.com。主页是鸟语的,没打算做中文版。因为Google Pages被GFW捂得十分严实,中文版做了也白做~~ ★ 2008年8月11日星期一:发现之前上传盒子的版本弄错了,盒子上的不是最终版本。最终版本版本号为:1.0.0.166。已经下载了的麻烦再检查一下。 6-6-2008 几款TTF等宽字体秀今天整理字体,翻出了俺收藏的这些等宽TTF矢量字体(点阵字俺一直用俺的DIY作品,无视其他( ̄^ ̄))。大家有兴趣可以看看弄来试试。以下都是SlickEdit 2008中11pt字号的显示效果,按照字母顺序排序。字体都是Google来的,自己可以找到。 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() 5-3-2008 Megatops ProCoder Font字体主页上线文字部分以前就写好了,今晚终于下定决定放到Google Pages上去了。不过这不意味着我接着会开始积极更新这套字体了——相反,新的开发任务又要开始,我这只是赶着最后一个清闲的晚上,把最后还没放上来的东西放上来罢了(╯﹏╰)。估计在之后的好几个月,可能都不会再有什么空闲时间来维护更新这套字体了。如果各位有什么不满意的地方,就先忍着吧~~忍个半年等我缓过劲来了,俺就会回来更新了~~ 页面位置:http://zhaojie.ding.googlepages.com/megatopsprocoderfont 感谢简单好用的Google Pages,在我的个人主页空间没掉4年以后让我再次有了向网上挂页面的动力~~ 26-2-2008 猪哥的Megatops ProCoder 1.0字体新品发布因为自己时不时也用用Ultraedit、EmEditor、EditPlus这样的编辑器,发现原来的ProCoder字体覆盖了128-255编码范围和中文字体冲突在这些不能正确计算宽度的编辑器里面确实还是挺麻烦的。所以简单裁剪了一个仅包含0-127范围的Lite版Megatops ProCoder字体。可以正常调用宋体显示全角引号、单引号、省略号等。当然,128及以上的西欧字符被裁掉了,所以这个版本无法正确显示德文和法文。如果你有这种需要就得使用没有裁过的完整版。所以我是建议你两个版本都安装,在类似于EmEditor这种能够为不同字符集指定字体的编辑器里面就可以无痛切换。 以下是在EditPlus中Lite版本的显示效果,因为已经完全裁掉了0x7F以上的字符,所以全角符号完全由中文宋体支持: ![]() 和原来的Full版可以共存,直接安装即可。点击这里下载 ★ Megatops ProCoder正如其名:仅仅面向有长时间编码或屏幕代码阅读需求的专业程序员设计,不明白其设计目的的麻烦绕行~~ 15-2-2008 C语言的inline转以前我用Docbook写的一篇关于C语言inline关键字使用的文章。唉,要是能用docbook直接写Blog就好了。用得越多发现Docbook这个东西真是越好用啊~~
本文介绍了GCC和C99标准中inline使用上的不同之处。inline属性在使用的时候,要注意以下两点:
gcc对C语言的inline做了自己的扩展,其行为与C99标准中的inline有较大的不同。 GCC的static inline定义很容易理解:你可以把它认为是一个static的函数,加上了inline的属性。这个函数大部分表现和普通的static函数一样,只不过在调用这种函数的时候,gcc会在其调用处将其汇编码展开编译而不为这个函数生成独立的汇编码。除了以下几种情况外:
static inline函数和static函数一样,其定义的范围是local的,即可以在程序内有多个同名的定义(只要不位于同一个文件内即可)。
相对于C99的inline来说,GCC的inline更容易理解:可以认为它是一个普通全局函数加上了inline的属性。即在其定义所在文件内,它的表现和static inline一致:在能展开的时候会被内联展开编译。但是为了能够在文件外调用它,gcc一定会为它生成一份独立的汇编码,以便在外部进行调用。即从文件外部看来,它和一个普通的extern的函数无异。举个例子: foo.c:
/* 这里定义了一个inline的函数foo() */
inline foo() {
...; <- 编译器会像非inline函数一样为foo()生成独立的汇编码
}
void func1() {
foo(); <- 同文件内foo()可能被编译器内联展开编译而不是直接call上面生成的汇编码
}
而在另一个文件里调用foo()的时候,则直接call的是上面文件内生成的汇编码: bar.c:
extern foo(); <- 声明foo(),注意不能在声明内带inline关键字
void func2() {
foo(); <- 这里就是直接call在foo.c内为foo()函数生成的汇编码了
}
GCC的static inline和inline都很好理解:看起来都像是对普通函数添加了可内联的属性。但是这个extern inline就千万不能想当然地理解成就是一个extern的函数+inline属性了。实际上gcc的extern inline十分古怪:一个extern inline的函数只会被内联进去,而绝对不会生成独立的汇编码!即使是通过指针应用或者是递归调用也不会让编译器为它生成汇编码,在这种时候对此函数的调用会被处理成一个外部引用。另外,extern inline的函数允许和外部函数重名,即在存在一个外部定义的全局库函数的情况下,再定义一个同名的extern inline函数也是合法的。以下用例子具体说明一下extern inline的特点: foo.c:
extern inline
int foo(int a)
{
return (-a);
}
void func1()
{
...;
a = foo(a); ①
p_foo = foo; ②
b = p_foo(b); ③
}
在这个文件内,gcc不会生成foo函数的汇编码。在func1中的调用点①,编译器会将上面定义的foo函数在这里内联展开编译,其表现类似于普通inline函数。因为这样的调用是能够进行内联处理的。而在②处,引用了foo函数的地址。但是注意:编译器是绝对不会为extern inline函数生成独立汇编码的!所以在这种非要个函数地址不可的情况下,编译器不得不将其处理为外部引用,在链接的时候链接到外部的foo函数去(填写外部函数的地址)。这时如果外部没有再定义全局的foo函数的话就会在链接时产生foo函数未定义的错误。 假设在另一个文件里面也定义了一个全局函数foo: foo2.c:
int foo(int a)
{
return (a);
}
那么在上面那个例子里面,后面一个对foo函数地址的引用就会在链接时被指到这个foo2.c中定义的foo函数去。也就是说:①调用foo函数的结果是a=-a,因为其内联了foo.c内的foo函数;而③调用的结果则是b=b,因为其实际上调用的是foo2.c里面的foo函数! extern inline的用法很奇怪也很少见,但是还是有其实用价值的。第一:它可以表现得像宏一样,可以在文件内用extern inline版本的定义取代外部定义的库函数(前提是文件内对其的调用不能出现无法内联的情况);第二:它可以让一个库函数在能够被内联的时候尽量被内联使用。举个例子: 在一个库函数的c文件内,定义一个普通版本的库函数libfunc: lib.c:
void libfunc()
{
...;
}
然后再在其头文件内,定义(注意不是声明!)一个实现相同的exterin inline的版本: lib.h:
extern inline libfunc()
{
...;
}
那么在别的文件要使用这个库函数的时候,只要include了lib.h,在能内联展开的地方,编译器都会使用头文件内extern inline的版本来展开。而在无法展开的时候(函数指针引用等情况),编译器就会引用lib.c中的那个独立编译的普通版本。即看起来似乎是个可以在外部被内联的函数一样,所以这应该是gcc的extern inline意义的由来。 但是注意这样的使用是有代价的:c文件中的全局函数的实现必须和头文件内extern inline版本的实现完全相同。否则就会出现前面所举例子中直接内联和间接调用时函数表现不一致的问题。
以下主要描述C99的inline与Gcc不同的部分。对于相同的部分请参考GCC inline的说明。 同GCC的static inline(第 1.1 节 “static inline”)。 C99的inline的使用相当令人费解。当一个定义为inline的函数没有被声明为extern的时候,其表现有点类似于gcc中extern inline那样(C99里面这段描述有点晦涩,原文如下):
即如果一个inline函数在文件范围内没有被声明为extern的话,这个函数在文件内的表现就和gcc的extern inline相似:在本文件内调用时允许编译器使用本文件内定义的这个内联版本,但同时也允许外部存在同名的全局函数。只是比较奇怪的是C99居然没有指定编译器是否必须在本文件内使用这个inline的版本而是让编译器厂家自己来决定,相当模糊的定义。 如果在文件内把这个inline函数声明为extern,则这个inline函数的表现就和gcc的inline一致了:这个函数即成为一个“external definition”(可以简单理解为全局函数):可以在外部被调用,并且在程序内仅能存在一个这样名字的定义。 下面举例说明C99中inline的特性: 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); ②
}
在上面这个例子里,函数fahr是个全局函数:因为在①处将fahr声明为extern,因此在②处调用fahr的时候使用的一定是这个文件内所定义的版本(只不过编译器可以将这里的调用进行内联展开)。在文件外部也可以调用这个函数(说明像gcc的inline一样,编译器在这种情况下会为fahr生成独立的汇编码)。 而cels函数因为没有在文件范围内被声明为extern,因此它就是前面所说的“inline definition”,这时候它实际上仅能作用于本文件范围(就像一个static的函数一样),外部也可能存在一个名字也为cels的同名全局函数。在②处调用cels的时候编译器可能选择用本文件内的inline版本,也有可能跑去调用外部定义的cels函数(C99没有规定此时的行为,不过编译器肯定都会尽量使用文件内定义的inline版本,要不然inline函数就没有存在的意义了)。从这里的表现上看C99中未被声明为extern的inline函数已经和gcc的extern inline十分相似了:本文件内的inline函数可以作为外部库函数的替代。
27-1-2008 猪哥牌TFTP Server出炉猪哥的TFTP Server终于处于实用状态了,基本上没啥大问题,放出来下载。 为了避免不明用处的人瞎下载,这里说明一下下载对象:
![]() 此处下载 |
|
|