﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-puppy居-随笔分类-杂项</title><link>http://www.cnitblog.com/puppypyb/category/8860.html</link><description>puppy居士</description><language>zh-cn</language><lastBuildDate>Wed, 20 Mar 2013 07:28:23 GMT</lastBuildDate><pubDate>Wed, 20 Mar 2013 07:28:23 GMT</pubDate><ttl>60</ttl><item><title>基础啊！基础！ 联合体不能在定义时初始化，也不能作为函数参数赋值</title><link>http://www.cnitblog.com/puppypyb/archive/2013/03/20/87112.html</link><dc:creator>puppy</dc:creator><author>puppy</author><pubDate>Wed, 20 Mar 2013 06:44:00 GMT</pubDate><guid>http://www.cnitblog.com/puppypyb/archive/2013/03/20/87112.html</guid><wfw:comment>http://www.cnitblog.com/puppypyb/comments/87112.html</wfw:comment><comments>http://www.cnitblog.com/puppypyb/archive/2013/03/20/87112.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/puppypyb/comments/commentRss/87112.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/puppypyb/services/trackbacks/87112.html</trackback:ping><description><![CDATA[<div>RT</div><img src ="http://www.cnitblog.com/puppypyb/aggbug/87112.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/puppypyb/" target="_blank">puppy</a> 2013-03-20 14:44 <a href="http://www.cnitblog.com/puppypyb/archive/2013/03/20/87112.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DivX和XviD不能不说的故事</title><link>http://www.cnitblog.com/puppypyb/archive/2008/09/09/48868.html</link><dc:creator>puppy</dc:creator><author>puppy</author><pubDate>Tue, 09 Sep 2008 01:57:00 GMT</pubDate><guid>http://www.cnitblog.com/puppypyb/archive/2008/09/09/48868.html</guid><wfw:comment>http://www.cnitblog.com/puppypyb/comments/48868.html</wfw:comment><comments>http://www.cnitblog.com/puppypyb/archive/2008/09/09/48868.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/puppypyb/comments/commentRss/48868.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/puppypyb/services/trackbacks/48868.html</trackback:ping><description><![CDATA[<font face="Courier New">&nbsp;&nbsp;&nbsp;我们知道，wmv，wma，xvid，divx，很大一部分avi，他们都是所谓的mpeg4的文件，这种文件的压缩比极高，但是显示的质量并没 有太大的改变。mpeg2就是我们常见的dvd所采用的编码规范，MPEG(活动图像专家组)包括一组规范。其中5,6已经胎死腹中，mpeg7不是面向 消费的。第一个mpeg4规范的实现，是由MS作出来的，不过很快就被破解了，之后破解版本有了很多 的分支（如xvid，divx等），MS自己的文件也有版本更新，所以，mpeg4不是一种固定的格式，而是一组格式的统称，他们都可以上朔到MS的最初 版本.<br><br>DivX和XviD不能不说的故事, 好像很多人不知道他们的关系。 如今的电影是越来越好看，拍摄、制作的特技效果越来越精彩，人们期待的程度越来越高，盗版也越来越多；同时电影制作公司的防盗版技术做的越来越高明。但有句老话叫："道高一尺，魔高一丈"，无论你的电影多精彩、防盗技术多高明，总是有人偏偏能够把你"盗"出来，而且还"盗亦有盗"，在保持"原版原味"的条件下，占用的空间变得越来越小，操作越来越灵活、简单，越来越方便传播。而且这种技术随着版本不断更新，画质越来越贴近原版、压缩速度越来越快、压缩／播放进程对计算机的需求越来越低。这就是DivX时代的新生力量──XviD。 <br><br>　　黑格尔说过"存在即合理" <br><br>　　随着时代的进步，社会的发展，在计算机视频技术方面更是突飞猛进。如今视频的业界标准已经到了DVD时代。主流的DVD光驱的价格已经降到400元人民币以内。DVD播放机的价格最便宜的已经降到了700元。但是这些都是近期发生的事情，目前仍有一大群only CD-ROM群体，他们不愿意再投资去买DVD光驱，有的甚至由于机器无法再扩充而不能购买DVD光驱。这便促使另一个的解决方案的萌发。 <br><br>　　除此之外，互联网宽带的普及，Adsl宽带入户，P2P软件的泛滥，使得650MB的大文件轻松的实现异地传输。还有正版DVD大片的价格居高不下，也是正版DVD普及化的一大障碍。基于以上因素的存在，有一种新的视频压缩技术出现，那就是DivX，即"压缩电影"。压缩电影的技术有很多种，但是DivX最为普及，它广泛流传于互联网与盗版盘。 <br><br>　　随着时间的推移DivX再推出刚刚推出不久，就不断推陈出新，从DivX3.11到DivX4，目前最新版本为DivX5.02。本来版本越高，技术也就越高、播放的质量应该更好、更清晰。但是事实告诉我们随着版本的提升，压缩后的播放效果提升不明显，压缩所用的时间越来越长，压缩后的体积没有太大的进步，甚至有的使用DivX5.02压缩以后会出现跳帧的问题。这到底是为什么呢？难道视频压缩技术已经达到顶峰不能够再穿越了么？ <br><br>　　目前又出现一种新的压缩技术名为XviD，在视频业界初见端倪，就目前来看它的压缩时间就是一大卖点，它可以在保持DivX5的画质的基础上，大大提高压缩时间。 <br><br>　　光从名字上看就可以看出Xvid与Divx，他们之间肯定有着千丝万缕的联系，大家一定想知道。下面就为大家谈谈关于XviD的故事。 <br><br>　　Long long ago&#8230; <br><br>　　故事的经过是这样的。 <br><br>　　早在1998年微软开发了第一个（也是唯一的）在PC上使用的MPEG-4（注）编码器，它包括MS MPEG4V1、MS MPEG4V2、MS MPEG4V3的系列编码内核。其中的V1和V2用来制作AVI文件，一直到现在它都是作为Windows的默认组件。不过V1和V2的编码质量不是很好，一直到MS MPEG4V3才开始有好转，画质有了显著的进步。但是不知微软出何居心，却将这个MS MPEG4V3 的视频编码内核封闭在仅仅应用于Windows Media流媒体技术上，也 就是说，我们经常看到的ASF流媒体文件中。ASF文件虽然有一些优势，但是由于过分的封闭，不能被编辑，未得到广泛的应用。这便惹怒了不怕天不怕地的视频黑客和置于钻研视频编码的高手。后来，这些小组不仅破解了微软的视频编码，而且经过他们的修改,一种新的视频编码诞生了。那就是广为流传的Mpeg4编码器──DivX3.11。 <br><br>　　随后一发不可收拾，DivX被传得红得发紫，很快就成了业界的标准。但是问题同样很快的出现了，DivX的基础技术是非法盗用微软的，只能在地下里流传，却上不了台面，正所谓"名不正，言不顺"，无法进行广泛的发展，即产品化，更无法生产硬件播放机。 <br><br>　　"生产力要改变生产关系" <br><br>　　在这种情况的迫使下，一些视频编码的高级程序员（包括原DivX 的开发者）组建了一家公司，名为DivXNetworks Inc。这家公司发起一个完全开放源码的项目，名为"ProjectMayo"，目标是开发一套全新的、开放源码的MPEG4编码软件。由于它完全符合ISO MPEG4标准，又是完全开放源代码（就象linux操作系统），OpenDivX CODEC吸引了很多软件、视频高手参与。人力、物力大大投入，OpenDivX编码器和解码器原型很快便公布于众，之后又开发出具有更高性能的编码器Encore 2等等。这DivX的辉煌时期。 <br><br>　　虽然主要编码工作是DXN的人在做，但许多的技术难关的突破完全得力于来自开放源码社会的帮助。 <br><br>　　DivX的优势被人们所接受，高品质的DVD电影的容量一般为5GB，但经过DivX编码后的大小只有650MB，仅仅为原DVD容量的八分之一，图像品质却与DVD相当。它可以通过互联网相互传输，还可以报存在一张CD光盘（650MB）上。 <br><br>　　DXN的野心： <br><br>　　DivXNetworks一直希望DivX能成为好莱坞巨头们选择的行业标准，并可以通过互联网进行传输的视频文件，就像唱片发行公司不得不接受MP3格式，并使用它在网上传输音乐文件一样。DXN希望并计划在网上出售视频内容的公司达成技术转让的协议。但是，到目前为止，它尚未和任何一家主要的、甚至具有影响力的电影制片公司达成这类协议。 <br><br>　　很可惜的是想DivX这么好的电影只能在电脑上播放，目前还没有一款播放机能够播放这样的光盘。日前，DXN已经来到了中国，这家公司的负责人表示，目前有许多美国人都希望能买到采用这一技术的DVD播放设备，但全球还没有人能生产，所以他希望能与中国的DVD制造商携手，在年内拿出产品，并且首先在美国推出。 <br><br>　　"天底下真的好人多么？那么小人算好人么？" <br><br>　　就在DivX顺利发展时期，DivX的技术逐渐成熟，商机无限的时候，一台好戏上演了。由于DivX的技术不是依据GPL协议（通用公共许可证，一种开放源码项目中常用的保障自由使用和修改的软件或源码的协议），而是LGPL协议（注）。这是DXN公司为自己留的后门。 <br><br>　　2001年7月就在Encore2基本成型的时候，DXN公司突然封闭了DivX的原代码，并在此基础上发布了自有产品DivX4。DivX 4的基础就是开放源代码OpenDivX中的Encore 2，DXN利用了DivX的招牌。DNX公司这么做，可以说是出其不备的摆了所有人一刀。开放源码社会就这样被狠狠地涮了一回，他们是那么的无辜。 <br><br>　　DXN公司趁热打铁，很快推出了DivX5，但是DivX5没有比DivX4强到哪里去，甚至有bug，更可气的是这一版本还要收费。可怜阿，有那么多无偿为DivX技术付出的智慧与劳动的人，可悲阿，他们为一值都在无偿的为DNX公司赚钱。这种垄断和一直处于垄断地位的微软来说，DXN要更恨、更毒。 <br><br>　　人世间还是好人多！正义当头！ <br><br>　　首先是全球整个0dayz组织（注）永远的拒绝了DXN公司的DivX45。被人"涮"了一把的开源社团决定另起门户，逐渐重新聚拢开发力量，在OpenDivX版本的基础上，再次开发出一种新的MPEG-4编码、解码软件。这就是：XviD。从技术上来说XviD已经基本上与DivX5接近，或者还有所超越； <br><br>　　春天来了： <br><br>　　近一年来XviD继承并发展了曾经的OpenDIVX Encore 2，并且使其的性能、效率的到了极大的提升，被认为是目前最快的MPEG4编码。这是因为XviD重新改写了所有原代码，焕然一新。除此之外，Xvid还吸收了前车之鉴，依照GPL发布。（不再是以前DivX的LGPL，也就是说：谁要是想用它做成产品而不开放源码是非法的）而且在2002年，也就是今年，TDX2002（全球最著名的地下电影发行组织，每年在网上放出数千部最新而且高品质影片RIP）已经接纳XviD为官方标准。这样TDX2002就有了两个正式标准：DivX 3.11与XviD。而DivX 4、5像其它封闭的商业软件一样，被永远拒绝。 <br><br>　　报应来了！ <br><br>　　对开源软件下毒手的人远不止DXN一家，目前因为一家商业软件公司盗用XviD源代码，而被迫停止开发。具体的情况请参阅：</font><a href="http://www.xvid.org/" target=_blank><u><font color=#000000>http://www.xvid.org</font></u></a><font face="Courier New">； <br><br>　　　　　　　 DivX 4/5　　　　　　　　　　　　　　　 　　　 XviD <br>出品公司　 DivXNetworks Inc　　　　　　　　　　　　　　开放源代码(GPL授权) <br>推出时间　　　1998年　　　　　　　　　　　　　　　　　　 2002年2月 <br>创始人　　　　罗达（Rota）及电脑黑客基尔（Gej）　　　　被DXN"涮"的人 <br>TDX2002认证　Yes　　　　　　　　　　　　　　　　　　　　　Yes <br>oDay认证　　　No　　　　　　　　 　　　　　　　　　　　　　Yes <br>最新版本　　　5.02　　　　　　　　　　　　　　　　　　　　　1.3+ <br>费用　　　　　收费　　　　　　　　　　　　　　　　　　　　　免费 <br>压缩时间　　　长　　　　　　 　　 　　　　　　　　　　　　&nbsp;&nbsp; &nbsp;稍短 <br>图像质量　　　高、接近DVD　　　　　　　　　　　　　　　　高、接近DVD <br>压缩容量　　　较小　　　　　　　　　　　　　　　　　　　 　 较小 <br>编码容量　　　3.4MB　　　　　　　　　　 　　　　　　　　　 359K <br>优化设置　　　一般　　　　　　　　强大的可调节性，使用这可设置很多选项，分别针对不同电影进行不同方式的压缩。 <br><br>　　XviD使用技巧： <br><br>　　关于XviD压缩设置的文章很多，XviD可以调节的选项很细，由于篇幅限制，不再本文的讨论之内。在这里，我推荐大家使用"2-Pass"编码，因为它能给我们更精确的最终文件大小，并且生成最佳质量的编码 (在文件大小相同的情况下)。 <br><br>　　只安装DivX5的编解码器不能播放由Xvid压缩的电影。但是只安装XviD编码，可以顺利播放DivX5压缩的电影。但是在播放DivX5电影的时候，速度不能让人满意。加上ffdshow（注）之后效果明显改善。看来XviD在播放divX5的还不是很完善。 <br><br>　　虽然XviD到目前来讲与DivX5对战，仍有些身单力薄，优势不是很明显。但是笔者很看好XviD。首先，它是绝对开放源代码，这使得有更多的人投入到XviD的研发之中。还有，它完全重写DivX的原代码，让新的XivD去粗取精、焕然一新；目前XviD的开发人员有很多都是当初DivX的研发人员，对DivX的错误了解得很清楚，重写之后，XivD的地层优势可见一斑。另外，DivX4／5虽然版本不断更新，但是功能提升并不高，优势不明显。XviD是新生力量，而且充满了复仇的力量。祝XviD一路走好。 <br><br>　　XviD版本的历史: <br><br>　　1.0 2002年2月17日 第一版 ，首次发布 <br>　　1.0 2002年2月28日 大量的修正和更准确地解释 <br>　　1.1 2002年3月2日 分析澄清了很多概念 <br>　　1.2 2002年3月4日 加入量化矩阵(quantization matrix), 移去量(removed quant). 柔和(smoothing) 技术 <br>　　1.3 2002年3月8日 关于 Nic's XviD Directshow Filter 的详释 <br>　　1.3+ 2002年7月23日 按照Nic's XVID Codec校正补充部分内容（目前最新版本） <br><br>　　关于DivX起源的小知识： <br><br>　　这种名为DivX 的技术，由一个27岁的法籍影音发烧友罗达（Rota）及电脑黑客基尔（Gej）创造出来得。 <br><br>　　原来DivX所采的技术并非这两位仁兄发明的，他们只不过是个盗版天才。随着Wind ows的大行其道，微软开发了MPEG-4技术，能够将视频影像文件容量压缩到很小。罗达与基尔将程式重写一遍，但将其改名为DivX，且放在网上随意任人下载。 <br><br>　　微软声称将对所有推动DivX发展的人、企业作出追究。可是罗达正全面申请将他们的DivX合法化。由于DivX虽然是从Windows的发明出来的，但却没有用过任何微软的技术。而且，他更与美国一些技术人士及财经人员开会，和组新公司 ProjectMayo.com全力推广DivX。 <br><br>　　其实，DivX是视频DVD的另一种保存方式，要靠DeCSS程序（注）才能做到。因为DV D本身有防复制的标记，让DVD不能随便复制到电脑里，但DeCSS能将它解码，令其可以复制，压缩成DivX电影。针对这一做法，各大电影商立即采取行动，防止DeCSS外流及散播，但为时已晚，DeCSS在Yahoo！、Google上都能找到。 <br>　 <br>　　名词解释: <br><br>　　DeCSS程序：乔．约翰森编写的小程序，仅有57K，不仅震撼了好莱坞，还引发了无数的法律纠纷。他创造出来的&#8220;小魔怪&#8221;，如今已经成了好莱坞制片商们最恨之入骨的冤家对头。DeCSS程序能够将正版加密的DVD影片复制到计算机硬盘上。它还可以将这些影片上传到互联网上。 <br><br>　　MPEG-4技术：是一种崭新的低码率、高压缩比的视频编码标准，传输速率为4.8~64kbit/s，使用时占用的存储空间比较小。目前的DivX（最新的XviD）电影都采用的此技术，现在被广泛采用。 <br><br>　　GPL协议：通用公共许可证，一种开放源码项目中常用的保障自由使用和修改的软件或源码的协议。 <br><br>　　LGPL协议：次级GPL(Lesser GPL)，与GPL一样，是一种公共许可证。与GPL的最大不同是它允许私有。 <br><br>　　Ffdshow：一个支持 Xvid、MPEG4-V3 MPEG4-V2 以及 DivX 所有版本所制作的视频文件的播放软件，占CPU 资源比较少。</font> 
<img src ="http://www.cnitblog.com/puppypyb/aggbug/48868.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/puppypyb/" target="_blank">puppy</a> 2008-09-09 09:57 <a href="http://www.cnitblog.com/puppypyb/archive/2008/09/09/48868.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>diff和patch使用指南</title><link>http://www.cnitblog.com/puppypyb/archive/2008/08/29/48539.html</link><dc:creator>puppy</dc:creator><author>puppy</author><pubDate>Fri, 29 Aug 2008 10:07:00 GMT</pubDate><guid>http://www.cnitblog.com/puppypyb/archive/2008/08/29/48539.html</guid><wfw:comment>http://www.cnitblog.com/puppypyb/comments/48539.html</wfw:comment><comments>http://www.cnitblog.com/puppypyb/archive/2008/08/29/48539.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/puppypyb/comments/commentRss/48539.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/puppypyb/services/trackbacks/48539.html</trackback:ping><description><![CDATA[<p>diff和patch是一对工具，在数学上来说，diff是对两个集合的差运算，patch是对两个集合的和运算。<br>diff比较两个文件或文件集合的差异，并记录下来，生成一个diff文件，这也是我们常说的patch文件，即补丁文件。<br>patch能将diff文件运用于 原来的两个集合之一，从而得到另一个集合。举个例子来说文件A和文件B,经过diff之后生成了补丁文件C,那么着个过程相当于 A -B = C ,那么patch的过程就是B+C = A 或A-C =B。<br>因此我们只要能得到A, B, C三个文件中的任何两个，就能用diff和patch这对工具生成另外一个文件。</p>
<p>这就是diff和patch的妙处。下面分别介绍一下两个工具的用法(待续)</p>
<p>1. diff的用法</p>
<p>diff后面可以接两个文件名或两个目录名。 如果是一个目录名加一个文件名，那么只作用在那么个目录下的同名文件。</p>
<p>如果是两个目录的话，作用于该目录下的所有文件，不递归。如果我们希望递归执行，需要使用-r参数。</p>
<p>命令diff A B &gt; C ,一般A是原始文件，B是修改后的文件，C称为A的补丁文件。<br>不加任何参数生成的diff文件格式是一种简单的格式，这种格式只标出了不一样的行数和内容。我们需要一种更详细的格式，可以标识出不同之处的上下文环境，这样更有利于提高patch命令的识别能力。这个时候可以用-c开关。<br>2. patch的用法</p>
<p>patch用于根据原文件和补丁文件生成目标文件。还是拿上个例子来说</p>
<p>patch A C 就能得到B, 这一步叫做对A打上了B的名字为C的补丁。</p>
<p>之一步之后，你的文件A就变成了文件B。如果你打完补丁之后想恢复到A怎么办呢？</p>
<p>patch -R B C 就可以重新还原到A了。</p>
<p>所以不用担心会失去A的问题。</p>
<p>其实patch在具体使用的时候是不用指定原文件的，因为补丁文件中都已经记载了原文件的路径和名称。patch足够聪明可以认出来。但是有时候会 有点小问题。比如一般对两个目录diff的时候可能已经包含了原目录的名字，但是我们打补丁的时候会进入到目录中再使用patch,着个时候就需要你告诉 patch命令怎么处理补丁文件中的路径。可以利用-pn开关，告诉patch命令忽略的路径分隔符的个数。举例如下：</p>
<p>A文件在 DIR_A下，修改后的B文件在DIR_B下，一般DIR_A和DIR_B在同一级目录。我们为了对整个目录下的所有文件一次性diff,我们一般会到DIR_A和DIR_B的父目录下执行以下命令</p>
<pre>diff -rc DIR_A DIR_B &gt; C</pre>
<p>着个时候补丁文件C中会记录了原始文件的路径为 DIR_A/A</p>
<p>现在另一个用户得到了A文件和C文件，其中A文件所在的目录也是DIR_A。 一般，他会比较喜欢在DIR_A目录下面进行patch操作，它会执行</p>
<pre>patch &lt; C</pre>
<p>但是这个时候patch分析C文件中的记录，认为原始文件是./DIR_A/A，但实际上是./A，此时patch会找不到原始文件。为了避免这种情况我们可以使用-p1参数如下</p>
<pre>patch -p1 &lt; C</pre>
<p>此时，patch会忽略掉第1个&#8221;/&#8221;之前的内容，认为原始文件是 ./A，这样就正确了。</p>
<p>最后有以下几点注意：</p>
<ol>
    <li>一次打多个patch的话，一般这些patch有先后顺序，得按次序打才行。
    <li>在patch之前不要对原文件进行任何修改
    <li>如果patch中记录的原始文件和你得到的原始文件版本不匹配(很容易出现)，那么你可以尝试使用patch, 如果幸运的话，可以成功。大部分情况下，会有不匹配的情况，此时patch会生成rej文件，记录失败的地方，你可以手工修改。 </li>
