<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>ISO C, C++</title><link>http://blog.vckbase.com/smileonce/category/186.html</link><description>偶学习ISO C89/C99, ISO C++98的一些心得，书上有的、总结的很详细、很清晰的内容，将不会再这里出现。</description><managingEditor>乾坤一笑</managingEditor><dc:language>zh-CN</dc:language><generator>.Text Version 0.958.2004.214</generator><item><dc:creator>乾坤一笑</dc:creator><title>用sprintf()打印一个%号的难处</title><link>http://blog.vckbase.com/smileonce/archive/2006/03/16/18521.html</link><pubDate>Thu, 16 Mar 2006 12:12:00 GMT</pubDate><guid>http://blog.vckbase.com/smileonce/archive/2006/03/16/18521.html</guid><wfw:comment>http://blog.vckbase.com/smileonce/comments/18521.html</wfw:comment><comments>http://blog.vckbase.com/smileonce/archive/2006/03/16/18521.html#Feedback</comments><slash:comments>16</slash:comments><wfw:commentRss>http://blog.vckbase.com/smileonce/comments/commentRss/18521.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/smileonce/services/trackbacks/18521.html</trackback:ping><description>古人但凡要做一件大事，总是要先沐浴更衣。比如诸葛亮借东风，就沐浴更衣后披头散发的大作文章。姜子牙做法事，也总是先沐浴更衣然后再掐咒念诀。这么搞科学吗？为什么要这么搞？我觉得这样做能够使头脑清醒，使精神放松，使全身更有序的工作。可惜老板总是不许我们上班的时候先沐浴更衣，然后穿着睡衣、踩着拖鞋写代码，于是产品中便出现了无穷无尽的bug&amp;#8230;&amp;#8230;&lt;BR&gt;&lt;BR&gt;闲言少叙，书归正传。（最近实在是才尽，blog好久没有更新，所以把这家丑卖卖，博取两三点铜钱。大老爷儿们，父老乡亲门，大姑大姐叔叔阿姨，有钱的帮个钱场，没钱的帮个人场，当当当&amp;#8230;&amp;#8230;）今天就连sprintf()也着捉弄了我一把，想打印一个%出来，竟然也打不出来。我的代码是这么写的：&lt;BR&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;FONT color=#a000a0&gt;#include &amp;lt;stdio.h&amp;gt;
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
int&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; main&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/B&gt; argc&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; char&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; *&lt;/FONT&gt;&lt;/B&gt;argv&lt;B&gt;&lt;FONT color=#646464&gt;[])
{&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    int&lt;/FONT&gt;&lt;/B&gt; t&lt;B&gt;&lt;FONT color=#646464&gt; =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 5&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    char&lt;/FONT&gt;&lt;/B&gt; buf&lt;B&gt;&lt;FONT color=#646464&gt;[&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt;100&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;];&lt;/FONT&gt;&lt;/B&gt;
    sprintf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;buf&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt; "%% Hello, world %d times! "&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt; t&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;
    printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;buf&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    
    return&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;
}&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;
//期望显示为：% Hello, world 5 times!
//实际显示为：Hello, world 5 times!
//想打印的%没有打印出来&lt;/FONT&gt;&lt;/I&gt;&lt;/PRE&gt;看出什么毛病了么？我想除了天天处理字符串的人，才能把这个错看成一个眼中钉。笨笨如我，就愣是半天没看出为嘛没有打印出%来。我们知道printf()这一系的函数是靠一个参数(记做format参数)来控制输出格式的，如果含有%s，就表示对应位置是一个字符串，如果是%d，就表示对应位置是一个int型变量。如果想在format中占个%号的地儿，就必须连续写两个%，也就是上面代码中的sprintf()的format参数那样子，否则只有一个%，sprintf()将会忽略之，不做处理。但是，为什么最终结果没有%呢？我连续想歪了无数理由(基本功不扎实啊)。&lt;BR&gt;&lt;BR&gt;其实说穿了不值一钱，请诸位上眼关瞧。&lt;BR&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;//为了清楚起见，我把字符串都用""给括起来
&lt;/FONT&gt;&lt;/I&gt;sprintf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;buf&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt; "%% Hello, world %d times! "&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt; t&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt; //执行后的buf其实是"% Hello, world 5 times!"
&lt;/FONT&gt;&lt;/I&gt;printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;buf&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt; //printf("% Hello, world 5 times!");的结果是"Hello, world 5 times!"，一个%会被忽略掉&lt;/FONT&gt;&lt;/I&gt;&lt;/PRE&gt;哈哈，所以说，要想先用sprintf()，最后又用printf()去打印buf，就要这么写才行：&lt;BR&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;FONT color=#a000a0&gt;#include &amp;lt;stdio.h&amp;gt;
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
int&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; main&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/B&gt; argc&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; char&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; *&lt;/FONT&gt;&lt;/B&gt;argv&lt;B&gt;&lt;FONT color=#646464&gt;[])
{&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    int&lt;/FONT&gt;&lt;/B&gt; t&lt;B&gt;&lt;FONT color=#646464&gt; =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 5&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    char&lt;/FONT&gt;&lt;/B&gt; buf&lt;B&gt;&lt;FONT color=#646464&gt;[&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt;100&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;];&lt;/FONT&gt;&lt;/B&gt;
    sprintf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;buf&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt; "%%%% Hello, world %d times! "&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt; t&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;
    printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;buf&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    
    return&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;
}&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;
//结果显示为：% Hello, world 5 times!&lt;/FONT&gt;&lt;/I&gt;&lt;/PRE&gt;嘿嘿，让大家见笑了。^_^&lt;BR&gt;&lt;BR&gt;&lt;FONT color=#800080&gt;-------------&lt;BR&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT color=#a52a2a&gt;乾坤一笑 写于2006年03月16日&amp;nbsp; 转载请标明出处和原文链接&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&lt;/FONT&gt;&lt;img src ="http://blog.vckbase.com/smileonce/aggbug/18521.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>乾坤一笑</dc:creator><title>.c文件和.h文件的概念与联系</title><link>http://blog.vckbase.com/smileonce/archive/2006/02/06/17524.html</link><pubDate>Mon, 06 Feb 2006 11:54:00 GMT</pubDate><guid>http://blog.vckbase.com/smileonce/archive/2006/02/06/17524.html</guid><wfw:comment>http://blog.vckbase.com/smileonce/comments/17524.html</wfw:comment><comments>http://blog.vckbase.com/smileonce/archive/2006/02/06/17524.html#Feedback</comments><slash:comments>20</slash:comments><wfw:commentRss>http://blog.vckbase.com/smileonce/comments/commentRss/17524.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/smileonce/services/trackbacks/17524.html</trackback:ping><description>如果说难题最难的部分是基本概念，可能很多人都会持反对意见，但实际上也确实如此。&lt;BR&gt;&lt;BR&gt;我高中的时候学物理，老师抓的重点就是概念&amp;#8212;&amp;#8212;概念一定要搞清，于是难题也成了容易题。如果你能分析清楚一道物理难题存在着几个物理过程，每一个过程都遵守那一条物理定律(比如动量守恒、牛II定律、能量守恒)，那么就很轻松的根据定律列出这个过程的方程，N个过程必定是N个N元方程，难题也就迎刃而解。即便是高中的物理竞赛难题，最难之处也不过在于：(1)混淆你的概念，让你无法分析出几个物理过程，或某个物理过程遵循的那条物理定律；(2)存在高次方程，列出方程也解不出。而后者已经是数学的范畴了，所以说，最难之处还在于掌握清晰的概念。&lt;BR&gt;&lt;BR&gt;程序设计也是如此，如果概念很清晰，那基本上没什么难题(会难在数学上，比如算法的选择、时间空间与效率的取舍、稳定与资源的平衡上)。但是，要掌握清晰的概念也没那么容易。比如下面这个例子，看看你有没有很清晰透彻的认识。&lt;BR&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;//a.h
&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;void&lt;/FONT&gt;&lt;/B&gt; foo&lt;B&gt;&lt;FONT color=#646464&gt;();&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt; 

//a.c
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#include "a.h"  &lt;FONT color=#006400&gt;//&lt;STRONG&gt;我的问题出来了：这句话是要，还是不要？&lt;/STRONG&gt;&lt;/FONT&gt;
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;void&lt;/FONT&gt;&lt;/B&gt; foo&lt;B&gt;&lt;FONT color=#646464&gt;()
{&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    return&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;
}&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;

//main.c
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#include "a.h"
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; main&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/B&gt; argc&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; char&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; *&lt;/FONT&gt;&lt;/B&gt;argv&lt;B&gt;&lt;FONT color=#646464&gt;[])
{&lt;/FONT&gt;&lt;/B&gt;
    foo&lt;B&gt;&lt;FONT color=#646464&gt;();&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; 
 return&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;
}&lt;/FONT&gt;&lt;/B&gt;
&lt;/PRE&gt;
&lt;P&gt;&lt;BR&gt;针对上面的代码，请回答3个问题：&lt;BR&gt;1、a.c中的&lt;FONT color=#a000a0&gt;#include "a.h"&lt;/FONT&gt;这句话是不是多余的？&lt;BR&gt;2、为什么经常见xx.c里面include对应的xx.h？&lt;BR&gt;3、如果a.c中不写，那么编译器是不是会自动把.h文件里面的东西跟同名的.c文件绑定在一起？&lt;BR&gt;（请针对上面3道题仔细考虑10分钟，莫要着急看下面的解释。:) 考虑的越多，下面理解的就越深。）&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;好了，时间到！请忘掉上面的3道题，以及对这3道题引发出的你的想法，然后再听我慢慢道来。正确的概念是：从C编译器角度看，.h和.c皆是浮云，就是改名为.txt、.doc也没有大的分别。换句话说，就是.h和.c没啥必然联系。.h中一般放的是同名.c文件中定义的变量、数组、函数的声明，需要让.c外部使用的声明。这个声明有啥用？只是让需要用这些声明的地方方便引用。因为&lt;FONT color=#a000a0&gt;#include "xx.h"&lt;/FONT&gt;这个宏其实际意思就是把当前这一行删掉，把&lt;FONT color=#a000a0&gt;xx.h&lt;/FONT&gt;中的内容原封不动的插入在当前行的位置。由于想写这些函数声明的地方非常多（每一个调用xx.c中函数的地方，都要在使用前声明一下子），所以用&lt;FONT color=#a000a0&gt;#include "xx.h"&lt;/FONT&gt;这个宏就简化了许多行代码&amp;#8212;&amp;#8212;让预处理器自己替换好了。也就是说，&lt;FONT color=#a000a0&gt;xx.h&lt;/FONT&gt;其实只是让需要写&lt;FONT color=#a000a0&gt;xx.c&lt;/FONT&gt;中函数声明的地方调用（可以少写几行字），至于include这个.h文件是谁，是.h还是.c，还是与这个.h同名的.c，都没有任何必然关系。&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;这样你可能会说：啊？那我平时只想调用xx.c中的某个函数，却include了xx.h文件，岂不是宏替换后出现了很多无用的声明？没错，确实引入了很多垃圾&amp;nbsp;，但是它却省了你不少笔墨，并且整个版面也看起来清爽的多。鱼与熊掌不可得兼，就是这个道理。反正多些声明（.h一般只用来放声明，而放不定义，参见拙著《&lt;A id=_72fd0fb928d96e0_HomePageDays_DaysList__ctl1_DayItem_DayList__ctl1_TitleUrl href="/smileonce/archive/2006/02/05/17510.html"&gt;&lt;FONT color=#003366&gt;过马路，左右看&lt;/FONT&gt;&lt;/A&gt;》）也无害处，又不会影响编译，何乐而不为呢？&lt;BR&gt;&lt;BR&gt;翻回头再看上面的3个问题，很好解答了吧？&lt;BR&gt;1、答：不一定。这个例子中显然是多余的。但是如果.c中的函数也需要调用同个.c中的其他函数，那么这个.c往往会include同名的.h，这样就不需要为声明和调用顺序而发愁了（C语言要求使用之前必须声明，而include同名.h一般会放在.c的开头）。有很多工程甚至把这种写法约定为代码规范，以规范出清晰的代码来。&lt;BR&gt;2、答：1中已经回答过了。&lt;BR&gt;3、答：不会。问这个问题的人绝对是概念不清，要不就是想混水摸鱼。非常讨厌的是中国的很多考试出的都是这种烂题，生怕别人有个清楚的概念了，绝对要把考生搞晕。&lt;BR&gt;&lt;BR&gt;搞清楚语法和概念说易也易，说难也难。窍门有三点：1)不要晕着头工作，要抽空多思考思考，多看看书;&amp;nbsp; 2) 看书要看好书，问人要问强人。烂书和烂人都会给你一个错误的概念，误导你。3)勤能补拙是良训，一分辛苦一分才。&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&lt;FONT color=#800080&gt;-------------&lt;BR&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT color=#a52a2a&gt;乾坤一笑 写于2006年02月06日&amp;nbsp; 转载请标明出处和原文链接&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;&lt;img src ="http://blog.vckbase.com/smileonce/aggbug/17524.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>乾坤一笑</dc:creator><title>过马路，左右看</title><link>http://blog.vckbase.com/smileonce/archive/2006/02/05/17510.html</link><pubDate>Sun, 05 Feb 2006 11:51:00 GMT</pubDate><guid>http://blog.vckbase.com/smileonce/archive/2006/02/05/17510.html</guid><wfw:comment>http://blog.vckbase.com/smileonce/comments/17510.html</wfw:comment><comments>http://blog.vckbase.com/smileonce/archive/2006/02/05/17510.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://blog.vckbase.com/smileonce/comments/commentRss/17510.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/smileonce/services/trackbacks/17510.html</trackback:ping><description>小时候，大人们总是教导小孩子&amp;#8220;过马路，左右看&amp;#8221;。我年纪小不懂得为什么，但是由于大人们唠叨得遍数太多，以至于都深深印在脑海里，成为了潜意识。每每过马路的时候，不由自主得左右看看。长大以后，渐渐的喜欢考虑问题，凡事问个为什么：为什么是&amp;#8220;过马路，左右看&amp;#8221;而不是&amp;#8220;过马路，右左看&amp;#8221;？有朋友告诉我说那是因为中国话的习惯就是左右、男女、老幼之类的说，就像&amp;#8220;决一雌雄&amp;#8221;不叫作&amp;#8220;决一公母&amp;#8221;一样只是个习惯而已。可是，我觉得习惯是养成的，如果天天说&amp;#8220;过马路，右左看&amp;#8221;说多了，反倒这么说比较习惯&amp;#8212;&amp;#8212;这也说不准那～ :)&lt;BR&gt;&lt;BR&gt;其实，仔细想想，&amp;#8220;过马路，左右看&amp;#8221;是个很有道理的话。中国的车辆都是靠右行驶，所以过马路的时候前一半的过程（就是从路始边走到路中间的过程）总是车辆从我们左边开过来，而后一半的过程（从路中间到路右边的过程）总是车辆从右边开向左边。&lt;BR&gt;&lt;IMG height=186 src="/images/vckbase_com/smileonce/go_cross_road.GIF" width=402 border=0&gt;&lt;BR&gt;于是，这个俗语就教导我们先看左边再看右边，甚至可以说走前一半的时候可以只看左边，走后一半的时候可以只看右边。如果把口诀反过来做，就做了无用功；如果没有这个口诀，没准过马路时头会摇的跟一个波浪鼓似的。（&lt;FONT color=#800080&gt;注1&lt;/FONT&gt;）。&lt;BR&gt;&lt;BR&gt;中国人做事很讲究总结一个口诀，内功讲究心法，练刀有刀谱，练剑有剑诀，甚至书圣王曦之还写了个什么书诀（我忘了多少招了，那个兄弟提示下）。再比如《西游记》中说孙悟空过火焰山的时候把毛都烤糊了，于是左手捏了个避火诀冲了下去。这说明口诀很有用，本领大如孙大圣都用的上：虽然你不知道他是怎么来的，但是照着口诀做就没错&amp;#8212;&amp;#8212;老祖宗已经验证过了才总结成口诀传下来。&lt;BR&gt;&lt;BR&gt;其实软件开发的时候也有很多口诀，即便是不明白道理，但是照着做，总没错。如果不照着做，没准还真就捅了篓子，或者在代码中埋下了一时难以出现的隐患。下面就举一个C中的应用口诀的例子（C++我不懂，就不献丑拉。～）&lt;BR&gt;&lt;BR&gt;比如，有个口诀叫做&amp;#8220;定义宏常量或宏公式的时候，一定要加圆括号&amp;#8221;，有很多人就不理解，于是他们就不加，结果就出了类似于如下的问题：&lt;BR&gt;&lt;BR&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;FONT color=#a000a0&gt;#define NUM_A  100
#define NUM_B   25 * 2
#define int_div(a, b) a / b
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
float&lt;/FONT&gt;&lt;/B&gt; c&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;
c&lt;B&gt;&lt;FONT color=#646464&gt; =&lt;/FONT&gt;&lt;/B&gt; int_div&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;NUM_B&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt; NUM_A&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt; //作者原意是  50/100,实际结果是 25 * 2 / 100, 结果没错
&lt;/FONT&gt;&lt;/I&gt;c&lt;B&gt;&lt;FONT color=#646464&gt; =&lt;/FONT&gt;&lt;/B&gt; int_div&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;NUM_A&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt; NUM_B&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt; //作者原意是 100/50,实际结果是 100 / 25 * 2，结果错了。&lt;/FONT&gt;&lt;/I&gt;&lt;/PRE&gt;试想，如果我们就按照口诀来操作：&lt;BR&gt;&lt;BR&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;FONT color=#a000a0&gt;#define NUM_A (100) 
#define NUM_B (25 * 2)
#define int_div(a, b) ( (a) / (b) )&lt;/FONT&gt;&lt;/PRE&gt;又怎么会出错呢？&lt;BR&gt;&lt;BR&gt;再举个例子，比如有个口诀叫做&amp;#8220;头文件里面只声明不定义&amp;#8221;。如果不照这个口诀操作，也会出问题。比如：&lt;BR&gt;&lt;BR&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;//a.h
&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/B&gt; max&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/B&gt; a&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; int&lt;/FONT&gt;&lt;/B&gt; b&lt;B&gt;&lt;FONT color=#646464&gt;)
{&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    return&lt;/FONT&gt;&lt;/B&gt; a&lt;B&gt;&lt;FONT color=#646464&gt;&amp;gt;&lt;/FONT&gt;&lt;/B&gt;b&lt;B&gt;&lt;FONT color=#646464&gt;?&lt;/FONT&gt;&lt;/B&gt;a&lt;B&gt;&lt;FONT color=#646464&gt;:&lt;/FONT&gt;&lt;/B&gt;b&lt;B&gt;&lt;FONT color=#646464&gt;;
}&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;

//main.c
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#include "a.h"
#include "a.h" //include 两遍后就会重复定义max()，结果出重复定义的错。
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
int&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; main&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;()
{&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
	return&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;
}&lt;/FONT&gt;&lt;/B&gt;
&lt;/PRE&gt;&lt;BR&gt;你肯能会说，我在.h里面加点料儿，保证它不重复定义,比如：&lt;BR&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;//a.h
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#ifndef _A_H_
#define _A_H_
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
int&lt;/FONT&gt;&lt;/B&gt; max&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/B&gt; a&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; int&lt;/FONT&gt;&lt;/B&gt; b&lt;B&gt;&lt;FONT color=#646464&gt;)
{&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    return&lt;/FONT&gt;&lt;/B&gt; a&lt;B&gt;&lt;FONT color=#646464&gt;&amp;gt;&lt;/FONT&gt;&lt;/B&gt;b&lt;B&gt;&lt;FONT color=#646464&gt;?&lt;/FONT&gt;&lt;/B&gt;a&lt;B&gt;&lt;FONT color=#646464&gt;:&lt;/FONT&gt;&lt;/B&gt;b&lt;B&gt;&lt;FONT color=#646464&gt;;
}&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#a000a0&gt;

#endif //_A_H_&lt;/FONT&gt;&lt;/PRE&gt;Okey，现在上面那个case确实搞定了（&lt;FONT color=#800080&gt;注2&lt;/FONT&gt;）。但是下面这个就又不行了：&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;//a.h
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#ifndef _A_H_
#define _A_H_
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
int&lt;/FONT&gt;&lt;/B&gt; max&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/B&gt; a&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; int&lt;/FONT&gt;&lt;/B&gt; b&lt;B&gt;&lt;FONT color=#646464&gt;)
{&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    return&lt;/FONT&gt;&lt;/B&gt; a&lt;B&gt;&lt;FONT color=#646464&gt;&amp;gt;&lt;/FONT&gt;&lt;/B&gt;b&lt;B&gt;&lt;FONT color=#646464&gt;?&lt;/FONT&gt;&lt;/B&gt;a&lt;B&gt;&lt;FONT color=#646464&gt;:&lt;/FONT&gt;&lt;/B&gt;b&lt;B&gt;&lt;FONT color=#646464&gt;;
}&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#a000a0&gt;
#endif //_A_H_
&lt;/FONT&gt;&lt;I&gt;&lt;FONT color=#008000&gt;
//b.h
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#ifndef _B_H_
#define _B_H_
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;void&lt;/FONT&gt;&lt;/B&gt; foo&lt;B&gt;&lt;FONT color=#646464&gt;();&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#a000a0&gt;
#endif //_B_H_
&lt;/FONT&gt;&lt;I&gt;&lt;FONT color=#008000&gt;
//b.c
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#include "a.h"
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;void&lt;/FONT&gt;&lt;/B&gt; foo&lt;B&gt;&lt;FONT color=#646464&gt;()
{&lt;/FONT&gt;&lt;/B&gt;
    max&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt;100&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 200&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;);
}&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;