</ol>
<img src ="http://www.cnitblog.com/puppypyb/aggbug/48539.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/puppypyb/" target="_blank">puppy</a> 2008-08-29 18:07 <a href="http://www.cnitblog.com/puppypyb/archive/2008/08/29/48539.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>网络序</title><link>http://www.cnitblog.com/puppypyb/archive/2008/08/27/48430.html</link><dc:creator>puppy</dc:creator><author>puppy</author><pubDate>Wed, 27 Aug 2008 07:07:00 GMT</pubDate><guid>http://www.cnitblog.com/puppypyb/archive/2008/08/27/48430.html</guid><wfw:comment>http://www.cnitblog.com/puppypyb/comments/48430.html</wfw:comment><comments>http://www.cnitblog.com/puppypyb/archive/2008/08/27/48430.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/puppypyb/comments/commentRss/48430.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/puppypyb/services/trackbacks/48430.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;被阴了一把.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;做M2M终端协议的时候，报文封装都是按照little-endian来处理的。与服务器那边却总是连不上，后来把数据发过去核对，才发现服务器那边只认big-endian，即所谓的网络序。问题是协议里面并没有明确说明要这样做，没办法，只好再花时间加上htons、ntohs。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在网络上发送数据之前，一般的做法的确是要转换成网络顺序发送。下次在做网络协议时一定要事先弄清楚，切记！<br><br><font size=2>为了保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用</font><span style="FONT-SIZE: 9pt; COLOR: black">big&nbsp;endian</span><span style="FONT-SIZE: 9pt; COLOR: black">排序方式。</span><span style="FONT-SIZE: 9pt; COLOR: black"><br><br></span><span style="FONT-SIZE: 9pt; COLOR: black">为了进行转换</span><span style="FONT-SIZE: 9pt; COLOR: black">&nbsp;bsd&nbsp;socket</span><span style="FONT-SIZE: 9pt; COLOR: black">提供了转换的函数</span>&nbsp;<span style="FONT-SIZE: 9pt; COLOR: black">有下面四个:<br></span><span style="FONT-SIZE: 9pt; COLOR: black"><span style="FONT-SIZE: 9pt; COLOR: black">&nbsp;(s&nbsp;</span><span style="FONT-SIZE: 9pt; COLOR: black">-- </span><span style="FONT-SIZE: 9pt; COLOR: black">short&nbsp;&nbsp;&nbsp; l </span><span style="FONT-SIZE: 9pt; COLOR: black">-- </span><span style="FONT-SIZE: 9pt; COLOR: black">long &nbsp;&nbsp; h </span><span style="FONT-SIZE: 9pt; COLOR: black">-- </span><span style="FONT-SIZE: 9pt; COLOR: black">host&nbsp;&nbsp; n </span><span style="FONT-SIZE: 9pt; COLOR: black">-- </span><span style="FONT-SIZE: 9pt; COLOR: black">network)</span><br>htons&nbsp;</span><span style="FONT-SIZE: 9pt; COLOR: black">把</span><span style="FONT-SIZE: 9pt; COLOR: black">unsigned&nbsp;short</span><span style="FONT-SIZE: 9pt; COLOR: black">类型从主机序转换到网络序</span><span style="FONT-SIZE: 9pt; COLOR: black"><br>htonl&nbsp;</span><span style="FONT-SIZE: 9pt; COLOR: black">把</span><span style="FONT-SIZE: 9pt; COLOR: black">unsigned&nbsp;long</span><span style="FONT-SIZE: 9pt; COLOR: black">类型从主机序转换到网络序</span><span style="FONT-SIZE: 9pt; COLOR: black"><br>ntohs&nbsp;</span><span style="FONT-SIZE: 9pt; COLOR: black">把</span><span style="FONT-SIZE: 9pt; COLOR: black">unsigned&nbsp;short</span><span style="FONT-SIZE: 9pt; COLOR: black">类型从网络序转换到主机序</span><span style="FONT-SIZE: 9pt; COLOR: black"><br>ntohl&nbsp;</span><span style="FONT-SIZE: 9pt; COLOR: black">把</span><span style="FONT-SIZE: 9pt; COLOR: black">unsigned&nbsp;long</span><span style="FONT-SIZE: 9pt; COLOR: black">类型从网络序转换到主机序</span><span style="FONT-SIZE: 9pt; COLOR: black"><br><br></span><span style="FONT-SIZE: 9pt; COLOR: black">在使用</span><span style="FONT-SIZE: 9pt; COLOR: black">little&nbsp;endian</span><span style="FONT-SIZE: 9pt; COLOR: black">的系统中</span>&nbsp;<span style="FONT-SIZE: 9pt; COLOR: black">这些函数会把字节序进行转换</span><span style="FONT-SIZE: 9pt; COLOR: black">&nbsp;<br></span><span style="FONT-SIZE: 9pt; COLOR: black">在使用</span><span style="FONT-SIZE: 9pt; COLOR: black">big&nbsp;endian</span><span style="FONT-SIZE: 9pt; COLOR: black">类型的系统中</span>&nbsp;<span style="FONT-SIZE: 9pt; COLOR: black">这些函数会定义成空宏</span><span style="FONT-SIZE: 9pt; COLOR: black"><br></span><span style="FONT-SIZE: 9pt; COLOR: black">同样</span>&nbsp;<span style="FONT-SIZE: 9pt; COLOR: black">在网络程序开发时</span>&nbsp;<span style="FONT-SIZE: 9pt; COLOR: black">或是跨平台开发时</span>&nbsp;<span style="FONT-SIZE: 9pt; COLOR: black">也应该注意保证只用一种字节序</span>&nbsp;<span style="FONT-SIZE: 9pt; COLOR: black">不然两方的解释不一样就会产生</span><span style="FONT-SIZE: 9pt; COLOR: black">bug.<br></span><span style="FONT-SIZE: 9pt; COLOR: black"><br></span><span style="FONT-SIZE: 9pt; COLOR: black"><br></span><span style="FONT-SIZE: 9pt; COLOR: black">不同的</span><span style="FONT-SIZE: 9pt; COLOR: black">CPU</span><span style="FONT-SIZE: 9pt; COLOR: black">上运行不同的操作系统，字节序也是不同的，参见下表。</span><span style="FONT-SIZE: 9pt; COLOR: black"><br></span><span style="FONT-SIZE: 9pt; COLOR: black">处理器</span><span style="FONT-SIZE: 9pt; COLOR: black">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-SIZE: 9pt; COLOR: black">操作系统</span><span style="FONT-SIZE: 9pt; COLOR: black">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-SIZE: 9pt; COLOR: black">字节排序</span><span style="FONT-SIZE: 9pt; COLOR: black"><br>Alpha&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-SIZE: 9pt; COLOR: black">全部</span><span style="FONT-SIZE: 9pt; COLOR: black">&nbsp;&nbsp;&nbsp;&nbsp;Little&nbsp;endian<br>HP-PA&nbsp;&nbsp;&nbsp;&nbsp;NT&nbsp;&nbsp;&nbsp;&nbsp;Little&nbsp;endian<br>HP-PA&nbsp;&nbsp;&nbsp;&nbsp;UNIX&nbsp;&nbsp;&nbsp;&nbsp;Big&nbsp;endian<br>Intelx86&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-SIZE: 9pt; COLOR: black">全部</span><span style="FONT-SIZE: 9pt; COLOR: black">&nbsp;&nbsp;&nbsp;&nbsp;Little&nbsp;endian&nbsp;&lt;-----x86</span><span style="FONT-SIZE: 9pt; COLOR: black">系统是小端字节序系统</span><span style="FONT-SIZE: 9pt; COLOR: black"><br>Motorola680x()&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-SIZE: 9pt; COLOR: black">全部</span><span style="FONT-SIZE: 9pt; COLOR: black">&nbsp;&nbsp;&nbsp;&nbsp;Big&nbsp;endian<br>MIPS&nbsp;&nbsp;&nbsp;&nbsp;NT&nbsp;&nbsp;&nbsp;&nbsp;Little&nbsp;endian<br>MIPS&nbsp;&nbsp;&nbsp;&nbsp;UNIX&nbsp;&nbsp;&nbsp;&nbsp;Big&nbsp;endian<br>PowerPC&nbsp;&nbsp;&nbsp;&nbsp;NT&nbsp;&nbsp;&nbsp;&nbsp;Little&nbsp;endian<br>PowerPC&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-SIZE: 9pt; COLOR: black">非</span><span style="FONT-SIZE: 9pt; COLOR: black">NT&nbsp;&nbsp;&nbsp;&nbsp;Big&nbsp;endian&nbsp;&nbsp;&lt;-----PPC</span><span style="FONT-SIZE: 9pt; COLOR: black">系统是大端字节序系统</span><span style="FONT-SIZE: 9pt; COLOR: black"><br>RS/6000&nbsp;&nbsp;&nbsp;&nbsp;UNIX&nbsp;&nbsp;&nbsp;&nbsp;Big&nbsp;endian<br>SPARC&nbsp;&nbsp;&nbsp;&nbsp;UNIX&nbsp;&nbsp;&nbsp;&nbsp;Big&nbsp;endian<br>ARM</span><span style="FONT-SIZE: 9pt; COLOR: black">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-SIZE: 9pt; COLOR: black">全部</span><span style="FONT-SIZE: 9pt; COLOR: black">&nbsp;&nbsp;&nbsp;&nbsp;Little&nbsp;endian&nbsp;</span> 
<img src ="http://www.cnitblog.com/puppypyb/aggbug/48430.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/puppypyb/" target="_blank">puppy</a> 2008-08-27 15:07 <a href="http://www.cnitblog.com/puppypyb/archive/2008/08/27/48430.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GNU C扩展</title><link>http://www.cnitblog.com/puppypyb/archive/2008/08/20/48171.html</link><dc:creator>puppy</dc:creator><author>puppy</author><pubDate>Wed, 20 Aug 2008 02:30:00 GMT</pubDate><guid>http://www.cnitblog.com/puppypyb/archive/2008/08/20/48171.html</guid><wfw:comment>http://www.cnitblog.com/puppypyb/comments/48171.html</wfw:comment><comments>http://www.cnitblog.com/puppypyb/archive/2008/08/20/48171.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/puppypyb/comments/commentRss/48171.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/puppypyb/services/trackbacks/48171.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<font size=4>GNU C是一个功能非常强大的跨平台C编译器，它对C语言提供了很多扩展，这些扩展对优化、目标代码布局、更安全的检查等方面提供了很强的支持。本文把支持GNU扩展的C语言称为GNU C。<br><br>&nbsp;&nbsp;&nbsp; Linux内核代码使用了大量的GNU C扩展，以至于能够编译Linux内核的唯一编译器是GNU CC，以前甚至出现过编译 Linux内核要使用特殊的GNU CC版本的情况。本文是对Linux内核使用的GNU C扩展的一个汇总，希望当你读内核源码遇到不理解的语法和语义时，能从本文找到一个初步的解答，更详细的信息可以查看gcc.info。<br><br></font><a href="http://hi.baidu.com/zengzhaonong/blog/item/089b821619317f50f2de322a.html" target=_blank><strong><u><font color=#0000ff size=4>语句表达式</font></u></strong></a><br><font size=4>------------------------------------------<br>GNU C把包含在括号中的复合语句看做是一个表达式，称为语句表达式，它可以出现在任何允许表达式的地方，你可以在语句表达式中使用循环、局部变量等，原本只能在复合语句中使用。例如：<br>&nbsp;&nbsp;&nbsp; #define min_t(type, x, y) ({ type __x = x;\<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; type __y = y;\<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <font color=#800000><strong>__x &lt; __y ? __x : __y;</strong></font>})<br><br><font color=#800000><strong>复合语句的最后一个语句应该是一个表达式，它的值将成为这个语句表达式的值。</strong></font>这里定义了一个安全的求最小值的宏，在标准C中，通常定义为:<br>&nbsp;&nbsp;&nbsp; #define min(x,y) ((x) &lt; (y) ? (x) : (y))<br><br><strong>这个定义计算x和y分别两次(<u>x和y中的小者被计算两次</u>)，当参数有副作用时，将产生不正确的结果。</strong> 使用语句表达式只计算参数一次，避免了可能的错误。语句表达式通常用于宏定义。<br><br><br><strong>typeof</strong><br>------------------------------------------<br>使用前一节定义的宏需要知道参数的类型，利用typeof可以定义更通用的宏，不必事先知道参数的类型，例如：<br>&nbsp;&nbsp;&nbsp; 141: #define min(x,y) ({ \<br>&nbsp;&nbsp;&nbsp; 142: &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; const typeof(x) _x = (x); \<br>&nbsp;&nbsp;&nbsp; 143: &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; const typeof(y) _y = (y); \<br>&nbsp;&nbsp;&nbsp; 144: &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (void) (&amp;_x == &amp;_y); \<br>&nbsp;&nbsp;&nbsp; 145: &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _x &lt; _y ? _x : _y; })<br><br>这里typeof(x)表示x的值类型，第142行定义了一个与x类型相同的局部常量_x并初使化为x，注意第144行的作用是检查参数x和y的类型是否 相同(如果x和y的类型不同编译器将会发出warning，并不影响后面语句的执行)。typeof可以用在任何类型可以使用的地方，通常用于宏定义。<br><br><br><br></font><a href="http://hi.baidu.com/zengzhaonong/blog/item/f6ce3a1fccac55c9a786698c.html" target=_blank><strong><u><font color=#0000ff size=4>零长度数组</font></u></strong></a><br><font size=4>------------------------------------------<br>&nbsp;&nbsp;&nbsp; GNU C允许使用零长度数组，在定义变长对象的头结构时，这个特性非常有用。例如：<br>&nbsp;&nbsp;&nbsp; struct minix_dir_entry {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; __u16 inode;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; char name[0];<br>&nbsp;&nbsp;&nbsp; };<br>结构的最后一个元素定义为零长度数组，它不占结构的空间。在标准C中则需要定义数组长度为1，分配时计算对象大小比较复杂。<br><br><br><strong>可变参数宏</strong><br>------------------------------------------<br>&nbsp;&nbsp;&nbsp; 在 GNU C中，宏可以接受可变数目的参数，就象函数一样，例如：<br>&nbsp;&nbsp;&nbsp; #define KERN_DEBUG "&lt;7&gt;" <br>&nbsp;&nbsp;&nbsp; #define pr_debug(fmt,arg...) printk(KERN_DEBUG fmt,##arg)<br>这里arg表示其余的参数，可以是零个或多个，这些参数以及参数之间的逗号构成arg的值，在宏扩展时替换arg，例如：<br>&nbsp;&nbsp;&nbsp; pr_debug("%s:%d",filename,line)<br>扩展为<br>&nbsp;&nbsp;&nbsp; printk("&lt;7&gt;" "%s:%d", filename, line)<br><br>使用##的原因是处理arg不匹配任何参数的情况。如果arg的值为空，GNU C预处理器在这种特殊情况下，丢弃##之前的逗号，这样<br>&nbsp;&nbsp; pr_debug("success!\n")<br>扩展为<br>&nbsp;&nbsp; printk("&lt;7&gt;" "success!\n")<br>注意最后没有逗号。<br><br><br><strong>标号元素</strong><br>------------------------------------------<br>标准C要求数组或结构变量的初使化值必须以固定的顺序出现， 在GNU C中，通过指定索引或结构域名，允许初始化值以任意顺序出现。指定数组索引的方法是在初始化值前写 '[INDEX] ='，要指定一个范围使用 '[FIRST ... LAST] =' 的形式，例如：<br>&nbsp;&nbsp;&nbsp; static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };<br>&nbsp;&nbsp;&nbsp; 将数组的所有元素初使化为 ~0UL，这可以看做是一种简写形式。<br><br>&nbsp;&nbsp;&nbsp; 要指定结构元素，在元素值前写 'FIELDNAME:'，例如：<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; struct file_operations ext2_file_operations = {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; llseek: generic_file_llseek,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; read: generic_file_read,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; write: generic_file_write,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ioctl: ext2_ioctl,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mmap: generic_file_mmap,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; open: generic_file_open,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; release: ext2_release_file,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fsync: ext2_sync_file,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; };<br><br>将结构ext2_file_operations的元素llseek初始化为generic_file_llseek，元素read 初始化genenric_file_read，依次类推。我觉得这是GNU C 扩展中最好的特性之一，当结构的定义变化以至元素的偏移改变时，这种初始化方法仍然保证已知元素的正确性。对于未出现在初始化中的元素，其初值为 0。<br><br><br><br><strong>case范围</strong><br>------------------------------------------<br>GNU C 允许在一个 case 标号中指定一个连续范围的值，例如：<br>&nbsp;&nbsp;&nbsp; case '0' ... '9': c -= '0'; break;<br>&nbsp;&nbsp;&nbsp; case 'a' ... 'f': c -= 'a'-10; break;<br>&nbsp;&nbsp;&nbsp; case 'A' ... 'F': c -= 'A'-10; break;<br><br>&nbsp;&nbsp;&nbsp; case '0' ... '9':<br>&nbsp;&nbsp;&nbsp; 相当于<br>&nbsp;&nbsp;&nbsp; case '0': case '1': case '2': case '3': case '4':<br>&nbsp;&nbsp;&nbsp; case '5': case '6': case '7': case '8': case '9':<br><br><br><br><br><strong>声明的特殊属性</strong><br>------------------------------------------<br>GNU C允许声明函数、变量和类型的特殊属性，以便手工的代码优化和更仔细的代码检查。要指定一个声明的属性，在声明后写__attribute__ (( ATTRIBUTE ))，其中ATTRIBUTE是属性说明，多个属性以逗号分隔。GNU C支持十几个属性，这里介绍最常用的：<br><br>* noreturn<br>属性noreturn用于函数，表示该函数从不返回。这可以让编译器生成稍微优化的代码，最重要的是可以消除不必要的警告信息比如未初使化的变量。例如：<br>&nbsp;&nbsp;&nbsp; # define ATTRIB_NORET __attribute__((noreturn)) ....<br>&nbsp;&nbsp;&nbsp; asmlinkage NORET_TYPE void do_exit(long error_code)&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ATTRIB_NORET;<br><br>* format(ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK)<br>属性format用于函数，表示该函数使用printf, scanf 或strftime风格的参数，使用这类函数最容易犯的错误是格式串与参数不匹配，指定format属性可以让编译器根据格式串检查参数类型。例如：<br>&nbsp;&nbsp;&nbsp; asmlinkage int printk(const char * fmt, ...)<br>&nbsp;&nbsp;&nbsp; __attribute__ ((format (printf, 1, 2)));<br>表示第一个参数是格式串，从第二个参数起根据格式串检查参数。<br><br>* unused<br>属性unused用于函数和变量，表示该函数或变量可能不使用，这个属性可以避免编译器产生警告信息。<br><br>* section ("section-name")<br>属性section用于函数和变量，通常编译器将函数放在.text节，变量放在.data或 .bss 节，使用section属性，可以让编译器将函数或变量放在指定的节中。例如：<br>&nbsp;&nbsp;&nbsp; #define __init __attribute__ ((__section__ (".text.init")))<br>&nbsp;&nbsp;&nbsp; #define __exit __attribute__ ((unused, __section__(".text.exit")))<br>&nbsp;&nbsp;&nbsp; #define __initdata __attribute__ ((__section__ (".data.init")))<br>&nbsp;&nbsp;&nbsp; #define __exitdata __attribute__ ((unused, __section__ (".data.exit")))<br>&nbsp;&nbsp;&nbsp; #define __initsetup __attribute__ ((unused,__section__ (".setup.init")))<br>&nbsp;&nbsp;&nbsp; #define __init_call __attribute__ ((unused,__section__ (".initcall.init")))<br>&nbsp;&nbsp;&nbsp; #define __exit_call __attribute__ ((unused,__section__ (".exitcall.exit")))<br>&nbsp;&nbsp;&nbsp; 连接器可以把相同节的代码或数据安排在一起，Linux内核很喜欢使用这种技术，例如系统的初始化代码被安排在单独的一个节，在初始化结束后就可以释放这部分内存。<br><br>* aligned (ALIGNMENT)<br>属性aligned用于变量、结构或联合类型，指定变量、结构域、结构或联合的对齐量，以字节为单位，例如：<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; struct i387_fxsave_struct {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; unsigned short cwd;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; unsigned short swd;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; unsigned short twd;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; unsigned short fop;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } __attribute__ ((aligned (16)));<br>&nbsp;&nbsp;&nbsp; 表示该结构类型的变量以16字节对齐。通常编译器会选择合适的对齐量，显示指定对齐通常是由于体系限制、优化等原因。<br><br>* packed<br>属性packed用于变量和类型，用于变量或结构域时表示使用最小可能的对齐，用于枚举、结构或联合类型时表示该类型使用最小的内存。例如：<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; struct Xgt_desc_struct {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; unsigned short size;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; unsigned long address __attribute__((packed));<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; };<br>域address将紧接着size分配。属性packed的用途大多是定义硬件相关的结构，使元素之间没有因对齐而造成的空洞。<br><br><br><strong>当前函数名</strong><br>------------------------------------------<br>&nbsp;&nbsp;&nbsp; GNU CC预定义了两个标志符保存当前函数的名字，__FUNCTION__保存函数在源码中的名字；</font><a name=baidusnap0></a><font size=4><strong style="COLOR: black; BACKGROUND-COLOR: rgb(255,255,102)">__PRETTY_FUNCTION__</strong>保存带语言特色的名字。在C函数中，这两个名字是相同的，在C++函数中，<strong style="COLOR: black; BACKGROUND-COLOR: rgb(255,255,102)">__PRETTY_FUNCTION__</strong>包括函数返回类型等额外信息，Linux内核只使用了__FUNCTION__。<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void ext2_update_dynamic_rev(struct super_block *sb) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; struct ext2_super_block *es = EXT2_SB(sb)-&gt;s_es;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (le32_to_cpu(es-&gt;s_rev_level) &gt; EXT2_GOOD_OLD_REV)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ext2_warning(sb, __FUNCTION__,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "updating to rev %d because of new feature flag, "<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "running e2fsck is recommended",<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; EXT2_DYNAMIC_REV);<br>&nbsp;&nbsp;&nbsp; 这里__FUNCTION__将被替换为字符串 "ext2_update_dynamic_rev"。虽然__FUNCTION__看起来类似于标准 C中的__FILE__，但实际上__FUNCTION__是被编译器替换的，不象__FILE__ 被预处理器替换。<br><br><br><br><strong>内建函数</strong><br>------------------------------------------<br>GNU C提供了大量的内建函数，其中很多是标准C库函数的内建版本，例如memcpy，它们与对应的C库函数功能相同，本文不讨论这类函数，其他内建函数的名字通常以__builtin开始。<br>* __builtin_return_address (LEVEL)<br>内建函数__builtin_return_address返回当前函数或其调用者的返回地址，参数LEVEL指定在栈上搜索框架的个数，0表示当前函数的返回地址，1表示当前函数的调用者的返回地址，依此类推。例如：<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printk(&nbsp;&nbsp;&nbsp; KERN_ERR "schedule_timeout: wrong timeout "<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "value %lx from %p\n", timeout,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; __builtin_return_address(0));<br><br>* __builtin_constant_p(EXP)<br>内建函数__builtin_constant_p用于判断一个值是否为编译时常数，如果参数EXP的值是常数，函数返回 1，否则返回 0。例如：<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #define test_bit(nr,addr) \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (__builtin_constant_p(nr) ? \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; constant_test_bit((nr),(addr)) : \<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; variable_test_bit((nr),(addr)))<br>&nbsp;&nbsp;&nbsp; 很多计算或操作在参数为常数时有更优化的实现，在GNU C中用上面的方法可以根据参数是否为常数，只编译常数版本或非常数版本，这样既不失通用性，又能在参数是常数时编译出最优化的代码。<br><br>* __builtin_expect(EXP, C)<br>&nbsp;&nbsp;&nbsp; 内建函数__builtin_expect用于为编译器提供分支预测信息，其返回值是整数表达式EXP的值，C的值必须是编译时常数。例如：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 13: #define likely(x) __builtin_expect((x),1)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 14: #define unlikely(x) __builtin_expect((x),0)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 564: if (unlikely(in_interrupt())) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 565: printk("Scheduling in interrupt\n");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 566: BUG();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 567: }<br>&nbsp;&nbsp;&nbsp; 这个内建函数的语义是 EXP 的预期值是 C，编译器可以根据这个信息适当地重排语句块的顺序，使程序在预期的情况下有更高的执行效率。上面的例子表示处于中断上下文是很少发生的，第 565-566 行的目标码可能会放在较远的位置，以保证经常执行的目标码更紧凑。</font> 
<img src ="http://www.cnitblog.com/puppypyb/aggbug/48171.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/puppypyb/" target="_blank">puppy</a> 2008-08-20 10:30 <a href="http://www.cnitblog.com/puppypyb/archive/2008/08/20/48171.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ANSI C普通预定义宏</title><link>http://www.cnitblog.com/puppypyb/archive/2008/08/20/48169.html</link><dc:creator>puppy</dc:creator><author>puppy</author><pubDate>Wed, 20 Aug 2008 02:27:00 GMT</pubDate><guid>http://www.cnitblog.com/puppypyb/archive/2008/08/20/48169.html</guid><wfw:comment>http://www.cnitblog.com/puppypyb/comments/48169.html</wfw:comment><comments>http://www.cnitblog.com/puppypyb/archive/2008/08/20/48169.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/puppypyb/comments/commentRss/48169.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/puppypyb/services/trackbacks/48169.html</trackback:ping><description><![CDATA[<table style="TABLE-LAYOUT: fixed">
    <tbody>
        <tr>
            <td>
            <div class=cnt id=blog_text>
            <p>__FILE__ <br>This macro expands to the name of the current input file, in the form of a C string constant. This is the path by which the preprocessor opened the file, not the short name specified in #include or as the input file name argument. For example, "/usr/local/include/myheader.h" is a possible expansion of this macro.</p>
            <p>__LINE__ <br>This macro expands to the current input line number, in the form of a decimal integer constant. While we call it a predefined macro, it's a pretty strange macro, since its "definition" changes with each new line of source code. <br>__FILE__ and __LINE__ are useful in generating an error message to report an inconsistency detected by the program; the message can state the source line at which the inconsistency was detected. For example,</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp; fprintf (stderr, "Internal error: "<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "negative string length "<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "%d at %s, line %d.",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; length, __FILE__, __LINE__);<br>&nbsp;&nbsp;&nbsp;&nbsp; <br>An #include directive changes the expansions of __FILE__ and __LINE__ to correspond to the included file. At the end of that file, when processing resumes on the input file that contained the #include directive, the expansions of __FILE__ and __LINE__ revert to the values they had before the #include (but __LINE__ is then incremented by one as processing moves to the line after the #include).</p>
            <p>A #line directive changes __LINE__, and may change __FILE__ as well. See Line Control.</p>
            <p>C99 introduces __func__, and GCC has provided __FUNCTION__ for a long time. Both of these are strings containing the name of the current function (there are slight semantic differences; see the GCC manual). Neither of them is a macro; the preprocessor does not know the name of the current function. They tend to be useful in conjunction with __FILE__ and __LINE__, though.</p>
            <p><br>__DATE__ <br>This macro expands to a string constant that describes the date on which the preprocessor is being run. The string constant contains eleven characters and looks like "Feb 12 1996". If the day of the month is less than 10, it is padded with a space on the left. <br>If GCC cannot determine the current date, it will emit a warning message (once per compilation) and __DATE__ will expand to "??? ?? ????".</p>
            <p><br>__TIME__ <br>This macro expands to a string constant that describes the time at which the preprocessor is being run. The string constant contains eight characters and looks like "23:59:01". <br>If GCC cannot determine the current time, it will emit a warning message (once per compilation) and __TIME__ will expand to "??:??:??".</p>
            <p><br>__STDC__ <br>In normal operation, this macro expands to the constant 1, to signify that this compiler conforms to ISO Standard C. If GNU CPP is used with a compiler other than GCC, this is not necessarily true; however, the preprocessor always conforms to the standard unless the -traditional-cpp option is used. <br>This macro is not defined if the -traditional-cpp option is used.</p>
            <p>On some hosts, the system compiler uses a different convention, where __STDC__ is normally 0, but is 1 if the user specifies strict conformance to the C Standard. CPP follows the host convention when processing system header files, but when processing user files __STDC__ is always 1. This has been reported to cause problems; for instance, some versions of Solaris provide X Windows headers that expect __STDC__ to be either undefined or 1. See Invocation.</p>
            <p><br>__STDC_VERSION__ <br>This macro expands to the C Standard's version number, a long integer constant of the form yyyymmL where yyyy and mm are the year and month of the Standard version. This signifies which version of the C Standard the compiler conforms to. Like __STDC__, this is not necessarily accurate for the entire implementation, unless GNU CPP is being used with GCC. <br>The value 199409L signifies the 1989 C standard as amended in 1994, which is the current default; the value 199901L signifies the 1999 revision of the C standard. Support for the 1999 revision is not yet complete.</p>
            <p>This macro is not defined if the -traditional-cpp option is used, nor when compiling C++ or Objective-C.</p>
            <p><br>__STDC_HOSTED__ <br>This macro is defined, with value 1, if the compiler's target is a hosted environment. A hosted environment has the complete facilities of the standard C library available.</p>
            <p>__cplusplus <br>This macro is defined when the C++ compiler is in use. You can use __cplusplus to test whether a header is compiled by a C compiler or a C++ compiler. This macro is similar to __STDC_VERSION__, in that it expands to a version number. A fully conforming implementation of the 1998 C++ standard will define this macro to 199711L. The GNU C++ compiler is not yet fully conforming, so it uses 1 instead. We hope to complete our implementation in the near future.</p>
            <p>__OBJC__ <br>This macro is defined, with value 1, when the Objective-C compiler is in use. You can use __OBJC__ to test whether a header is compiled by a C compiler or a Objective-C compiler.</p>
            <p>__ASSEMBLER__ <br>This macro is defined with value 1 when preprocessing assembly language.</p>
            <p>GCC 中普通预定义宏<br>__GNUC__ <br>__GNUC_MINOR__ <br>__GNUC_PATCHLEVEL__ <br>These macros are defined by all GNU compilers that use the C preprocessor: C, C++, and Objective-C. Their values are the major version, minor version, and patch level of the compiler, as integer constants. For example, GCC 3.2.1 will define __GNUC__ to 3, __GNUC_MINOR__ to 2, and __GNUC_PATCHLEVEL__ to 1. They are defined only when the entire compiler is in use; if you invoke the preprocessor directly, they are not defined. <br>__GNUC_PATCHLEVEL__ is new to GCC 3.0; it is also present in the widely-used development snapshots leading up to 3.0 (which identify themselves as GCC 2.96 or 2.97, depending on which snapshot you have).</p>
            <p>If all you need to know is whether or not your program is being compiled by GCC, you can simply test __GNUC__. If you need to write code which depends on a specific version, you must be more careful. Each time the minor version is increased, the patch level is reset to zero; each time the major version is increased (which happens rarely), the minor version and patch level are reset. If you wish to use the predefined macros directly in the conditional, you will need to write it like this:</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Test for GCC &gt; 3.2.0 */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #if __GNUC__ &gt; 3 || \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (__GNUC__ == 3 &amp;&amp; (__GNUC_MINOR__ &gt; 2 || \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (__GNUC_MINOR__ == 2 &amp;&amp; \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __GNUC_PATCHLEVEL__ &gt; 0))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>Another approach is to use the predefined macros to calculate a single number, then compare that against a threshold:</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #define GCC_VERSION (__GNUC__ * 10000 \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + __GNUC_MINOR__ * 100 \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + __GNUC_PATCHLEVEL__)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Test for GCC &gt; 3.2.0 */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #if GCC_VERSION &gt; 30200<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>Many people find this form easier to understand.</p>
            <p><br>__GNUG__ <br>The GNU C++ compiler defines this. Testing it is equivalent to testing (__GNUC__ &amp;&amp; __cplusplus).</p>
            <p>__STRICT_ANSI__ <br>GCC defines this macro if and only if the -ansi switch, or a -std switch specifying strict conformance to some version of ISO C, was specified when GCC was invoked. It is defined to 1. This macro exists primarily to direct GNU libc's header files to restrict their definitions to the minimal set found in the 1989 C standard.</p>
            <p>__BASE_FILE__ <br>This macro expands to the name of the main input file, in the form of a C string constant. This is the source file that was specified on the command line of the preprocessor or C compiler.</p>
            <p>__INCLUDE_LEVEL__ <br>This macro expands to a decimal integer constant that represents the depth of nesting in include files. The value of this macro is incremented on every #include directive and decremented at the end of every included file. It starts out at 0, it's value within the base file specified on the command line.</p>
            <p>__ELF__ <br>This macro is defined if the target uses the ELF object format.</p>
            <p>__VERSION__ <br>This macro expands to a string constant which describes the version of the compiler in use. You should not rely on its contents having any particular form, but it can be counted on to contain at least the release number.</p>
            <p>__OPTIMIZE__ <br>__OPTIMIZE_SIZE__ <br>__NO_INLINE__ <br>These macros describe the compilation mode. __OPTIMIZE__ is defined in all optimizing compilations. __OPTIMIZE_SIZE__ is defined if the compiler is optimizing for size, not speed. __NO_INLINE__ is defined if no functions will be inlined into their callers (when not optimizing, or when inlining has been specifically disabled by -fno-inline). <br>These macros cause certain GNU header files to provide optimized definitions, using macros or inline functions, of system library functions. You should not use these macros in any way unless you make sure that programs will execute with the same effect whether or not they are defined. If they are defined, their value is 1.</p>
            <p><br>__CHAR_UNSIGNED__ <br>GCC defines this macro if and only if the data type char is unsigned on the target machine. It exists to cause the standard header file limits.h to work correctly. You should not use this macro yourself; instead, refer to the standard macros defined in limits.h.</p>
            <p>__WCHAR_UNSIGNED__ <br>Like __CHAR_UNSIGNED__, this macro is defined if and only if the data type wchar_t is unsigned and the front-end is in C++ mode.</p>
            <p>__REGISTER_PREFIX__ <br>This macro expands to a single token (not a string constant) which is the prefix applied to CPU register names in assembly language for this target. You can use it to write assembly that is usable in multiple environments. For example, in the m68k-aout environment it expands to nothing, but in the m68k-coff environment it expands to a single %.</p>
            <p>__USER_LABEL_PREFIX__ <br>This macro expands to a single token which is the prefix applied to user labels (symbols visible to C code) in assembly. For example, in the m68k-aout environment it expands to an _, but in the m68k-coff environment it expands to nothing. <br>This macro will have the correct definition even if -f(no-)underscores is in use, but it will not be correct if target-specific options that adjust this prefix are used (e.g. the OSF/rose -mno-underscores option).</p>
            <p><br>__SIZE_TYPE__ <br>__PTRDIFF_TYPE__ <br>__WCHAR_TYPE__ <br>__WINT_TYPE__ <br>These macros are defined to the correct underlying types for the size_t, ptrdiff_t, wchar_t, and wint_t typedefs, respectively. They exist to make the standard header files stddef.h and wchar.h work correctly. You should not use these macros directly; instead, include the appropriate headers and use the typedefs.</p>
            <p>__CHAR_BIT__ <br>Defined to the number of bits used in the representation of the char data type. It exists to make the standard header given numerical limits work correctly. You should not use this macro directly; instead, include the appropriate headers.</p>
            <p>__SCHAR_MAX__ <br>__WCHAR_MAX__ <br>__SHRT_MAX__ <br>__INT_MAX__ <br>__LONG_MAX__ <br>__LONG_LONG_MAX__ <br>Defined to the maximum value of the signed char, wchar_t, signed short, signed int, signed long, and signed long long types respectively. They exist to make the standard header given numerical limits work correctly. You should not use these macros directly; instead, include the appropriate headers.</p>
            <p>__USING_SJLJ_EXCEPTIONS__ <br>This macro is defined, with value 1, if the compiler uses the old mechanism based on setjmp and longjmp for exception handling.</p>
            <p>__NEXT_RUNTIME__ <br>This macro is defined, with value 1, if (and only if) the NeXT runtime (as in -fnext-runtime) is in use for Objective-C. If the GNU runtime is used, this macro is not defined, so that you can use this macro to determine which runtime (NeXT or GNU) is being used.</p>
            __LP64__ <br>_LP64 <br>These macros </div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cnitblog.com/puppypyb/aggbug/48169.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/puppypyb/" target="_blank">puppy</a> 2008-08-20 10:27 <a href="http://www.cnitblog.com/puppypyb/archive/2008/08/20/48169.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>