//c.h
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#ifndef _C_H_
#define _C_H_
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;void&lt;/FONT&gt;&lt;/B&gt; bar&lt;B&gt;&lt;FONT color=#646464&gt;();&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#a000a0&gt;
#endif //_C_H_
&lt;/FONT&gt;&lt;I&gt;&lt;FONT color=#008000&gt;
//c.c
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#include "a.h"
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;void&lt;/FONT&gt;&lt;/B&gt; bar&lt;B&gt;&lt;FONT color=#646464&gt; ()
{&lt;/FONT&gt;&lt;/B&gt;
    max&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt;300&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 400&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;);
}&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;

//main.c
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#include "b.h"
#include "c.h"
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; main&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;()
{&lt;/FONT&gt;&lt;/B&gt;
    foo&lt;B&gt;&lt;FONT color=#646464&gt;();&lt;/FONT&gt;&lt;/B&gt;
    bar&lt;B&gt;&lt;FONT color=#646464&gt;();&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
	return&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;
}&lt;/FONT&gt;&lt;/B&gt;
&lt;/PRE&gt;&lt;BR&gt;分开编译b.c、c.c和main.c都还可以通过，但是最后一link就玩儿完，因为max()被定义了两遍。所以如果max()的定义放在a.c文件里，而在a.h中只写max()的声明就不会有这个问题了。（&lt;FONT color=#800080&gt;注3&lt;/FONT&gt;）&lt;BR&gt;&lt;BR&gt;综上所述，我想说的是：如果能通透理解口诀的含义那是最好（达到了心中有剑、见招拆招的境界，每招虽无口诀的形但是却暗含了口诀的神），如果不能通透理解，不妨先照着口诀做，而不是总跟前人总结口诀对着干，真是&amp;#8220;不听老人言，吃亏在眼前&amp;#8221;。做的多了，也就慢慢悟了，可以细细琢磨口诀的真正含义，总结口诀应用的场景，从而达到避开&amp;#8220;听了老人言，吃亏在后面&amp;#8221;的境界了！：p 这就是否定之否定么？我瞎说的。^_^&lt;BR&gt;&lt;BR&gt;&lt;FONT color=#800080&gt;注1：&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080&gt;后来我想到：英国的车是靠左边开的，会不会他们教小孩子的口诀是：when going across the road, look right then left! :p&lt;BR&gt;&lt;FONT color=#800080&gt;注2：&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080&gt;这里用了&amp;#8220;头文件里面要加guard宏&amp;#8221;的口诀，所以避免了一个问题！:p&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#800080&gt;注3：&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#808080&gt;后来释雪提出来，可以在.h中定义的函数加个inline来搞定。这个例子举的不好，我只是觉得函数定义和声明的概念比变量定义和声明的概念容易描述清楚才举这个例子。其实对于出&amp;#8220;函数定义写在.h中&amp;#8221;的错还真不多见；不过把数组定义和初始化写在.h文件中可真就屡见不鲜了，有时候还真是让人头疼的狠。&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#800080&gt;-------------&lt;BR&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT color=#a52a2a&gt;乾坤一笑 写于2006年02月05日&amp;nbsp; 转载请标明出处和原文链接&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color=#000000&gt;&amp;nbsp; &lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;img src ="http://blog.vckbase.com/smileonce/aggbug/17510.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>乾坤一笑</dc:creator><title>C语言的异常机制</title><link>http://blog.vckbase.com/smileonce/archive/2005/08/16/11053.html</link><pubDate>Tue, 16 Aug 2005 15:47:00 GMT</pubDate><guid>http://blog.vckbase.com/smileonce/archive/2005/08/16/11053.html</guid><wfw:comment>http://blog.vckbase.com/smileonce/comments/11053.html</wfw:comment><comments>http://blog.vckbase.com/smileonce/archive/2005/08/16/11053.html#Feedback</comments><slash:comments>18</slash:comments><wfw:commentRss>http://blog.vckbase.com/smileonce/comments/commentRss/11053.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/smileonce/services/trackbacks/11053.html</trackback:ping><description>晚上回家翻vckbase的帖子，看到这么一段：&lt;BR&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;usr_root&lt;B&gt;&lt;FONT color=#646464&gt; :&lt;/FONT&gt;&lt;/B&gt; c99支持异常吗？
周星星&lt;B&gt;&lt;FONT color=#646464&gt;    :&lt;/FONT&gt;&lt;/B&gt; 当然不
usr_root&lt;B&gt;&lt;FONT color=#646464&gt; :&lt;/FONT&gt;&lt;/B&gt; 为什么是当然不？&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;异常机制和c无缘？&lt;/FONT&gt;&lt;/STRONG&gt;
七猫  &lt;B&gt;&lt;FONT color=#646464&gt;   :&lt;/FONT&gt;&lt;/B&gt; 当然，到现在还有很多人不喜欢异常。连有些C＋＋的标准库都支持不带异常的。
周星星&lt;B&gt;&lt;FONT color=#646464&gt;    :&lt;/FONT&gt;&lt;/B&gt; ：）俺就是这样的人
usr_root&lt;B&gt;&lt;FONT color=#646464&gt; :&lt;/FONT&gt;&lt;/B&gt; 哦，我是你的影子&lt;/PRE&gt;汗！&lt;IMG height=20 src="/Emoticons/QQ/icon18.gif" width=20 border=0&gt;&amp;nbsp;为了C语言偶不得不说几句申一下冤，真是比窦娥还冤：&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;C语言中，标准库函数setjmp和longjmp形成了结构化异常工具的基础。简单的说即setjmp实例化异常处理程序，而longjmp产生异常。&lt;/FONT&gt;&lt;/STRONG&gt;举个例子如下：&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;
/* -------------------------------------------------------------------------
** File : cexcept.c                                                        *
** Coder: Spark Song.                                                      * 
** Note : Use the example code from 《C Interfaces and Implementations》   *  
** -------------------------------------------------------------------------
*/&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;

#include &amp;lt;setjmp.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;assert.h&amp;gt;
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
int&lt;/FONT&gt;&lt;/B&gt; Allocation_handled&lt;B&gt;&lt;FONT color=#646464&gt; =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;
jmp_buf Allocate_Failed&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;

void&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; *&lt;/FONT&gt;&lt;/B&gt;allocate&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;unsigned&lt;/FONT&gt;&lt;/B&gt; n&lt;B&gt;&lt;FONT color=#646464&gt;)
{&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    void&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; *&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; new&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; = (&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;void&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; *)&lt;/FONT&gt;&lt;/B&gt;malloc&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;n&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;

    if&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; (&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;new&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;)&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
        return&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; new&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;

    if&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; (&lt;/FONT&gt;&lt;/B&gt;Allocation_handled&lt;B&gt;&lt;FONT color=#646464&gt;)&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;          /* 如果实例化了异常处理程序的话... */&lt;/FONT&gt;&lt;/I&gt;
        longjmp&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;Allocate_Failed&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 1&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt; /* 产生异常，并抛出 */&lt;/FONT&gt;&lt;/I&gt;
    
    assert&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt;0&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt; /* 如果没有实例化异常处理程序，则此断言会报出运行期的错误 */&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT color=#646464&gt;
}&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;


int&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; main&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/B&gt; argc&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; char&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; *&lt;/FONT&gt;&lt;/B&gt;argv&lt;B&gt;&lt;FONT color=#646464&gt;[])
{&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    char&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; *&lt;/FONT&gt;&lt;/B&gt;buf&lt;B&gt;&lt;FONT color=#646464&gt; =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    int&lt;/FONT&gt;&lt;/B&gt; count&lt;B&gt;&lt;FONT color=#646464&gt; =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;


    Allocation_handled&lt;B&gt;&lt;FONT color=#646464&gt; =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 1&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;         /* 设置实例化异常的标志，设为1表示实例化了异常处理程序 */&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; 
    if&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; (&lt;/FONT&gt;&lt;/B&gt;setjmp&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;Allocate_Failed&lt;B&gt;&lt;FONT color=#646464&gt;))&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;    /* 实例化异常 */&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT color=#646464&gt;
    {&lt;/FONT&gt;&lt;/B&gt;
        fprintf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;stderr&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt; "EXCEPT: Couldn't allocate the buffer\n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt; 
        exit&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;EXIT_FAILURE&lt;B&gt;&lt;FONT color=#646464&gt;);
    }&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;      
        
    while&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt;1&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;)&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;    /* 测试代码：一直分配内存，直到没有内存为止。没有内存时会触发异常 */&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT color=#646464&gt;
    {&lt;/FONT&gt;&lt;/B&gt;
        buf&lt;B&gt;&lt;FONT color=#646464&gt; = (&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;char&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; *)&lt;/FONT&gt;&lt;/B&gt;allocate&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt;4096000&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;         
        printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt;"Allocate successs, the count is: %d\n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt; count&lt;B&gt;&lt;FONT color=#646464&gt;++);
    }&lt;/FONT&gt;&lt;/B&gt;

    Allocation_handled&lt;B&gt;&lt;FONT color=#646464&gt; =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;  
	return&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;
}&lt;/FONT&gt;&lt;/B&gt;
&lt;/PRE&gt;
&lt;P&gt;上面这个例子在MingW下通过，编译时使用了-std=c89 -pedantic的编译开关(强制使用c89的语法检查)和-std=iso9899:199409&amp;nbsp; -pedantic（强制使用c99的语法检查）。运行结果如下：&lt;/P&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;FONT color=#000080&gt;Allocate successs&lt;B&gt;,&lt;/B&gt; the count is&lt;B&gt;:&lt;/B&gt;   1&lt;/FONT&gt;&lt;B&gt;
&lt;FONT color=#000080&gt;... ...&lt;/FONT&gt;&lt;/B&gt;
&lt;FONT color=#000080&gt;Allocate successs&lt;B&gt;,&lt;/B&gt; the count is&lt;B&gt;:&lt;/B&gt; 447
Allocate successs&lt;B&gt;,&lt;/B&gt; the count is&lt;B&gt;:&lt;/B&gt; 448
Allocate successs&lt;B&gt;,&lt;/B&gt; the count is&lt;B&gt;:&lt;/B&gt; 449
Allocate successs&lt;B&gt;,&lt;/B&gt; the count is&lt;B&gt;:&lt;/B&gt; 450&lt;/FONT&gt;
&lt;FONT color=#800080&gt;&lt;STRONG&gt;EXCEPT: Couldn't allocate the buffer&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;简要讲述一下代码的流程：setjmp用来实例化异常处理程序，在这里我们的异常处理程序就是往stderr输出一个字符串并退出应用程序。setjmp会返回2次值（颇有些fork()的味道）。setjmp第一次返回值是在应用代码（这里就是main函数里面）调用setjmp的地方，这时候它实例化了异常处理程序，并返回0,所以异常处理程序的代码并没有被执行。在allocate中调用longjmp的时候，会引起setjmp第二次值的返回，此时的返回值由longjmp的第二个参数所决定。文中我们调用longjmp的时候，传给它的第二个参数是1,所以setjmp返回时会执行if中的异常处理程序。&lt;BR&gt;&lt;BR&gt;这个例子就是最最简单的C语言处理异常的原型，我们完全可以利用它来构造出一整套的异常处理体系，一点也不比C＋＋之类的高级语言差。为什么不把异常加入语言本身？我想这是由C语言的设计理念和设计目的决定的。C语言是面向底层和系统开发的较低级的语言，所以语言本身并不复杂，强大的功能完全可以通过函数库来实现。&lt;BR&gt;&lt;BR&gt;欲更深入的了解C语言的异常处理体系的设计，可以参考David R.Hanson的&lt;I&gt;C Interfaces and Implementations&lt;/I&gt;(中文版《C语言接口与实现》）。&lt;BR&gt;&lt;BR&gt;爱书吧，它是知识的源泉！～～&lt;BR&gt;&lt;BR&gt;&lt;FONT color=#800080&gt;-------------&lt;BR&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT color=#a52a2a&gt;乾坤一笑 写于2005年8月16日&amp;nbsp; 转载请标明出处和原文链接&lt;/STRONG&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&lt;/P&gt;&lt;img src ="http://blog.vckbase.com/smileonce/aggbug/11053.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>乾坤一笑</dc:creator><title>解惑：sizeof(联合)这个值是怎么计算的</title><link>http://blog.vckbase.com/smileonce/archive/2005/08/08/10658.html</link><pubDate>Mon, 08 Aug 2005 14:13:00 GMT</pubDate><guid>http://blog.vckbase.com/smileonce/archive/2005/08/08/10658.html</guid><wfw:comment>http://blog.vckbase.com/smileonce/comments/10658.html</wfw:comment><comments>http://blog.vckbase.com/smileonce/archive/2005/08/08/10658.html#Feedback</comments><slash:comments>27</slash:comments><wfw:commentRss>http://blog.vckbase.com/smileonce/comments/commentRss/10658.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/smileonce/services/trackbacks/10658.html</trackback:ping><description>&lt;P&gt;[不要只做技术]在论坛上问如下代码结果为什么是24?&lt;/P&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;union&lt;/FONT&gt;&lt;/B&gt; DATE&lt;B&gt;&lt;FONT color=#646464&gt;
{&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    char&lt;/FONT&gt;&lt;/B&gt; a&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    int&lt;/FONT&gt;&lt;/B&gt; i&lt;B&gt;&lt;FONT color=#646464&gt;[&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt;5&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;];&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    double&lt;/FONT&gt;&lt;/B&gt; b&lt;B&gt;&lt;FONT color=#646464&gt;;
};&lt;/FONT&gt;&lt;/B&gt;

DATE max&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;

cout&lt;B&gt;&lt;FONT color=#646464&gt;&amp;lt;&amp;lt;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; sizeof&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;max&lt;B&gt;&lt;FONT color=#646464&gt;) &amp;lt;&amp;lt;&lt;/FONT&gt;&lt;/B&gt; endl&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;BR&gt;&lt;/PRE&gt;
&lt;P&gt;这个问题很好回答，并且我把这个问题归结于基本概念题（就是入门书必须介绍的）。我想一般来说，做过内存管理的，对这个语言特性肯定不会陌生。&lt;BR&gt;&lt;BR&gt;摘几句&lt;I&gt;The C Programming Language&lt;/I&gt;里面讲述这个问题的原话，以说明读书还是必要的：&lt;BR&gt;&lt;FONT color=#000080&gt;①联合就是一个结构，②它的所有成员相对于基地址的偏移量都为0,③此结构空间要大到足够容纳最&amp;#8220;宽&amp;#8221;的成员，④并且，其对齐方式要适合于联合中所有类型的成员。&lt;BR&gt;&lt;/FONT&gt;&lt;BR&gt;怕有的兄弟还不明白，特附图一个帮助理解：&lt;BR&gt;
&lt;TABLE cellSpacing=0 cellPadding=0 width=265 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width=98&gt;char a;&lt;/TD&gt;
&lt;TD width=26&gt;&lt;FONT color=#a52a2a&gt;&lt;STRONG&gt;=&amp;gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2 bgColor=#003399&gt;&lt;FONT color=#000080&gt;x&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2 bgColor=#ffffff&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2 bgColor=#ffffff&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2 bgColor=#ffffff&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=2&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TR&gt;
&lt;TD width=98&gt;int i[5];&lt;/TD&gt;
&lt;TD width=26&gt;&lt;FONT color=#a52a2a&gt;&lt;STRONG&gt;=&amp;gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD borderColor=#999999 bgColor=#ff3300 colSpan=4&gt;
&lt;P align=center&gt;&lt;FONT color=#ff0000&gt;&amp;nbsp;x&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=24 bgColor=#ff3300 colSpan=4&gt;
&lt;P align=center&gt;&lt;FONT color=#ff0000&gt;&amp;nbsp;x&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=24 bgColor=#ff3300 colSpan=4&gt;
&lt;P align=center&gt;&lt;FONT color=#ff0000&gt;&amp;nbsp;x&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=24 bgColor=#ff3300 colSpan=4&gt;
&lt;P align=center&gt;&lt;FONT color=#ff0000&gt;&amp;nbsp;x&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=24 bgColor=#ff3300 colSpan=4&gt;
&lt;P align=center&gt;&lt;FONT color=#ff0000&gt;&amp;nbsp;x&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=24 bgColor=#ffcc66 colSpan=4&gt;
&lt;P align=center&gt;&lt;FONT color=#000000&gt;x&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width=98&gt;double b;&lt;/TD&gt;
&lt;TD width=26&gt;&lt;FONT color=#a52a2a&gt;&lt;STRONG&gt;=&amp;gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD borderColor=#999999 bgColor=#006600 colSpan=8&gt;
&lt;P align=center&gt;&amp;nbsp;&lt;FONT color=#006400&gt;x&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=24 colSpan=8&gt;
&lt;P align=center&gt;&amp;nbsp;&lt;/P&gt;&lt;/TD&gt;
&lt;TD borderColor=#999999 width=24 colSpan=8&gt;
&lt;P align=center&gt;&amp;nbsp;&lt;/P&gt;&lt;/TD&gt;
&lt;P align=center&gt;&amp;nbsp;
&lt;P&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/P&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;BR&gt;&lt;FONT color=#000080&gt;&lt;U&gt;该结构要放得下int i[5]必须要至少占4&amp;#215;5=20个字节。如果没有double的话20个字节够用了，此时按4字节对齐。但是加入了double就必须考虑double的对齐方式，double是按照8字节对齐的，所以必须添加4个字节使其满足8&amp;#215;3=24,也就是必须也是8的倍数，这样一来就出来了24这个数字。综上所述，最终联合体的最小的size也要是所包含的所有类型的基本长度的最小公倍数才行。（这里的字节数均指winnt下的值，平台、编译器不同值也有可能不同。）&lt;/U&gt;&lt;/FONT&gt;&lt;BR&gt;&lt;BR&gt;联合在存储分配的时候用的机会最多，因为很少有像存储分配这样需要给多种不同类型的变量分配空间而又打算尽可能的节约内存的，这很适合联合的特性。上述对齐的方式有个很有趣的用法也就常在存储分配里面使用。（下面依旧用&lt;EM&gt;The C Programming Language&lt;/EM&gt;中的例子作答）&lt;/P&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;typedef&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; long&lt;/FONT&gt;&lt;/B&gt; Align&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;

union&lt;/FONT&gt;&lt;/B&gt; header&lt;B&gt;&lt;FONT color=#646464&gt; {&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    struct&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; {&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
        union&lt;/FONT&gt;&lt;/B&gt; header&lt;B&gt;&lt;FONT color=#646464&gt; *&lt;/FONT&gt;&lt;/B&gt;ptr&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
        unsigned&lt;/FONT&gt;&lt;/B&gt; size&lt;B&gt;&lt;FONT color=#646464&gt;;
    }&lt;/FONT&gt;&lt;/B&gt; s&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;
    Align x&lt;B&gt;&lt;FONT color=#646464&gt;;
}&lt;/FONT&gt;&lt;/B&gt;&lt;/PRE&gt;
&lt;P&gt;这里的Align有什么用？作用只有一个，就是强迫分配的结构体按long的长度对齐。&lt;BR&gt;&lt;BR&gt;爱书吧，它是知识的源泉！～～&lt;BR&gt;&lt;BR&gt;&lt;FONT color=#800080&gt;-------------&lt;BR&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT color=#a52a2a&gt;乾坤一笑 写于2005年8月8日&amp;nbsp; 转载请标明出处和原文链接&lt;/STRONG&gt;&lt;/FONT&gt; &lt;/P&gt;&lt;img src ="http://blog.vckbase.com/smileonce/aggbug/10658.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>乾坤一笑</dc:creator><title>第三方C代码移植过程中的typedef重复定义问题</title><link>http://blog.vckbase.com/smileonce/archive/2005/08/06/10547.html</link><pubDate>Sat, 06 Aug 2005 07:21:00 GMT</pubDate><guid>http://blog.vckbase.com/smileonce/archive/2005/08/06/10547.html</guid><wfw:comment>http://blog.vckbase.com/smileonce/comments/10547.html</wfw:comment><comments>http://blog.vckbase.com/smileonce/archive/2005/08/06/10547.html#Feedback</comments><slash:comments>29</slash:comments><wfw:commentRss>http://blog.vckbase.com/smileonce/comments/commentRss/10547.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/smileonce/services/trackbacks/10547.html</trackback:ping><description>楔子：&lt;BR&gt;&amp;nbsp; 本文主要描述了把第三方代码移植到某一目标平台过程中所发生的typedef重复定义的问题。之所以要写这个问题，原因有三：1&amp;gt;这个问题是一个移植代码过程中经常遇到的老大难问题2&amp;gt;我还没有完全（或者说完美的）解决这个问题3&amp;gt;想得到诸位高手的点拨。&lt;BR&gt;&lt;BR&gt;首先要看看下面的原始代码（为了突出重点，我简化了代码结构。实际代码要复杂的多）：&lt;BR&gt;a.c和a.h代表主开发平台的代码，下面简称为A平台代码；b.c和b.h代表要移植到A平台的第三方的代码，下面简称为B代码。&lt;BR&gt;&lt;FONT color=#ff0000 size=4&gt;&lt;STRONG&gt;&lt;BR&gt;&amp;lt;代码片断I&amp;gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;BR&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;//filename: b.h
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#ifndef B_H
#define B_H
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
typedef&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; long&lt;/FONT&gt;&lt;/B&gt; INT32&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;

void&lt;/FONT&gt;&lt;/B&gt; b_bar&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;INT32 num&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#a000a0&gt;

#endif //B_H&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;/P&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;//filename: b.c
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;
#include &amp;lt;stdio.h&amp;gt;
#include "b.h"
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
void&lt;/FONT&gt;&lt;/B&gt; b_bar&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;INT32 num&lt;B&gt;&lt;FONT color=#646464&gt;)
{&lt;/FONT&gt;&lt;/B&gt;
	printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt;"b_bar trace: %d\n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt; num&lt;B&gt;&lt;FONT color=#646464&gt;);
}&lt;/FONT&gt;&lt;/B&gt;&lt;/PRE&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;//filename: a.h
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#ifndef A_H
#define A_H
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
typedef&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; short&lt;/FONT&gt;&lt;/B&gt; INT32&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;

void&lt;/FONT&gt;&lt;/B&gt; a_foo&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;INT32 num&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#a000a0&gt;

#endif //A_H&lt;/FONT&gt;&lt;/PRE&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;//filename: a.c
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#include &amp;lt;stdio.h&amp;gt;
#include "a.h"
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
void&lt;/FONT&gt;&lt;/B&gt; a_foo&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;INT32 num&lt;B&gt;&lt;FONT color=#646464&gt;)
{&lt;/FONT&gt;&lt;/B&gt;
	printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt;"a_foo trace: %d\n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt; num&lt;B&gt;&lt;FONT color=#646464&gt;);
}&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;

int&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; main&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;()
{&lt;/FONT&gt;&lt;/B&gt;
	INT32 abc&lt;B&gt;&lt;FONT color=#646464&gt;=&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt;100&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;
	a_foo&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;abc&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;
&lt;B&gt;&lt;FONT color=#646464&gt;}&lt;/FONT&gt;&lt;/B&gt;&lt;/PRE&gt;源代码中A代码和B代码中并无任何瓜葛。A代码和B代码中都定义了一个叫做INT32的类型，但是在A代码中INT32是以short为原型的，就是说A代码中所有使用INT32的类型都是期望使用short的。同理，B代码中的所有使用INT32类型的地方都是期望使用long的。因此，我们只要在移植过程中保证A代码和B代码中的类型定义都满足自己原始的期望，那么这个移植过程中类型定义就是成功的，代码运行起来也就会很稳定；反之，移植的代码就存在着极大的风险。&lt;BR&gt;&lt;BR&gt;现在进入正题。我们想在a.c中使用B代码中的b_bar()这个函数，常规的方法是这样的：&lt;BR&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000 size=4&gt;&amp;lt;代码片断II&amp;gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;BR&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;//filename: a.c
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#include &amp;lt;stdio.h&amp;gt;
#include "a.h"
&lt;/FONT&gt;&lt;I&gt;&lt;FONT color=#008000&gt;
&lt;STRONG&gt;//////// Add this include sentence,We want use B 's declare&lt;/STRONG&gt;
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;&lt;STRONG&gt;#include "b.h"&lt;/STRONG&gt; 
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
void&lt;/FONT&gt;&lt;/B&gt; a_foo&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;INT32 num&lt;B&gt;&lt;FONT color=#646464&gt;)
{&lt;/FONT&gt;&lt;/B&gt;
	printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt;"a_foo trace: %d\n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt; num&lt;FONT color=#646464&gt;&lt;STRONG&gt;);
}&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;

&lt;STRONG&gt;void&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt; a_xxx&lt;FONT color=#646464&gt;(&lt;/FONT&gt;INT32 num&lt;FONT color=#646464&gt;)&lt;/FONT&gt;&lt;/STRONG&gt;&lt;STRONG&gt;&lt;I&gt;&lt;FONT color=#008000&gt;  ///////// Add this function
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#646464&gt;{&lt;/FONT&gt;
	printf&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;FONT color=#ff00ff&gt;"a_xxx trace: %d\n"&lt;/FONT&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt; num&lt;FONT color=#646464&gt;);&lt;/FONT&gt;
	b_bar&lt;FONT color=#646464&gt;(&lt;/FONT&gt;num&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/STRONG&gt;&lt;STRONG&gt;&lt;I&gt;&lt;FONT color=#008000&gt;   ///////// Call b_bar() function
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#646464&gt;}&lt;/FONT&gt;&lt;/STRONG&gt;&lt;FONT color=#0000ff&gt;

&lt;STRONG&gt;int&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt; main&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT color=#646464&gt;&lt;STRONG&gt;()
{&lt;/STRONG&gt;&lt;/FONT&gt;
	INT32 abc&lt;B&gt;&lt;FONT color=#646464&gt;=&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt;100&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;
	a_foo&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;abc&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt; 
	&lt;STRONG&gt;a_xxx&lt;FONT color=#646464&gt;(&lt;/FONT&gt;abc&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/STRONG&gt;&lt;I&gt;&lt;FONT color=#008000&gt;&lt;STRONG&gt;  ///////// Use a_xxx() function&lt;/STRONG&gt;
&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT color=#646464&gt;}&lt;/FONT&gt;&lt;/B&gt;&lt;/PRE&gt;但是，我们代码如果这么使用的话，就会出错。错误的原因大概是：redefinition; different basic types。重复定义，不一致的基本类型。因为A代码和B代码中都定义了INT32这个类型。&lt;BR&gt;&lt;BR&gt;那么我们应该如何搞定？有大概三种方法来解决这个问题，我们一一来看。&lt;BR&gt;&lt;BR&gt;一、extern声明法&lt;BR&gt;这种方法的基本思想是讲问题由编译阶段推迟到链接阶段。我一般会优先使用这种方法，代码如下：&lt;BR&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000 size=4&gt;&amp;lt;代码片断III&amp;gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;BR&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;//filename: a.c
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#include &amp;lt;stdio.h&amp;gt;
#include "a.h"
&lt;/FONT&gt;&lt;I&gt;&lt;FONT color=#008000&gt;
&lt;STRONG&gt;///Use extern declare instead of include sentence, and use long instead of INT32&lt;/STRONG&gt;
&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;extern&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; void&lt;/FONT&gt;&lt;/B&gt; b_bar&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;long&lt;/FONT&gt;&lt;/B&gt; num&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;

void&lt;/FONT&gt;&lt;/B&gt; a_foo&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;INT32 num&lt;B&gt;&lt;FONT color=#646464&gt;)
{&lt;/FONT&gt;&lt;/B&gt;
	printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt;"a_foo trace: %d\n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt; num&lt;B&gt;&lt;FONT color=#646464&gt;);
}&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;

void&lt;/FONT&gt;&lt;/B&gt; a_xxx&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;INT32 num&lt;B&gt;&lt;FONT color=#646464&gt;)&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;  ///////// Add this function
&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT color=#646464&gt;{&lt;/FONT&gt;&lt;/B&gt;
	printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt;"a_xxx trace: %d\n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt; num&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;
	b_bar&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;num&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;   ///////// Call b_bar() function
&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT color=#646464&gt;}&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;

int&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; main&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;()
{&lt;/FONT&gt;&lt;/B&gt;
	INT32 abc&lt;B&gt;&lt;FONT color=#646464&gt;=&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt;100&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;
	a_foo&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;abc&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt; 
	a_xxx&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;abc&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;  ///////// Use a_xxx() function
&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT color=#646464&gt;}&lt;/FONT&gt;&lt;/B&gt;&lt;/PRE&gt;如上面代码所示，我不再在A代码里面include B代码的.h文件，这样就避免了typedef的重复定义。同时，我修改了extern的b_bar()的声明，使其使用C语言基本类型long，这样就满足了B代码的原始期望，B代码运行起来就不会有错。通过extern，将问题推迟到链接期，链接的过程中是以原始类型为基准的，所以链接起来也不会出错。基本上就解决了这个问题。&lt;BR&gt;方法一的缺点：1&amp;gt;修改extern的B代码的声明中的类型为基本类型，看起来代码不是很优雅；2&amp;gt;如果A代码中多处使用B代码，或者要使用B代码中的多个函数，大量的extern将使代码看起来非常的恶心。&lt;BR&gt;&lt;BR&gt;二、统一typedef法&lt;BR&gt;我所使用的X公司的源代码实际上也是有好几个部分拼接而成的，每个部分都有自己的typedef。它的代码中通过如下方法来规避typedef重复定义的问题：&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000 size=4&gt;&amp;lt;代码片断IV&amp;gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;BR&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;//filename: b.h
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#ifndef B_H
#define B_H

#ifndef A_H
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;typedef&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; long&lt;/FONT&gt;&lt;/B&gt; INT32&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#a000a0&gt;
#endif
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
void&lt;/FONT&gt;&lt;/B&gt; b_bar&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;INT32 num&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#a000a0&gt;

#endif //B_H&lt;/FONT&gt;&lt;/PRE&gt;&lt;FONT color=#000080&gt;修改b.h，而b.c、a.h 使用代码片断1的，a.c使用代码片断2的。&lt;BR&gt;&lt;/FONT&gt;这样一来，B代码在b.h进行typedef的时候，如果检测到目前代码中已经存在了INT32这个定义，就不在进行这个定义了，就使用现存的INT32这个定义。这样一来，其实B代码在使用short来替代INT32,而不是它的原始期望中的long。我个人认为，这会导致B代码中的某些实现不稳定、出错。所以在移植第三方代码过程中，我绝对不推荐这种用法。（这是开讨论会中争议最大的地方，如果你有金砖，千万不要吝惜，拍过来吧～～让暴风雨来的更猛烈些吧）&lt;BR&gt;&lt;BR&gt;三、类型适配法&lt;BR&gt;这段文字已经不是再解决上面的问题了，纯粹是做为一种引申的思路而已。某些公司的代码会提供自己名字前缀的typedef，如ABC公司的类型定义就是ABC_INT32，而XXX公司的类型定义就是XXX_INT32。这样就能保证自己的类型定义总是在自己内部使用，而不至于引起冲突来。&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000 size=4&gt;&amp;lt;代码片断V&amp;gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;BR&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;//filename: b.h
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;#ifndef B_H
#define B_H
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
typedef&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; long&lt;/FONT&gt;&lt;/B&gt; B_INT32&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;

void&lt;/FONT&gt;&lt;/B&gt; b_bar&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;B_INT32 num&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#a000a0&gt;

#endif //B_H&lt;/FONT&gt;&lt;/PRE&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;//filename: b.c
&lt;/FONT&gt;&lt;/I&gt;&lt;FONT color=#a000a0&gt;
#include &amp;lt;stdio.h&amp;gt;
#include "b.h"
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
void&lt;/FONT&gt;&lt;/B&gt; b_bar&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;B_INT32 num&lt;B&gt;&lt;FONT color=#646464&gt;)
{&lt;/FONT&gt;&lt;/B&gt;
	printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt;"b_bar trace: %d\n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt; num&lt;B&gt;&lt;FONT color=#646464&gt;);
}&lt;/FONT&gt;&lt;/B&gt;
&lt;/PRE&gt;&lt;BR&gt;&lt;FONT color=#000080&gt;修a.h 使用代码片断1的，a.c使用代码片断2的。&lt;/FONT&gt;&lt;BR&gt;这样就不会在A代码和B代码之间引起类型定义冲突了。如果类型定义复杂了，有可能在A和B之间要进行强制类型转换，这点的确不爽。不过一般B代码会引入一个类型适配层，用typedef来把A和B之间的类型建立等价关系，这样就一点问题也没有了。&lt;BR&gt;&lt;BR&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;I&gt;&lt;FONT color=#008000&gt;//filename: b_type_adapt.h
&lt;/FONT&gt;&lt;/I&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;typedef&lt;/FONT&gt;&lt;/B&gt; B_INT32 A_INT&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
typedef&lt;/FONT&gt;&lt;/B&gt; B_UINT32 A_UINT&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;
&lt;/PRE&gt;&lt;BR&gt;在A代码中使用B代码的时候就include这个b_type_adapt.h，这样A就能正确识别出B的类型来。问题就完全解决了。&lt;BR&gt;&lt;BR&gt;总结：遗憾的是，有很多公司的代码都不是按照方法3来做的，它们都认为自己比较牛，自己应该定义原始类型，％^&amp;amp;（&amp;#215;）#％￥^&amp;amp;&amp;#8230;&amp;#8230; 唉，就苦了我们porting engineer了。因为是做porting，所以我不能把B中的typedef的类型做个全文替换，这样以后升级B代码就更头疼了。唉，这年头混口饭吃不容易阿～～&lt;BR&gt;&lt;FONT color=#800080&gt;-------------&lt;BR&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT color=#a52a2a&gt;乾坤一笑 写于2005年8月6日&amp;nbsp; 转载请标明出处和原文链接&lt;/STRONG&gt;&lt;/FONT&gt; &lt;img src ="http://blog.vckbase.com/smileonce/aggbug/10547.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>乾坤一笑</dc:creator><title>C语言学习方法</title><link>http://blog.vckbase.com/smileonce/archive/2005/08/01/10379.html</link><pubDate>Mon, 01 Aug 2005 12:44:00 GMT</pubDate><guid>http://blog.vckbase.com/smileonce/archive/2005/08/01/10379.html</guid><wfw:comment>http://blog.vckbase.com/smileonce/comments/10379.html</wfw:comment><comments>http://blog.vckbase.com/smileonce/archive/2005/08/01/10379.html#Feedback</comments><slash:comments>44</slash:comments><wfw:commentRss>http://blog.vckbase.com/smileonce/comments/commentRss/10379.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/smileonce/services/trackbacks/10379.html</trackback:ping><description>&lt;P&gt;谈谈偶的学习方法，抛砖引玉！：）&lt;BR&gt;&lt;BR&gt;学习不论讲不讲方法，最终都能学会。但是别人1个月学会了，而你却100年才学会，这不就晚了么？：）所以说，学习还是要讲究方法的。学习方法正确，事半功倍；学习方法不正确，事倍而功半。&lt;BR&gt;&lt;BR&gt;什么才是学习C语言的捷径？我的答案是看书。书中所写，是前人数十年经验所写，看十本书，就相当于汲取了前人数十年的功力，那么你的内功也会迅速上升1甲子。：）书当然要看好书，只有好书才营养丰富。假如你花了1天时间看了一本破书，而该书介绍的知识虽然对于你来说是全新的知识，但是由于书中组织不当、或者深度不够，使你获取的营养很少，还不如自己研究一天来的快，这种书就不值当看了。学习C语言要看那些好书？我认为首先要把基础书给看扎实了，比如拙著《&lt;A class=postTitle2 id=viewpost1_TitleUrl href="/smileonce/archive/2004/12/05/1898.html"&gt;&lt;FONT color=#0000cc&gt;C语言之四书五经&lt;/FONT&gt;&lt;/A&gt;》中介绍的4本。（虽然这些书很多已经绝版了，但我相信电子版也是很有益处。况且，如果你真的想看，我相信你一定有办法搞的到。）这些书你会在很短的时间内看完（比如一两个月），这取决于你的基础和悟性。之后要看那些书呢？我不妨再列几本。Bjarne Stroustrup的《C++程序设计语言》（&lt;I&gt;The C++ Programming Language&lt;/I&gt;）一定要看，这本书里面对于C的一些基础概念的定义，比我见过的其他任何C语言书都要全，都要仔细；Bjarne Stroustrup的《C++语言的设计与演化》（&lt;I&gt;The Design and Evolution of C++&lt;/I&gt;）和David R.Hanson 的《C语言接口与实现 创建可重用软件的技术》（&lt;I&gt;C Interfaces and Implaementations Techniques for Creating Reusable Software&lt;/I&gt;）一定要看，这两本书讲述了如何用C来实现异常处理、实现类型的封装和扩展等一些大的项目中经常用到的高级技术。其他的书，操作系统的要看，编译原理的要看，算法的要看，模式的也要看。读书破万卷，coding如有神。总而言之，就如《传》中云：&amp;#8220;生而知之者，上也；学而知之者，次也；困而学之又其次也。&amp;#8221;我们不能总是因困而学之，而要做到兵马未动，粮草先行。&lt;BR&gt;&lt;BR&gt;看书是学习的导向，书中能一一介绍清楚概念，但书却不能把应用的细节一一介绍给你，因为应用总是招数繁复，变化多端。因此我们要想熟悉招数，懂得书中所讲怎么使用，还要多读源码。Linus给别人解答问题的时候，常说Read the fucking source code；候捷也在其文中提到&amp;#8220;源码之前，了无秘密。&amp;#8221;这就是大师的箴言呀。源码就像是动画、就像是幻灯片，把书中的招式一一演练给你看。可以说高手的经验大都是源自代码。源码和书一样，也是要看好的，不要看差的。在此，我推荐看Linux kernel source code 和 Linux tcp/ip source code。这两套代码都是开源的，垂手可得。此外，还可以配合着Andrew S.Tanenbaum的《操作系统的设计与实现》(&lt;I&gt;Operating Systems：Design and Implementation&lt;/I&gt;)、毛德操 胡希明的《Linux内核 源代码情景分析》、Jonathan Corbet,Alessandro Rubini,Greg Kroah-Hartman合著的《Linux设备驱动程序》（&lt;I&gt;Linux Device Driver,3e&lt;/I&gt;）、W.Richard Stevens《TCP/IP详解（3部）》&lt;I&gt; (TCP/IP Illustracted )&lt;/I&gt;、W.Richard Stevens《UNIX环境高级编程》（&lt;I&gt;Advanced Programming in the UNIX Environment&lt;/I&gt;，新版增加了Linux kernel的内容）等书来看，方便的很。&lt;BR&gt;&lt;BR&gt;当然程序不是看出来的，是写出来的。我高中的时候每天坚持写6个小时程序，《数据结构》和排列组合、图论方面的习题反复做了N遍。到现在虽然已经时隔五六年，很多内容早已淡忘掉，但却培养了我很强的编码能力和调试能力，直到现在还对我的工作有很大的帮助。&lt;BR&gt;&lt;BR&gt;学习忌贪多、忌浮躁、忌急功近利、忌目中无人。把学习计划放的长一些，培养一个好的学习方法，一步一步慢慢走，终能成为高手。&lt;BR&gt;&lt;FONT color=#800080&gt;-------------&lt;BR&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT color=#a52a2a&gt;乾坤一笑 写于2005年8月1日&amp;nbsp; 转载请标明出处和原文链接&lt;/STRONG&gt;&lt;/FONT&gt; &lt;/P&gt;&lt;img src ="http://blog.vckbase.com/smileonce/aggbug/10379.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>乾坤一笑</dc:creator><title>为什么不常见include .c文件</title><link>http://blog.vckbase.com/smileonce/archive/2005/07/26/10070.html</link><pubDate>Tue, 26 Jul 2005 14:02:00 GMT</pubDate><guid>http://blog.vckbase.com/smileonce/archive/2005/07/26/10070.html</guid><wfw:comment>http://blog.vckbase.com/smileonce/comments/10070.html</wfw:comment><comments>http://blog.vckbase.com/smileonce/archive/2005/07/26/10070.html#Feedback</comments><slash:comments>23</slash:comments><wfw:commentRss>http://blog.vckbase.com/smileonce/comments/commentRss/10070.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/smileonce/services/trackbacks/10070.html</trackback:ping><description>今天有人问我： #include能不能include一个（多个.c文件）？&lt;BR&gt;偶的回答是：从理论上讲可以，但是不推荐。&lt;BR&gt;&lt;BR&gt;为什么经常见到include .h文件而不是include .c文件？或者说include是不是就是为包含.h文件设定的语法？这个问题的答案偶不知道，没有见有文档记载、说明这个问题。不过从语法角度讲，include的意思就是从当前位置包含另外一个文件，就象宏替换一样把当前行用另外一个文件的整个内容替换掉。&lt;BR&gt;&lt;BR&gt;从这点讲，include .c文件是可行的，c编译器完全能够正常处理。但是为什么不常见include .c文件？我想从两个方面可以得到一点解释。一就是，从设计角度上讲，源代码区分为.h和.c文件，是为了接口与实现的分离，实际上两者没什么本质的差别。.h文件提供接口，.c文件提供具体的实现，两者可以一一对应，也可以不一一对应，没有强制要求。一个.c文件做为一个模块的实现，有可能要跟其他的模块打交道，这个时候就需要include其他模块的接口(其他模块的.h文件)；而包含其他模块的实现(.c文件)是没有意义的、危险的。&lt;STRIKE&gt;二就是从编译角度上来讲，make对同名的.h和.c之间提供隐讳规则的支持，就是说在makefile中不必显式指定一个.c文件依赖于同名的.h文件，就能达到显示指定这一依赖规则的作用。&lt;BR&gt;&lt;/STRIKE&gt;&lt;BR&gt;&lt;STRIKE&gt;这个规则的副作用就是，如果.c文件中包含了另外的.c文件，除非在Makefile中显示指定这种依赖规则，否则make不会自动添加这种依赖关系。这样，很多时候被包含的.c文件改变了，原本需要重新编译的模块得不到重新编译(除非你手动删除对应的.obj或者执行rebuild)，这样的话对工程管理和排错都造成了很大的障碍。&lt;/STRIKE&gt;&lt;BR&gt;&lt;BR&gt;所以，我们不应该在项目中include .c文件，这样使用者出于直觉很难想到这里会有问题，增加了排错的难度。前几天偶移植一个国际知名大公司的代码就遇到了这个问题，耗费了半天的时间查看了全部的源码和makefile才发现了这个不常见编译现象。当然，那个公司的代码之所以这么做，是他认为这些代码已经很成熟了，不需要修改和反复重新编译。但它的做法确实对我的调试造成了很大的障碍。&lt;BR&gt;&lt;BR&gt;－－－－－&lt;BR&gt;谢谢[满头大汗]的提醒，偶又做了改动：删除线都是写的不对的内容。补充的是：即便是include了.c文件，如果修改Makefile，也能完成其依赖关系。这个帖子放的久了，就不删掉了。&lt;BR&gt;&lt;BR&gt;－－－－－ GNU Make Document 中的相关章节 －－－－－&lt;BR&gt;
&lt;P style="BACKGROUND: #e6e6e6"&gt;4.12 自动生成依赖&lt;BR&gt;在为一个程序编写的makefile文件中，常常需要写许多仅仅是说明一些OBJ文件依靠头文件的规则。例如，如果&amp;#8216;main.c&amp;#8217;通过一条#include语句使用&amp;#8216;defs.h&amp;#8217;，您需要写入下的规则：&lt;BR&gt;main.o: defs.h&lt;BR&gt;您需要这条规则让make知道如果&amp;#8216;defs.h&amp;#8217;一旦改变必须重新构造&amp;#8216;main.o&amp;#8217;。由此您可以明白对于一个较大的程序您需要在makefile文件中写很多这样的规则。而且一旦添加或去掉一条#include语句您必须十分小心地更改makefile文件。&lt;BR&gt;为避免这种烦恼，现代C编译器根据原程序中的#include语句可以为您编写这些规则。如果需要使用这种功能，通常可在编译源程序时加入&amp;#8216;-M&amp;#8217;开关，例如，下面的命令：&lt;BR&gt;cc -M main.c&lt;BR&gt;产生如下输出：&lt;BR&gt;main.o : main.c defs.h&lt;BR&gt;这样您就不必再亲自写这些规则，编译器可以为您完成这些工作。&lt;BR&gt;注意，由于在makefile文件中提及构造&amp;#8216;main.o&amp;#8217;，因此&amp;#8216;main.o&amp;#8217;将永远不会被隐含规则认为是中间文件而进行搜寻，这同时意味着make不会在使用它之后自动删除它；参阅隐含规则链。&lt;BR&gt;对于旧版的make程序，通过一个请求命令，如&amp;#8216;make depend&amp;#8217;，利用编译器的特点生成依赖是传统的习惯。这些命令将产生一个&amp;#8216;depend&amp;#8217;文件，该文件包含所有自动生成的依赖；然后makefile文件可以使用include命令将它们读入（参阅包含其它makefile文件）。&lt;BR&gt;在GNU make中，重新构造makefile文件的特点使这个惯例成为了过时的东西――您永远不必具体告诉make重新生成依赖，因为GNU make总是重新构造任何过时的makefile文件。参阅Makefile文件的重新生成的过程。&lt;BR&gt;我们推荐使用自动生成依赖的习惯是把makefile文件和源程序文件一一对应起来。如，对每一个源程序文件&amp;#8216;name.c&amp;#8217;有一名为&amp;#8216;name.d&amp;#8217;的makefile文件和它对应，该makefile文件中列出了名为&amp;#8216;name.o&amp;#8217;的OBJ文件所依赖的文件。这种方式的优点是仅在源程序文件改变的情况下才有必要重新扫描生成新的依赖。&lt;BR&gt;这里有一个根据C语言源程序&amp;#8216;name.c&amp;#8217;生成名为&amp;#8216;name.d&amp;#8217;依赖文件的格式规则：&lt;BR&gt;%.d: %.c&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set -e; $(CC) -M $(CPPFLAGS) $&amp;lt; \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' &amp;gt; $@; \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ -s $@ ] || rm -f $@&lt;BR&gt;关于定义格式规则的信息参阅定义与重新定义格式规则。&amp;#8216;-e&amp;#8217;开关是告诉shell如果$(CC)命令运行失败（非零状态退出）立即退出。正常情况下，shell退出时带有最后一个命令在管道中的状态（sed）,因此make不能注意到编译器产生的非零状态。&lt;BR&gt;对于GNU C编译器您可以使用&amp;#8216;-MM&amp;#8217;开关代替&amp;#8216;-M&amp;#8217;，这是省略了有关系统头文件的依赖。详细内容参阅《GNU CC使用手册》中控制预处理选项。&lt;BR&gt;命令Sed的作用是翻译（例如）：&lt;BR&gt;main.o : main.c defs.h&lt;BR&gt;到：&lt;BR&gt;main.o main.d : main.c defs.h&lt;BR&gt;这使每一个&amp;#8216;.d&amp;#8217;文件和与之对应的&amp;#8216;.o&amp;#8217;文件依靠相同的源程序文件和头文件，据此，Make可以知道如果任一个源程序文件和头文件发生变化，则必须重新构造依赖文件。&lt;BR&gt;一旦您定义了重新构造&amp;#8216;.d&amp;#8217;文件的规则，您可以使用使用include命令直接将它们读入，（参阅包含其它makefile文件），例如：&lt;BR&gt;sources = foo.c bar.c&lt;BR&gt;include $(sources:.c=.d)&lt;BR&gt;（这个例子中使用一个代替变量参照从源程序文件列表&amp;#8216;foo.c bar.c'翻译到依赖文件列表&amp;#8216;foo.d bar.d'。详细内容参阅替换引用。）所以，&amp;#8216;.d&amp;#8217;的makefile文件和其它makefile文件一样，即使没用您的任何进一步的指令，make同样会在必要的时候重新构建它们。参阅Makefile文件的重新生成过程。&lt;BR&gt;&lt;/P&gt;&lt;FONT color=#800080&gt;-------------&lt;BR&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT color=#a52a2a&gt;乾坤一笑 写于2005年7月26日&amp;nbsp; 转载请标明出处和原文链接&lt;/STRONG&gt;&lt;/FONT&gt; &lt;img src ="http://blog.vckbase.com/smileonce/aggbug/10070.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>乾坤一笑</dc:creator><title>小议char *和C语言的字符串</title><link>http://blog.vckbase.com/smileonce/archive/2005/06/26/8330.html</link><pubDate>Sat, 25 Jun 2005 18:20:00 GMT</pubDate><guid>http://blog.vckbase.com/smileonce/archive/2005/06/26/8330.html</guid><wfw:comment>http://blog.vckbase.com/smileonce/comments/8330.html</wfw:comment><comments>http://blog.vckbase.com/smileonce/archive/2005/06/26/8330.html#Feedback</comments><slash:comments>18</slash:comments><wfw:commentRss>http://blog.vckbase.com/smileonce/comments/commentRss/8330.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/smileonce/services/trackbacks/8330.html</trackback:ping><description>&lt;P&gt;前几天和清风雨交谈strncpy()函数的时候，他认为&amp;#8220;如果一个函数有一个char * str的参数，那么str一定是一个字符串&amp;#8221;，而我对此不以为然。难得到了周末，抽得出功夫,谈谈我对char *含义的认识,与大家共同讨论一下。&lt;/P&gt;
&lt;P&gt;C语言是开发操作系统的首选语言，在很多方面都能从C代码中看到机器的固有性质。比如,PASCAL语言的数组索引是从1开始计数，而C语言就是从0开始计数。从0开始计数不太符合一般人的正常思维模式，但是为什么C语言要采用这种设计方式呢？因为C语言最初主要是为操作系统开发人员和编译器设计人员设计的&amp;#8212;&amp;#8212;对于经常需要考察内存地址的开发人员，偏移量的概念在他们脑子里面根深蒂固。要把100个int型的整数放在从地址0x0000开始的一段内存中，如果系统是按Byte编址的，那么第100个元素(其数组索引为99)的要放入的地址必然是：0x0000 + sizeof(int) * 99， 而不是乘以100，所以索引以0开始是很有好处的。(C语言的底层特性请参考P.V.D.L的《Expert C Programming&amp;#8212;&amp;#8212;Deep C Secrets》，中文版《C专家编程》)&lt;/P&gt;
&lt;P&gt;同样而言，C语言对所谓字符串的处理也和其他语言不同。(参见拙著《&lt;A href="http://blog.vckbase.com/smileonce/archive/2005/06/18/6777.html"&gt;我用错了strcat() &lt;/A&gt;》文后的评论) 它同样体现了便于系统设计的特点。例如unix系统总是把设备都映射为文件，对I/O流、光驱、硬盘、modem的访问最终都转换为了对文件的处理。而文件，也可以看作是一个长长的字符数组(文件以EOF结尾)。&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;C语言没有专门定义字符串数据类型(如其他语言中的string)，它用以'\0'结尾的字符数组来表示一个逻辑意义上的字符串。&lt;/FONT&gt;&lt;/STRONG&gt;C语言用一些对于字符数组的处理函数(特别是对以'\0'结尾的字符数组的处理函数)来处理所谓的以'\0'结尾的字符串，并把他们放在string.*、stdio.*等一些标准库文件中。string这个字眼也就对人造成了某些误解，好像是C语言中定义了字符串这种类型一样。&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;其实C语言只定义了char、int、float、void、poiner这几种基本类型，这正是C语言简洁之处。至于所谓的字符串，只是对字符数组的一种特殊应用而已。&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;由于没有了&amp;#8220;字符串类型&amp;#8221;，&amp;#8220;传char *参数就是传一个字符串进来&amp;#8221;之说自然也不攻自破。那么char *真正的含义是什么？我们不妨用大家最熟悉的int来对比一下。&lt;BR&gt;&lt;/P&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;FONT color=#a000a0&gt;#include &amp;lt;stdio.h&amp;gt;
&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
int&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; main&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/B&gt; argc&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; char&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; *&lt;/FONT&gt;&lt;/B&gt;argv&lt;B&gt;&lt;FONT color=#646464&gt;[])
{&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;    
    int&lt;/FONT&gt;&lt;/B&gt; b&lt;B&gt;&lt;FONT color=#646464&gt;[&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt;3&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;] = {&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 17&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 18&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 19&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt; };&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    int&lt;/FONT&gt;&lt;/B&gt; a&lt;B&gt;&lt;FONT color=#646464&gt; =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 5&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;
    int&lt;/FONT&gt;&lt;/B&gt; d&lt;B&gt;&lt;FONT color=#646464&gt; =&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 2103157716&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; 

    int&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt; *&lt;/FONT&gt;&lt;/B&gt; i&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt; // pay attention to this variable
&lt;/FONT&gt;&lt;/I&gt;
    i&lt;B&gt;&lt;FONT color=#646464&gt; =&lt;/FONT&gt;&lt;/B&gt; b&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;
    printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt;"%d \n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;, *&lt;/FONT&gt;&lt;/B&gt;i&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;  // i points to a array, *i gets the first number of the array, 
                          // *i does not get the all elements of the array.
&lt;/FONT&gt;&lt;/I&gt;    
    i&lt;B&gt;&lt;FONT color=#646464&gt; =&lt;/FONT&gt;&lt;/B&gt; b&lt;B&gt;&lt;FONT color=#646464&gt; +&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 1&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;            // okey, i can get whichever element of the array.
&lt;/FONT&gt;&lt;/I&gt;    printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt;"%d \n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;, *&lt;/FONT&gt;&lt;/B&gt;i&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;

    printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt;"Int size: %d \n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt; sizeof&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;));&lt;/FONT&gt;&lt;/B&gt;
    printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt;"Address0: %#x \n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt; i&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt; // if i++, the value of i add by sizeof(int)
&lt;/FONT&gt;&lt;/I&gt;    i&lt;B&gt;&lt;FONT color=#646464&gt;++;&lt;/FONT&gt;&lt;/B&gt;
    printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt;"Address1: %#x \n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt; i&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;
   

    i&lt;B&gt;&lt;FONT color=#646464&gt; = &amp;amp;&lt;/FONT&gt;&lt;/B&gt;a&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;               // i also can point to a int variable. as i is a pointer, we shoule 
&lt;/FONT&gt;&lt;/I&gt;    printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt;"%d \n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;, *&lt;/FONT&gt;&lt;/B&gt;i&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;  // use &amp;amp; to get the address of a.
&lt;/FONT&gt;&lt;/I&gt;

    printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt;"%#x \n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;,&lt;/FONT&gt;&lt;/B&gt; d&lt;B&gt;&lt;FONT color=#646464&gt;);&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;  // I use a big number to prove that int * is only a pointer,
&lt;/FONT&gt;&lt;/I&gt;    i&lt;B&gt;&lt;FONT color=#646464&gt; = &amp;amp;&lt;/FONT&gt;&lt;/B&gt;d&lt;B&gt;&lt;FONT color=#646464&gt;;&lt;/FONT&gt;&lt;/B&gt;&lt;I&gt;&lt;FONT color=#008000&gt;               // which is not tightness to int type.
&lt;/FONT&gt;&lt;/I&gt;    printf&lt;B&gt;&lt;FONT color=#646464&gt;(&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#ff00ff&gt;"%#x \n"&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;, *((&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;unsigned char&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#646464&gt;*)&lt;/FONT&gt;&lt;/B&gt;i&lt;B&gt;&lt;FONT color=#646464&gt;));&lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;FONT color=#0000ff&gt;    
    
 return&lt;/FONT&gt;&lt;/B&gt;&lt;FONT color=#800080&gt; 0&lt;/FONT&gt;&lt;B&gt;&lt;FONT color=#646464&gt;;
}&lt;/FONT&gt;&lt;/B&gt;
&lt;/PRE&gt;
&lt;P&gt;代码中的int * i就是我们关注的焦点。它是一个指向int指针。也就是说：i指向一个内存地址，从这个地址开始存储了一个数据。int * i中的int标明应该使用int类型（长度为sizeof(int)个字节）来从这个地址取数据，也就是说要一次取sizeof(int)个byte的数据来拼成最后的结果。最后一个例子也证明了这一点：如果我们强制用unsigned char的大小的数据类型来对这个地址操作，就只能取出数据的一部分。反过来说，如果用较大数据类型来取实际存储较小数据类型的数据，就有可能越界操作内存，取回一些杂乱的内容或导致系统崩溃。int b[]这个数组，标明有一组数，放在以&amp;amp;b开始地址的内存空间内，每个元素占用了sizeof(int)个byte的内存单元；如果有类似于i=&amp;amp;b;i++;的操作，i的值就每次递增sizeof(int)而不是1，这样确保了i每次都能恰好取回一个正确的int。&lt;/P&gt;
&lt;P&gt;同理，char * c也是如此。如果我们定义了一个char *的变量c，那么c也只不过是一个指向内存中某个地址的指针而已。之所以标明它是char *的类型，就是说要以sizeof(char)为单位去内存中取数。所以，我们应该称呼char * c为指向char类型的指针&amp;#8212;&amp;#8212;而不是说c就是字符串。&lt;U&gt;为什么传一个char *指针给printf(),strlen()之类的函数，它就能把它当作一个字符串来处理呢？没错，我们不是定义了'\0'来表示一个"字符串"的终结么？我们只需从起始地址不断累加，遍历字符数组的每一个元素，直到找到一个'\0'为止，就算是处理一个字符串了&lt;/U&gt;&amp;#8212;&amp;#8212;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;从起始地址到'\0'为止的字符数组元素构成一个&amp;#8220;字符串&amp;#8221;，这就是C语言设计字符串的原理。&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;所以，当一个函数要求传入一个char *的参数，并不一定这个参数就一定是字符串(以'\0'结尾的字符数组)，char *只是一个字符指针而已,它仅仅提供了一个内存地址和每次遍历元素的偏移量而已。究竟函数对传入的参数有什么要求，还要视函数的具体实现而定。(我想ANSI C应该对参数有所要求和规定，可惜偶没有ANSI C文件，无法参考。&amp;nbsp;)&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;C语言一般约定是用char * str来表示以'\0'结尾的字符数组，但是由于某些实现上的效率的考虑，往往没有严格遵守这个约定。&lt;/FONT&gt;C语言的设计理念中没有强调使用者一定要使用遵守这个约定，不遵守这个约定也不违背C语言的基本语法规则。这或许可以看作是C语言和创造和使用它的黑客群体崇尚自由的一种特色、一种精神文化吧。&lt;/STRONG&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;小练习：&lt;BR&gt;1)参照上面int *的例子来编写一个类似代码验证一下char *是否也有类似特性。&lt;BR&gt;2)C语言这么设计字符串会在那些方面的处理上有为难之处。&lt;BR&gt;3)考察C语言标准库函数中，有那些函数传入char*的参数是一定要求以'\0'结尾的，那些函数对char *参数不做这个检查。&lt;BR&gt;&lt;BR&gt;&lt;FONT color=#800080&gt;-------------&lt;BR&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT color=#a52a2a&gt;乾坤一笑 写于2005年6月26日&amp;nbsp; 转载请标明出处和原文链接&lt;/STRONG&gt;&lt;/FONT&gt; &lt;/P&gt;&lt;img src ="http://blog.vckbase.com/smileonce/aggbug/8330.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>乾坤一笑</dc:creator><title>用Makefile打补丁——自动化构建</title><link>http://blog.vckbase.com/smileonce/archive/2005/06/18/6809.html</link><pubDate>Sat, 18 Jun 2005 08:07:00 GMT</pubDate><guid>http://blog.vckbase.com/smileonce/archive/2005/06/18/6809.html</guid><wfw:comment>http://blog.vckbase.com/smileonce/comments/6809.html</wfw:comment><comments>http://blog.vckbase.com/smileonce/archive/2005/06/18/6809.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://blog.vckbase.com/smileonce/comments/commentRss/6809.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/smileonce/services/trackbacks/6809.html</trackback:ping><description>&lt;P&gt;make和Makefile一向被用来编译、连接代码，这已经成为了思维的定势。如果能够突破这个定势，就会发现make原来还有很多妙用。&lt;BR&gt;&lt;BR&gt;Makefile其根本原理就是利用文件时间比较来触发一个动作。比如：&lt;/P&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;file_a&lt;B&gt;&lt;FONT color=#646464&gt;.&lt;/FONT&gt;&lt;/B&gt;obj&lt;B&gt;&lt;FONT color=#646464&gt; :&lt;/FONT&gt;&lt;/B&gt; file_a&lt;B&gt;&lt;FONT color=#646464&gt;.&lt;/FONT&gt;&lt;/B&gt;c
    gcc file_a&lt;B&gt;&lt;FONT color=#646464&gt;.&lt;/FONT&gt;&lt;/B&gt;c&lt;B&gt;&lt;FONT color=#646464&gt; -&lt;/FONT&gt;&lt;/B&gt; o file_a&lt;B&gt;&lt;FONT color=#646464&gt;.&lt;/FONT&gt;&lt;/B&gt;obj&lt;/PRE&gt;
&lt;P&gt;这就是一个最简单的应用。make读到这段代码时，会去比较file_a.obj和file_a.c的日期，如果file_a.c比file_a.obj还要新（就是时间晚，如2005-05-09 20:03:43 就比2003-12-07 04:03:12要新），这时候就会触发下面一行的动作。用gcc去编译file_a.c，从而重新生成file_a.obj，这就是项目编译中所做的事，通过比较时间，只编译需要编译的部分，这样比较高效、节约时间。&lt;BR&gt;&lt;BR&gt;我们也可以利用make的原理来打patch，效果很好。比如我的项目中平台会自动生成一个ori_font.c的文件，上面是平台提供的字库。而我不需要这个字库，我要替换掉其中这个文件中字库相关的一部分内容。于是我写了一个小程序 replace_fonts.exe，通过执行replace_fonts ori_font.c pt_font.c就可以把ori_font.c给替换掉。但是汉字是很多的，这个文件也非常大。所以我不想每次编译之前都替换这个文件，我只需要在平台重新生成代码后（平台更新了ori_font.c），我才使用replace_fonts，然后再编译工程即可。于是make可以帮我这个忙。&lt;BR&gt;&lt;BR&gt;首先我写一个Makefile:&lt;/P&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;&lt;FONT color=#a000a0&gt;#rpfonts.mak
#for replacing fonts res
&lt;/FONT&gt;
fonts&lt;B&gt;&lt;FONT color=#646464&gt;.&lt;/FONT&gt;&lt;/B&gt;obj&lt;B&gt;&lt;FONT color=#646464&gt; :&lt;/FONT&gt;&lt;/B&gt; fonts&lt;B&gt;&lt;FONT color=#646464&gt;.&lt;/FONT&gt;&lt;/B&gt;c
   replace_fonts ori_font&lt;B&gt;&lt;FONT color=#646464&gt;.&lt;/FONT&gt;&lt;/B&gt;c pt_font&lt;B&gt;&lt;FONT color=#646464&gt;.&lt;/FONT&gt;&lt;/B&gt;c&lt;/PRE&gt;
&lt;P&gt;然后把它加入我build工程的批处理文件中：&lt;/P&gt;&lt;PRE style="BACKGROUND: #e6e6e6"&gt;rem build_prj&lt;B&gt;&lt;FONT color=#646464&gt;.&lt;/FONT&gt;&lt;/B&gt;bat

gnumake&lt;B&gt;&lt;FONT color=#646464&gt; -&lt;/FONT&gt;&lt;/B&gt;f rpfonts&lt;B&gt;&lt;FONT color=#646464&gt;.&lt;/FONT&gt;&lt;/B&gt;mak
gnumake&lt;B&gt;&lt;FONT color=#646464&gt; -&lt;/FONT&gt;&lt;/B&gt;f prj&lt;B&gt;&lt;FONT color=#646464&gt;.&lt;/FONT&gt;&lt;/B&gt;mak&lt;/PRE&gt;
&lt;P&gt;Okey，我只需像平常一样执行build_prj.bat就好了，它会在需要替换字体的时候自动给偶替换的。嘻嘻，是不是很方便呢？:p&lt;BR&gt;&lt;BR&gt;&lt;FONT color=#800080&gt;-------------&lt;BR&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT color=#a52a2a&gt;乾坤一笑 写于2005年6月18 日&amp;nbsp; 转载请标明出处和原文链接&lt;/STRONG&gt;&lt;/FONT&gt; &lt;/P&gt;&lt;img src ="http://blog.vckbase.com/smileonce/aggbug/6809.html" width = "1" height = "1" /&gt;</description></item></channel></rss>