﻿<?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>BlogJava-jasmine214--love-随笔分类-C语言学习</title><link>http://www.blogjava.net/jasmine214--love/category/47200.html</link><description>只有当你的内心总是充满快乐、美好的愿望和宁静时，你才能拥有强壮的体魄和明朗、快乐或者宁静的面容。</description><language>zh-cn</language><lastBuildDate>Mon, 16 Jul 2012 11:10:41 GMT</lastBuildDate><pubDate>Mon, 16 Jul 2012 11:10:41 GMT</pubDate><ttl>60</ttl><item><title>c全局变量、static、函数指针</title><link>http://www.blogjava.net/jasmine214--love/archive/2012/07/16/383237.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Mon, 16 Jul 2012 08:03:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2012/07/16/383237.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/383237.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2012/07/16/383237.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/383237.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/383237.html</trackback:ping><description><![CDATA[<div><h2>c全局变量、static、函数指针</h2>   <div id="content" text-content=""  clearfix"=""> <p>1、static全局变量与普通的全局变量有什么区别？static局部变量和普通局部变量有什么区别？static函数与普通函数有什么区别？<br />&nbsp;&nbsp;&nbsp;   答：全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式，  静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序，  当一个源程序由多个源文件组成时，非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域， 即只在定义该变量的源文件内有效，  在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内，只能为该源文件内的函数公用，  因此可以避免在其它源文件中引起错误。<br />&nbsp;&nbsp;&nbsp;  从以上分析可以看出， 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域， 限制了它的使用范围。<br />&nbsp;&nbsp;&nbsp;  static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static)，内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数，应该在一个头文件中说明，要使用这些函数的源文件要包含这个头文件<br />&nbsp;&nbsp;&nbsp;  static全局变量与普通的全局变量有什么区别：static全局变量只初使化一次，防止在其他文件单元中被引用;<br />&nbsp;&nbsp;&nbsp;  static局部变量和普通局部变量有什么区别：static局部变量只被初始化一次，下一次依据上一次结果值；<br />&nbsp;&nbsp;&nbsp;  static函数与普通函数有什么区别：static函数在内存中只有一份，普通函数在每个被调用中维持一份拷贝<br />2、如何引用一个已经定义过的全局变量？<br />&nbsp;&nbsp;&nbsp;&nbsp;  答：extern<br />&nbsp;&nbsp;&nbsp;&nbsp;    可以用引用头文件的方式，也可以用extern关键字，如果用引用头文件方式来引用某个在头文件中声明的全局变理，假定你将那个变写错了，那么在编译期间  会报错，如果你用extern方式引用时，假定你犯了同样的错误，那么在编译期间不会报错，而在连接期间报错。</p><p>3、全局变量可不可以定义在可被多个.C文件包含的头文件中？为什么？<br />&nbsp;&nbsp;&nbsp;  答：可以，在不同的C文件中以static形式来声明同名全局变量。<br />&nbsp;&nbsp;&nbsp;  可以在不同的C文件中声明同名的全局变量，前提是其中只能有一个C文件中对此变量赋初值，此时连接不会出错。</p><p>4、程序的局部变量存在于（堆栈）中，全局变量存在于（静态区 ）中，动态申请数据存在于（ 堆）中。<br />5、设有以下说明和定义：<br />typedef union {long i; int k[5]; char c;} DATE;<br />struct data { int cat; DATE cow; double dog;} too;<br />DATE max;<br />则语句 printf(&#8221;%d&#8221;,sizeof(struct date)+sizeof(max));的执行结果是：___52____<br />&nbsp;&nbsp;&nbsp;  答：DATE是一个union, 变量公用空间. 里面最大的变量类型是int[5], 占用20个字节. 所以它的大小是20<br />data是一个struct, 每个变量分开占用空间. 依次为int4 + DATE20 + double8 = 32.<br />所以结果是 20 + 32 = 52.<br />当然&#8230;在某些16位编辑器下, int可能是2字节,那么结果是 int2 + DATE10 + double8 = 20<br />6. 函数指针<br />&nbsp;&nbsp;&nbsp;&nbsp;  定义： void (*fptr)();<br />&nbsp;&nbsp;&nbsp;&nbsp;  或者： typedef void (*FP)(); fp fptr;<br />&nbsp;&nbsp;&nbsp;&nbsp;  把函数的地址赋值给函数指针，可以采用下面两种形式：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  fptr=&amp;Function;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  fptr=Function;<br />&nbsp;&nbsp;&nbsp;&nbsp;  取地址运算符&amp;不是必需的，因为单单一个函数标识符就标号表示了它的地址，如果是函数调用，还必须包含一个圆括号括起来的参数表。<br />&nbsp;&nbsp;&nbsp;&nbsp;  可以采用如下两种方式来通过指针调用函数：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  x=(*fptr)();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  x=fptr();</p> </div></div>转：<div>http://hi.baidu.com/xmxqiyan/item/139d9e3c312833bf134b1419</div><img src ="http://www.blogjava.net/jasmine214--love/aggbug/383237.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2012-07-16 16:03 <a href="http://www.blogjava.net/jasmine214--love/archive/2012/07/16/383237.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C语言-宏条件编译详解</title><link>http://www.blogjava.net/jasmine214--love/archive/2012/07/16/383235.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Mon, 16 Jul 2012 07:46:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2012/07/16/383235.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/383235.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2012/07/16/383235.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/383235.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/383235.html</trackback:ping><description><![CDATA[<div><a>C语言宏条件编译详解</a></div><div>处理过程扫描源代码，对其进行初步的转换，产生新的源代码提供给编译器。可见预处理过程先于编译器对源代码进行处理。<br />在C  语言中，并没有任何内在的机制来完成如下一些功能：在编译时包含其他源文件、定义宏、根据条件决定编译时是否包含某些代码。要完成这些工作，就需要使用预 处理程序。尽管在目前绝大多数编译器都包含了预处理程序，但通常认为它们是独立于编译器的。预处理过程读入源代码，检查包含预处理指令的语句和宏定义，并 对源代码进行响应的转换。预处理过程还会删除程序中的注释和多余的空白字符。<br />预处理指令是以#号开头的代码行。#号必须是该行除了任何空白字符外的第一个字符。#后是指令关键字，在关键字和#号之间允许存在任意个数的空白字符。整行语句构成了一条预处理指令，该指令将在编译器进行编译之前对源代码做某些转换。下面是部分预处理指令：  <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 指令&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 用途<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 空指令，无任何效果<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> ＃i nclude&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 包含一个源代码文件<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 定义宏<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #undef&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 取消已定义的宏<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #if&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 如果给定条件为真，则编译下面代码<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #ifdef&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 如果宏已经定义，则编译下面代码<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #ifndef&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 如果宏没有定义，则编译下面代码<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #elif&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 如果前面的#if给定条件不为真，当前条件为真，则编译下面代码<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #endif&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 结束一个#if&#8230;&#8230;#else条件编译块<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #error&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 停止编译并显示错误信息</p> <p>一、文件包含<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> ＃i nclude预处理指令的作用是在指令处展开被包含的文件。包含可以是多重的，也就是说一个被包含的文件中还可以包含其他文件。标准C编译器至少支持八重嵌套包含。<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 预处理过程不检查在转换单元中是否已经包含了某个文件并阻止对它的多次包含。这样就可以在多次包含同一个头文件时，通过给定编译时的条件来达到不同的效果。例如：</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define AAA<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> ＃i nclude "t.c"<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #undef AAA<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> ＃i nclude "t.c"</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 为了避免那些只能包含一次的头文件被多次包含，可以在头文件中用编译时条件来进行控制。例如：<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr><br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #ifndef MY_H<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define MY_H<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &#8230;&#8230;<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #endif</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 在程序中包含头文件有两种格式：<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> ＃i nclude &lt;my.h&gt;<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> ＃i nclude "my.h"<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>   第一种方法是用尖括号把头文件括起来。这种格式告诉预处理程序在编译器自带的或外部库的头文件中搜索被包含的头文件。第二种方法是用双引号把头文件括起 来。这种格式告诉预处理程序在当前被编译的应用程序的源代码文件中搜索被包含的头文件，如果找不到，再搜索编译器自带的头文件。<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 采用两种不同包含格式的理由在于，编译器是安装在公共子目录下的，而被编译的应用程序是在它们自己的私有子目录下的。一个应用程序既包含编译器提供的公共头文件，也包含自定义的私有头文件。采用两种不同的包含格式使得编译器能够在很多头文件中区别出一组公共的头文件。</p> <p>二、宏<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>  宏定义了一个代表特定内容的标识符。预处理过程会把源代码中出现的宏标识符替换成宏定义时的值。宏最常见的用法是定义代表某个值的全局符号。宏的第二种用 法是定义带参数的宏，这样的宏可以象函数一样被调用，但它是在调用语句处展开宏，并用调用时的实际参数来代替定义中的形式参数。<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 1.#define指令<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define预处理指令是用来定义宏的。该指令最简单的格式是：首先神明一个标识符，然后给出这个标识符代表的代码。在后面的源代码中，就用这些代码来替代该标识符。这种宏把程序中要用到的一些全局值提取出来，赋给一些记忆标识符。<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define MAX_NUM 10<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> int array[MAX_NUM];<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> for(i=0;i&lt;MAX_NUM;i++)&nbsp;<wbr><br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr><br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>   在这个例子中，对于阅读该程序的人来说，符号MAX_NUM就有特定的含义，它代表的值给出了数组所能容纳的最大元素数目。程序中可以多次使用这个值。作 为一种约定，习惯上总是全部用大写字母来定义宏，这样易于把程序红的宏标识符和一般变量标识符区别开来。如果想要改变数组的大小，只需要更改宏定义并重新 编译程序即可。<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 宏表示的值可以是一个常量表达式，其中允许包括前面已经定义的宏标识符。例如：<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define ONE 1<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define TWO 2<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define THREE (ONE+TWO)<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 注意上面的宏定义使用了括号。尽管它们并不是必须的。但出于谨慎考虑，还是应该加上括号的。例如：<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> six=THREE*TWO;<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 预处理过程把上面的一行代码转换成：<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> six=(ONE+TWO)*TWO;<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 如果没有那个括号，就转换成six=ONE+TWO*TWO;了。<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 宏还可以代表一个字符串常量，例如：<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define VERSION "Version 1.0 Copyright(c) 2003"<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 2.带参数的#define指令<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 带参数的宏和函数调用看起来有些相似。看一个例子：<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define Cube(x) (x)*(x)*(x)<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 可以时任何数字表达式甚至函数调用来代替参数x。这里再次提醒大家注意括号的使用。宏展开后完全包含在一对括号中，而且参数也包含在括号中，这样就保证了宏和参数的完整性。看一个用法：<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> int num=8+2;<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> volume=Cube(num);<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 展开后为(8+2)*(8+2)*(8+2);<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 如果没有那些括号就变为8+2*8+2*8+2了。<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 下面的用法是不安全的：<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> volume=Cube(num++);<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 如果Cube是一个函数，上面的写法是可以理解的。但是，因为Cube是一个宏，所以会产生副作用。这里的擦书不是简单的表达式，它们将产生意想不到的结果。它们展开后是这样的：<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> volume=(num++)*(num++)*(num++);<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 很显然，结果是10*11*12,而不是10*10*10;<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 那么怎样安全的使用Cube宏呢？必须把可能产生副作用的操作移到宏调用的外面进行：<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> int num=8+2;<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> volume=Cube(num);<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> num++;<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 3.#运算符<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 出现在宏定义中的#运算符把跟在其后的参数转换成一个字符串。有时把这种用法的#称为字符串化运算符。例如：</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define PASTE(n) "adhfkj"#n</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> main()<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> printf("%s/n",PASTE(15));<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 宏定义中的#运算符告诉预处理程序，把源代码中任何传递给该宏的参数转换成一个字符串。所以输出应该是adhfkj15。<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 4.##运算符<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> ##运算符用于把参数连接到一起。预处理程序把出现在##两侧的参数合并成一个符号。看下面的例子：</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define NUM(a,b,c) a##b##c<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define STR(a,b,c) a##b##c</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> main()<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> printf("%d/n",NUM(1,2,3));<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> printf("%s/n",STR("aa","bb","cc"));<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 最后程序的输出为:<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 123<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> aabbcc<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 千万别担心，除非需要或者宏的用法恰好和手头的工作相关，否则很少有程序员会知道##运算符。绝大多数程序员从来没用过它。</p> <p>三、条件编译指令<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 条件编译指令将决定那些代码被编译，而哪些是不被编译的。可以根据表达式的值或者某个特定的宏是否被定义来确定编译条件。<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 1.#if指令<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #if指令检测跟在制造另关键字后的常量表达式。如果表达式为真，则编译后面的代码，知道出现#else、#elif或#endif为止；否则就不编译。<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 2.#endif指令<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #endif用于终止#if预处理指令。</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define DEBUG 0<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> main()<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #if DEBUG<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> printf("Debugging/n");<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #endif<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> printf("Running/n");<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 由于程序定义DEBUG宏代表0，所以#if条件为假，不编译后面的代码直到#endif，所以程序直接输出Running。<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 如果去掉#define语句，效果是一样的。<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 3.#ifdef和#ifndef<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define DEBUG</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> main()<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #ifdef DEBUG<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> printf("yes/n");<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #endif<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #ifndef DEBUG<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> printf("no/n");<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #endif<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #if defined等价于#ifdef; #if !defined等价于#ifndef<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 4.#else指令<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #else指令用于某个#if指令之后，当前面的#if指令的条件不为真时，就编译#else后面的代码。#endif指令将中指上面的条件块。</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define DEBUG</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> main()<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #ifdef DEBUG<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> printf("Debugging/n");<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #else<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> printf("Not debugging/n");<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #endif<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> printf("Running/n");<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 5.#elif指令<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #elif预处理指令综合了#else和#if指令的作用。</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #define TWO</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> main()<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #ifdef ONE<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> printf("1/n");<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #elif defined TWO<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> printf("2/n");<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #else<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> printf("3/n");<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #endif<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 程序很好理解，最后输出结果是2。</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 6.其他一些标准指令<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #error指令将使编译器显示一条错误信息，然后停止编译。<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #line指令可以改变编译器用来指出警告和错误信息的文件号和行号。<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> #pragma指令没有正式的定义。编译器可以自定义其用途。典型的用法是禁止或允许某些烦人的警告信息。</p></div>转：<div>http://blog.chinaunix.net/space.php?uid=20693685&amp;do=blog&amp;id=1892557</div><img src ="http://www.blogjava.net/jasmine214--love/aggbug/383235.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2012-07-16 15:46 <a href="http://www.blogjava.net/jasmine214--love/archive/2012/07/16/383235.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>struct sockaddr_nl 结构体 由来、含义以及使用——获取Linux路由表</title><link>http://www.blogjava.net/jasmine214--love/archive/2012/06/15/380877.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Fri, 15 Jun 2012 09:33:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2012/06/15/380877.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/380877.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2012/06/15/380877.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/380877.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/380877.html</trackback:ping><description><![CDATA[<div>Linux 用户态与内核态的交互<br />&nbsp;&nbsp;在 Linux 2.4 版以后版本的内核中，几乎全部的中断过程与用户态进程的通信都是使用  netlink  套接字实现的，例如iprote2网络管理工具，它与内核的交互就全部使用了netlink，著名的内核包过滤框架Netfilter在与用户空间的通 读，也在最新版本中改变为netlink，无疑，它将是Linux用户态与内核态交流的主要方法之一。它的通信依据是一个对应于进程的标识，一般定为该进 程的 ID。当通信的一端处于中断过程时，该标识为 0。当使用 netlink  套接字进行通信，通信的双方都是用户态进程，则使用方法类似于消息队列。但通信双方有一端是中断过程，使用方法则不同。netlink  套接字的最大特点是对中断过程的支持，它在内核空间接收用户空间数据时不再需要用户自行启动一个内核线程，而是通过另一个软中断调用用户事先指定的接收函 数。<br />《UNIX Network Programming Volume 1 - 3rd Edition》第18章<br />讲到BSD UNIX系统中routing socket的应用，这种套接字是按下面方式生成的：<br />rt_socket = socket(AF_ROUTE, SOCK_RAW, 0);<br />然 后就可以用它跟内核交互，进行网络环境管理的操作，如读取/设置/删除路由表信息，更改网关等等，但书中所列代码只在4.3BSD及以后版本的原始 UNIX系统下可用，Linux虽然实现了AF_ROUTE族套接字，但用法却完全不同。由于网上这方面知识的资料想对匮乏，现对Linux下 routing socket的使用做一介绍。<br />由于我现在在Magic Linux1.0下工作，所以以下的讲解全部基于2.4.10内核。Linux从v2.2开始引入这一机制，因此可以肯定从v2.2到v2.4的内核都是适用的，更新的v2.6我没有试过。<br /><br />Linux下虽然也有AF_ROUTE族套接字，但是这个定义只是个别名，请看<br />/usr/include/linux/socket.h, line 145:<br />#define AF_ROUTE AF_NETLINK /* Alias to emulate 4.4BSD */<br />可 见在Linux内核当中真正实现routing  socket的是AF_NETLINK族套接字。AF_NETLINK族套接字像一个连接用户空间和内核的双工管道，通过它，用户进程可以修改内核运行参 数、读取和设置路由信息、控制特定网卡的up/down状态等等，可以说是一个管理网络资源的绝佳途径。<br /><br />1 生成所需套接字，并绑定一个sockaddr结构<br /><br />先来看如何生成一个AF_NETLINK族套接字：<br />sockfd = socket(AF_NETLINK, socket_type, netlink_faimly);<br />这里socket_type可选SOCK_DGRAM或SOCK_RAW；因为AF_NETLINK族是面向数据报的套接字，所以不能使用SOCK_STREAM。<br />netlink_family指定要和内核中的哪个子系统进行交互，目前支持：<br />NETLINK_ROUTE 与路由信息相关，包括查询、设置和删除路由表中的条目等。待会儿我们将以这类family举个实际的例子；<br />NETLINK_FIREWALL 接收由IPv4防火墙代码发送的包；<br />NETLINK_ARPD 可以在用户空间进行arp缓存的管理；<br />NETLINK_ROUTE6 在用户空间发送和接收路由表信息更新；<br />还有几种虽然没有实现，但已经有了定义，为以后扩展做好了准备。<br /><br />接下来要给该套接字绑定一个sockaddr结构，实际上是一个sockaddr_nl结构：<br />struct sockaddr_nl {<br />sa_family_t nl_family; /*AF_NETLINK*/<br />unsigned short nl_pad; /* 0 */<br />pid_t nl_pid; /* 进程pid */<br />u_32 nl_groups; /* 多播组掩码*/<br />}nl;<br />这个结构一般按照注释填好就可以了，nl_groups我也不知道怎么用，一般填零了，表示没有多播。绑定：<br />bind(sockfd, (struct sockaddr*) &amp;nl, sizeof(nl));<br /><br />2 填充所需数据结构，并通过sendmsg()/send()等函数写到套接字里去<br /><br />到 此为止，与内核通信的准备工作就完成了，下面要做的工作是，选取适当的数据结构进行填充，并作为sendmsg()的参数发送出去，并recv()收到的 消息。这个数据结构就是nlmsghdr，它只是一个信息头，后面可以接任意长的数据，这些数据实际上又是针对某一需求所采用的特定数据结构。先来看 nlmsghdr：<br />struct nlmsghdr {<br />_u32 nlmsg_len; /* Length of msg including header */<br />_u32 nlmsg_type; /* 操作命令 */<br />_u16 nlmsg_flags; /* various flags */<br />_u32 nlmsg_seq; /* Sequence number */<br />_u32 nlmsg_pid; /* 进程PID */<br />};<br />/* 紧跟着是实际要发送的数据，长度可以任意 */<br /><br />nlmsg_type 决定这次要执行的操作，如查询当前路由表信息，所使用的就是RTM_GETROUTE。标准nlmsg_type包括：NLMSG_NOOP,  NLMSG_DONE, NLMSG_ERROR等。根据采用的nlmsg_type不同，还要选取不同的数据结构来填充到nlmsghdr后面：<br />操作 数据结构<br />RTM_NEWLINK ifinfomsg<br />RTM_DELLINK<br />RTM_GETLINK<br />RTM_NEWADDR ifaddrmsg<br />RTM_DELADDR<br />RTM_GETADDR<br />RTM_NEWROUTE rtmsg<br />RTM_DELROUTE<br />RTM_GETROUTE<br />RTM_NEWNEIGH ndmsg/nda_chcheinfo<br />RTM_DELNEIGH<br />RTM_GETNEIGH<br />RTM_NEWRULE rtmsg<br />RTM_DELRULE<br />RTM_GETRULE<br />RTM_NEWQDISC tcmsg<br />RTM_DELQDISC<br />RTM_GETQDISC<br />RTM_NEWTCLASS tcmsg<br />RTM_DELTCLASS<br />RTM_GETTCLASS<br />RTM_NEWTFILTER tcmsg<br />RTM_DELTFILTER<br />RTM_GETTFILTER<br />由于情形众多，我从现在开始将用一个特定的例子来说明问题。我们的目的是从内核读取IPV4路由表信息。从上面表看，nlmsg_type一定使用RTM_xxxROUTE操作，对应的数据结构是rtmsg。既然是读取，那么应该是RTM_GETROUTE了。<br />struct rtmsg {<br />unsigned char rtm_family; /* 路由表地址族 */<br />unsigned char rtm_dst_len; /* 目的长度 */<br />unsigned char rtm_src_len; /* 源长度 */ (2.4.10头文件的注释标反了？)<br />unsigned char rtm_tos; /* TOS */<br /><br />unsigned char rtm_table; /* 路由表选取 */<br />unsigned char rtm_protocol; /* 路由协议 */<br />unsigned char rtm_scope;<br />unsigned char rtm_type;<br /><br />unsigned int rtm_flags;<br />};<br />对于RTM_GETROUTE操作来说，我们只需指定两个成员：rtm_family:AF_INET, rtm_table: RT_TABLE_MAIN。其他成员都初始化为0即可。将这个结构体跟nlmsghdr结合起来，得到我们自己的新结构体：<br />struct {<br />struct nlmsghdr nl;<br />struct rtmsg rt;<br />}req;<br />填充好rt结构之后，还要调整nl结构相应成员的值。Linux定义了多个宏来处理nlmsghdr成员的值，我们这里用到的是NLMSG_LENGTH(size_t len);<br />req.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));<br />这将计算nlmsghdr长度与rtmsg长度的和（其中包括了将rtmsg进行4字节边界对齐的调整），并存储到nlmsghdr的nlmsg_len成员中。接下来要做的就是将这个新结构体req放到sendmsg()函数的msghdr.iov处，并调用函数。<br />sendmsg(sockfd, &amp;msg, 0);<br /><br />3 接收数据，并进行分析<br /><br />接下来的操作是recv()操作，从该套接字读取内核返回的数据，并进行分析处理。<br />recv(sockfd, p, sizeof(buf) - nll, 0);<br />其中p是指向一个缓冲区buf的指针，nll是已接收到的nlmsghdr数据的长度。<br />由于内核返回信息是一个字节流，需要调用者检查消息结尾。这是通过检查返回的nlmsghdr的nlmsg_type是否等于NLMSG_DONE来完成的。返回的数据格式如下：<br />-----------------------------------------------------------<br />| nlmsghdr+route entry | nlmsghdr+route entry | ......... <br />-----------------------------------------------------------<br />| 解出route entry<br />V<br />-----------------------------------------------------------<br />| dst_addr | gateway | Output interface| ...............<br />-----------------------------------------------------------<br />可 以看出，返回消息由多个(nlmsghdr + route entry)组成，当某个nlmsghdr的nlmsg_type ==  NLMSG_DONE时就表示信息输出已经完毕。而每一个route  entry由多个rtattr结构体组成，每个结构体表示该路由项的某个属性，如目的地址，网关等等。根据这个示意图我们就能够轻松解析需要的数据了。</div><br />原文：<div>http://www.douban.com/note/29453304/</div><img src ="http://www.blogjava.net/jasmine214--love/aggbug/380877.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2012-06-15 17:33 <a href="http://www.blogjava.net/jasmine214--love/archive/2012/06/15/380877.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C语言之static静态变量 </title><link>http://www.blogjava.net/jasmine214--love/archive/2012/06/05/380038.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Tue, 05 Jun 2012 08:43:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2012/06/05/380038.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/380038.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2012/06/05/380038.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/380038.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/380038.html</trackback:ping><description><![CDATA[<div><div> 		<br /><a id="cb_post_title_url" href="http://www.cnblogs.com/sideandside/archive/2007/03/29/692559.html"></a> 	</div> 	1. static 变量<br /><br />静态变量的类型 说明符是static。 静态变量当然是属于静态存储方式，但是属于静态存储方式的量不一定就是静态变量。 例如外部变量虽属于静态 存储方式，但不一定是静态变量，必须由 static加以定义后才能成为静态外部变量，或称静态全局变量。<br /><br />2. 静态局部变量<br />静态局部变量属于静态存储方式，它具有以下特点：<br />(1)静态局部变量在函数内定义 它的生存期为整个源程序，但是其作用域仍与自动变量相同，只能在定义该变量的函数内使用该变量。退出该函数后， 尽管该变量还继续存在，但不能使用它。<br /><br />(2)允许对构造类静态局部量赋初值 例如数组，若未赋以初值，则由系统自动赋以0值。<br />(3) 对基本类型的静态局部变量若在说明时未赋以初值，则系统自动赋予0值。而对自动变量不赋初值，则其值是不定的。 根据静态局部变量的特点， 可以  看出它是一种生存期为整个源程序的量。虽然离开定义它的函数后不能使用，但如再次调用定义它的函数时，它又可继续使用， 而且保存了前次被调用后留下的  值。 因此，当多次调用一个函数且要求在调用之间保留某些变量的值时，可考虑采用静态局部变量。虽然用全局变量也可以达到上述目的，但全局变量有时会造成  意外的副作用，因此仍以采用局部静态变量为宜。<br /><br />3.静态全局变量<br />全局变量(外部变量)的说明之前再冠以static 就构  成了静态的全局变量。全局变量本身就是静态存储方式， 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局  变量的作用域是整个源程序， 当一个源程序由多个源文件组成时，非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域，  即只在 定义该变量的源文件内有效，  在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内，只能为该源文件内的函数公用， 因此  可以避免在其它源文件中引起错误。从以上分析可以看出， 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量  后是改变了它的作用域， 限制了它的使用范围。因此static 这个说明符在不同的地方所起的作用是不同的。<br /><br />4. static 函数&#8230;..<br /><br />内部函数和外部函数<br /><br />当一个源程序由多个源文件组成时，Ｃ语言根据函数能否被其它源文件中的函数调用，将函数分为内部函数和外部函数。<br />1 内部函数（又称静态函数）<br />如果在一个源文件中定义的函数，只能被本文件中的函数调用，而不能被同一程序其它文件中的函数调用，这种函数称为内部函数。<br />定义一个内部函数，只需在函数类型前再加一个&#8220;static&#8221;关键字即可，如下所示：<br />static 函数类型 函数名(函数参数表)<br />{&#8230;&#8230;}<br />关键字&#8220;static&#8221;，译成中文就是&#8220;静态的&#8221;，所以内部函数又称静态函数。但此处&#8220;static&#8221;的含义不是指存储方式，而是指对函数的作用域仅局限于本文件。<br />使用内部函数的好处是：不同的人编写不同的函数时，不用担心自己定义的函数，是否会与其它文件中的函数同名，因为同名也没有关系。<br /><br />2 外部函数<br />外部函数的定义：在定义函数时，如果没有加关键字&#8220;static&#8221;，或冠以关键字&#8220;extern&#8221;，表示此函数是外部函数：<br />[extern] 函数类型 函数名(函数参数表)<br />{&#8230;&#8230;}<br />调用外部函数时，需要对其进行说明：<br />[extern] 函数类型 函数名(参数类型表)[，函数名2(参数类型表2)&#8230;&#8230;]；<br /><br />[案例]外部函数应用。<br />（1）文件mainf.c<br />main()<br />{ extern void input(&#8230;),process(&#8230;),output(&#8230;);<br />input(&#8230;); process(&#8230;); output(&#8230;);<br />}<br /><br />（2）文件subf1.c<br />&#8230;&#8230;<br />extern void input(&#8230;&#8230;) /*定义外部函数*/<br />{&#8230;&#8230;}<br />（3）文件subf2.c<br />&#8230;&#8230;<br />extern void process(&#8230;&#8230;) /*定义外部 函数*/<br />{&#8230;&#8230;}<br />（4）文件subf3.c<br />&#8230;&#8230;<br />extern void output(&#8230;&#8230;) /*定义外部函数*/<br />{&#8230;&#8230;}<br /><br />1、概述<br /><br />　　static 声明的变量在C语言中有两方面的特征：<br /><br />　　1)、变量会被放在程序的全局存储区中，这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与堆栈变量和堆变量的区别。　　2)、变量用static告知编译器，自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。<br /><br />　　2、问题：Static的理解<br /><br />　　关于static变量，请选择下面所有说法正确的内容：<br /><br />　　A、若全局变量仅在单个C文件中访问，则可以将这个变量修改为静态全局变量，以降低模块间的耦合度；<br /><br />　　B、若全局变量仅由单个函数访问，则可以将这个变量改为该函数的静态局部变量，以降低模块间的耦合度；<br /><br />　　C、设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时，需要考虑重入问题；<br /><br />　　D、静态全局变量过大，可那会导致堆栈溢出。 <br /><br />　　答案与分析：<br /><br />　　对于A，B：根据本篇概述部分的说明b)，我们知道，A,B都是正确的。<br /><br />　　对于C：根据本篇概述部分的说明a)，我们知道，C是正确的（所谓的函数重入问题，下面会详细阐述）。<br /><br />　　对于D：静态变量放在程序的全局数据区，而不是在堆栈中分配，所以不可能导致堆栈溢出，D是错误的。<br /><br />　　因此，答案是A、B、C。<br /><br />　　3、问题：不可重入函数<br /><br />　　曾经设计过如下一个函数，在代码检视的时候被提醒有bug，因为这个函数是不可重入的，为什么？<br /><br /> <table align="center" bgcolor="#e6e4dd" border="1" width="90%">     <tbody>         <tr>             <td>unsigned int sum_int( unsigned int base )<br />{<br />　unsigned int index;<br />　static unsigned int sum = 0; // 注意，是static类型的。 <br />　for (index = 1; index &lt;= base; index++)<br />　{<br />　　sum += index;<br />　}<br />　return sum;<br />}</td>         </tr>     </tbody> </table> <br />　　答案与分析：<br /><br />　　所谓的函数是可重入的（也可以说是可预测的），即：只要输入数据相同就应产生相同的输出。<br /><br />　 　这个函数之所以是不可预测的，就是因为函数中使用了static变量，因为static变量的特征，这样的函数被称为：带&#8220;内部存储器&#8221;功能的的函数。 因此如果我们需要一个可重入的函数，那么，我们一定要避免函数中使用static变量，这种函数中的static变量，使用原则是，能不用尽量不用。<br /><br />　　将上面的函数修改为可重入的函数很简单，只要将声明sum变量中的static关键字去掉，变量sum即变为一个auto 类型的变量，函数即变为一个可重入的函数。<br /><br />　　当然，有些时候，在函数中是必须要使用static变量的，比如当某函数的返回值为指针类型时，则必须是static的局部变量的地址作为返回值，若为auto类型，则返回为错指针。</div>原文：<div>http://www.cnblogs.com/sideandside/archive/2007/03/29/692559.html</div><img src ="http://www.blogjava.net/jasmine214--love/aggbug/380038.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2012-06-05 16:43 <a href="http://www.blogjava.net/jasmine214--love/archive/2012/06/05/380038.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>netlink socket理解</title><link>http://www.blogjava.net/jasmine214--love/archive/2012/06/01/379752.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Fri, 01 Jun 2012 08:25:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2012/06/01/379752.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/379752.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2012/06/01/379752.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/379752.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/379752.html</trackback:ping><description><![CDATA[<div><div><p>由于开发和维护内核的复杂性，只用最为关键同时对性能要求最高的代码才会放在内核中。其他的诸如GUI,管理和控制代码，通常放在用户空间运行。这种将实现分离在内核和用户空间的思想在Linux中非常常见。现在的问题是内核代码和用户代码如果彼此通信。</p>  <p>答案是内核空间和用户空间存在的各种IPC方法，例如系统调用，ioctl，proc文件系统和netlink socket。这篇文章讨论netlink socket和讨论其作为一种网络特征IPC的优势。</p>  <p>简介</p>  <p>Netlink   socket是用于内核和用户空间之间交换信息的特殊的IPC机制。它提供了一种全复用的通信链路。和TCP/IP使用的地址族AF_INET相 比，Netlink socket使用地址族AF_NETLINK，每个的netlink  socket特征定义协议类型在内核头文件中include/linux/netlink.h</p>  <p>以下是netlink socket当前支持的特征和他们的协议类型的子集：</p>  <ul><li>NETLINK_ROUTE:用户空间路由damon，如BGP，OSPF,RIP和内核包转发模块的通信信道。用户空间路由damon通过此种netlink协议类型更新内核路由表 </li><li>NETLINK_FIREWALL:接收IPv4防火墙代码发送的包 </li><li>NETLINK_NFLOG:用户空间iptable管理工具和内核空间Netfilter模块的通信信道 </li><li>NETLINK_ARPD：用户空间管理arp表 </li></ul>  <p>为 什么以上的特征使用netlink而不是系统调用，ioctl或者proc文件系统来完成通信？为新特性添加系统调用，ioctl和proc文件系统相对 而言是一项比较复杂的工作，我们冒着污染内核和损害系统稳定性的风险。netlink  socket相对简单：只有一个常量，协议类型，需要加入到netlink.h中。然后，内核模块和用户程序可以通过socket类型的API进行通信。</p>  <p>和 其他socket  API一样，Netlink是异步的，它提供了一个socket队列来平滑突发的信息。发送一个netlink消息的系统调用将消息排列到接受者的 netlink队列中然后调用接收者的接收处理函数。接收者，在接收处理函数的上下文中，可以决定是否立即处理该消息还是等待在另一个上下文中处理。不想 netlink，系统调用需要同步处理。因此，如果我们使用了一个系统来传递一条消息到内核，如果需要处理该条信息的时间很长，那么内核调度粒度可以会受 影响。</p>  <p>在内核中实现的系统调用代码在编译时被静态的链接到内核中，因此在一个可以动态加载的模块中包括系统调用代码是不合适的。在netlink socket中，内核中的netlink核心和在一个可加载的模块中没有编译时的相互依赖。</p>  <p>netlink socket支持多播，这也是其与其他交互手段相比较的优势之一。一个进程可以将一条消息广播到一个netlink组地址。任意多的进程可以监听那个组地址。这提供了一种从内核到用户空间进行事件分发接近完美的机制。</p>  <p>从 会话只能由用户空间应用发起的角度来看，系统调用和ioctl是单一的IPC。但是，如果一个内核模块有一个用户空间应用的紧急消息，没有一种直接的方法 来实现这些功能。通常，应用需要阶段性的轮询内核来获取状态变化，尽管密集的轮询会有很大的开销。netlink通过允许内核初始化一个对话来优雅的解决 这个问题。我们称之为netlink的复用特性。</p>  <p>最后，netlink提供了bsd socket风格的API，而这些API是被软件开发社区所熟知。因此，培训费用相较较小。</p>  <p><strong>和BSD路由socket的关系</strong></p>  <p>在BSC TCP/IP的栈实现中，有一种叫做路由套接字的特殊的socket。它有AF_ROUTE地址族，PF_ROUTE协议族和SOCK_RAWsocket类型。在bsd中，路由套接字用于在内核路由表中添加和删除路由。</p>  <p>在Linux中，路由套接字的实现通过netlink套接字的NETLINK_ROUTE协议类型来支持。netlink套接字提供了bsd路由套接字的功能的超集。</p>  <p><strong>Netlink套接字API</strong></p>  <p>标 准的套接字API，socket(),sendmsg(),recvmsg()和close()，可以被用户态程序使用。可以通过查询man手册页来看这 些函数的具体定义。这儿，我们讨论在netlink上下文中为这些API选择参数。对于写过TCP/IP套接字程序的人对这些API都应该非常熟悉。</p>  <p>创建一个套接字，</p>  <p>int socket(int domain，int type， int protocol)</p>  <p>domain指代地址族，AF_NETLINK，套接字类型不是SOCK_RAW就是SOCK_DGRAM，因为netlink是一个面向数据报的服务。</p>  <p>protocol选择该套接字使用那种netlink特征。以下是几种预定义的协议类型：NETLINK_ROUTE,NETLINK_FIREWALL,NETLINK_APRD,NETLINK_ROUTE6_FW。你也可以非常容易的添加自己的netlink协议。</p>  <p>为 每一个协议类型最多可以定义32个多播组。每一个多播组用一个bit mask来表示，1&lt;&lt;i(0&lt;= i&lt;=  31)，这在一组进程和内核进程协同完成一项任务时非常有用。发送多播netlink消息可以减少系统调用的数量，同时减少用来维护多播组成员信息的负 担。</p>  <p>bind()</p>  <p>和TCP/IP套接字一样，netlink bind()API用来将一个本地socket地址和一个打开的socket关联。一个netlink地址结构如下所示：</p>  <div>   <pre>   1:  struct sockaddr_nl</pre>    <pre>   2:  {</pre>    <pre>   3:    sa_family_t    nl_family;  /* AF_NETLINK   */</pre>    <pre>   4:    unsigned short nl_pad;     /* zero         */</pre>    <pre>   5:    __u32          nl_pid;     /* process pid */</pre>    <pre>   6:    __u32          nl_groups;  /* mcast groups mask */</pre>    <pre>   7:  } nladdr;</pre> </div>   <p>当使用bind()调用的时候，nl_pid域可以被赋值为调用进程的pid。nl_pid在这儿被当做该netlink套接字的本地地址。程序负责找一个独一无二的32位整数在填充该域。一种常见的做法是：</p>  <div>   <pre>   1:  NL_PID Formula 1:  nl_pid = getpid();</pre> </div>  <p>公式一使用进程ID号作为nl_pid的值，如果说该进程只需要一个netlink套接字，这是一个自然的选择。当一个进程中的不同线程需要同一个netlink协议多个netlink套接字。公式而可以用来产生nl_pid号：</p>  <div>   <pre>   1:  NL_PID Formula 2: pthread_self() &lt;&lt; 16 | getpid();</pre> </div>   <p>通过这种方法，同一个进程中的不同线程可以有同一种netlink协议类型的netlink套接字。事实上，即使在同一个线程中，在可能使用同一种协议类型的多个套接字。开发者必须要更有创造力来产生一个唯一的nl_pid。</p>  <p>如果应用想接受发送给特定多播组的netlink消息，所有感兴趣的多播组bit应该or在一起，并填充到nl_groups域。否则， nl_groups应该被显式至零，说明该应用只接受到该应用的消息，填充完上述域， 使用如下方式进行绑定：</p>  <div>   <pre>   1:  bind(fd, (struct sockaddr*)&amp;nladdr, sizeof(nladdr));</pre> </div>  <p><strong>发送一条netlink消息</strong></p>  <p>为了发送一条netlink消息到内核或者其他的用户空间进程，另外一个struct sockaddr_nl  nladdr需要作为目的地址，这和使用sendmsg()发送一个UDP包是一样的。如果该消息是发送至内核的，那么nl_pid和nl_groups 都置为0.</p>  <p>如果说消息时发送给另一个进程的单播消息，nl_pid是另外一个进程的pid值而nl_groups为零。</p>  <p>如果消息是发送给一个或多个多播组的多播消息，所有的目的多播组必须bitmask必须or起来从而形成nl_groups域。当我们填充struct msghdr结构用于sendmsg时，使用如下：</p>  <div>   <pre>   1:  struct msghdr msg;</pre>    <pre>   2:  msg.msg_name = (void *)&amp;(nladdr);</pre>    <pre>   3:  msg.msg_namelen = sizeof(nladdr);</pre> </div>   <p>netlink套接字也需要它自己本身的消息头，这是为了给所有协议类型的netlink消息提供一个统一的平台。</p>  <p>因为Linux内核netlink核心假设每个netlink消息中存在着以下的头，所有应用也必须在其发送的消息中提供这些头信息：</p>  <div>   <pre>   1:  struct nlmsghdr</pre>    <pre>   2:  {</pre>    <pre>   3:    __u32 nlmsg_len;   /* Length of message */</pre>    <pre>   4:    __u16 nlmsg_type;  /* Message type*/</pre>    <pre>   5:    __u16 nlmsg_flags; /* Additional flags */</pre>    <pre>   6:    __u32 nlmsg_seq;   /* Sequence number */</pre>    <pre>   7:    __u32 nlmsg_pid;   /* Sending process PID */</pre>    <pre>   8:  };</pre> </div>   <p>nlmsg_len指整个netlink消息的长度，包括头信息，这也是netlink核心所必须的。nlmsg_type用于应用但是对于 netlink核心而言其是透明的。nlmsg_flags用于给定附加的控制信息，其被netlink核心读取和更新。nlmsg_seq和 mlmsg_pid，应用用来跟踪消息，这些对于netlink核心也是透明的。</p>  <p>所以一个netlink消息由消息头和消息负载组成。一旦一个消息被加入，它就加入到一个通过nlh指针指向的缓冲区。我们也可以将消息发送到struct msghdr msg：</p>  <div>   <pre>   1:  struct iovec iov;</pre>    <pre>   2:  &nbsp;</pre>    <pre>   3:  iov.iov_base = (void *)nlh;</pre>    <pre>   4:  iov.iov_len = nlh-&gt;nlmsg_len;</pre>    <pre>   5:  &nbsp;</pre>    <pre>   6:  msg.msg_iov = &amp;iov;</pre>    <pre>   7:  msg.msg_iovlen = 1;</pre> </div>   <p>经过以上步骤，调用sendmsg()函数来发送netlink消息：</p>  <div>   <pre>   1:  sendmsg(fd, &amp;msg, 0);</pre> </div>  <div>&nbsp;</div>  <div><strong>接收netlink消息</strong></div>                <p>一个接收程序必须分配一个足够大的内存用于保存netlink消息头和消息负载。然后其填充struct msghdr msg，然后使用标准的recvmsg()函数来接收netlink消息，假设缓存通过nlh指针指向：</p>  <div>   <pre>   1:  struct sockaddr_nl nladdr;</pre>    <pre>   2:  struct msghdr msg;</pre>    <pre>   3:  struct iovec iov;</pre>    <pre>   4:  &nbsp;</pre>    <pre>   5:  iov.iov_base = (void *)nlh;</pre>    <pre>   6:  iov.iov_len = MAX_NL_MSG_LEN;</pre>    <pre>   7:  msg.msg_name = (void *)&amp;(nladdr);</pre>    <pre>   8:  msg.msg_namelen = sizeof(nladdr);</pre>    <pre>   9:  &nbsp;</pre>    <pre>  10:  msg.msg_iov = &amp;iov;</pre>    <pre>  11:  msg.msg_iovlen = 1;</pre>    <pre>  12:  recvmsg(fd, &amp;msg, 0);</pre> </div>   <p>当消息被正确的接收之后，nlh应该指向刚刚接收到的netlink消息的头。nladdr应该包含接收消息的目的地址，其中包括了消息发送者的 pid和多播组。同时，宏NLMSG_DATA(nlh)，定义在netlink.h中，返回一个指向netlink消息的负载的指针。 close(fd)调用关闭fd描述符所标识的socket。</p>  <p><strong>内核空间netlink API</strong></p>  <p>内核空间的netlinkAPI在内核中被netlink核心支持，即net/core/af_netlink.c。从内核角度看，这些API不同 于用户空间的API。这些API可以被内核模块使用从而存取netlink套接字与用户空间程序通信。除非你使用现存的netlink套接字协议类型，否 则你必须通过在netlink.h中定义一个常量来添加你自己的协议类型。例如，我们需要添加一个netlink协议类型用于测试，则在 netlink.h中加入下面的语句：</p>  <div>   <pre>   1:  #define NETLINK_TEST  17</pre> </div>   <p>之后，亦可以在linux内核中的任何地方引用添加的协议类型。</p>  <p>在用户空间，我们使用socket()来创建一个netlink套接字，但是在内核空间，我们使用如下的API：</p>  <div>   <pre>   1:  truct sock *</pre>    <pre>   2:  netlink_kernel_create(int unit,</pre>    <pre>   3:             void (*input)(struct sock *sk, int len));</pre> </div>   <p>参数unit，即为netlink协议类型，如NETLINK_TEST，回调函数会在消息到达netlink套接字时调用。当用户态程序发送一个NETLINK_TEST协议类型的消息给内核时，input()函数被调用。下面是一个实现回调函数的例子：</p>  <div>   <pre>   1:  void input (struct sock *sk, int len)</pre>    <pre>   2:  {</pre>    <pre>   3:   struct sk_buff *skb;</pre>    <pre>   4:   struct nlmsghdr *nlh = NULL;</pre>    <pre>   5:   u8 *payload = NULL;</pre>    <pre>   6:  &nbsp;</pre>    <pre>   7:   while ((skb = skb_dequeue(&amp;sk-&gt;receive_queue))</pre>    <pre>   8:         != NULL) {</pre>    <pre>   9:   /* process netlink message pointed by skb-&gt;data */</pre>    <pre>  10:   nlh = (struct nlmsghdr *)skb-&gt;data;</pre>    <pre>  11:   payload = NLMSG_DATA(nlh);</pre>    <pre>  12:   /* process netlink message with header pointed by</pre>    <pre>  13:    * nlh    and payload pointed by payload</pre>    <pre>  14:    */</pre>    <pre>  15:   }</pre>    <pre>  16:  }</pre> </div>         <p>input()函数在发送进程的sendmsg()系统调用上下文执行。如果在input中处理netlink消息非常快，那是没有问题的。如果处 理netlink消息需要很长的时间，我们希望在input()外面处理消息来避免阻塞其他系统调用进入内核。事实上，我们可以使用一个指定的内核线程来 来不断执行以下的步骤。使用skb=skb_recv_datagram(nl_sk)，其中nl_sk是 netlink_kernel_create()返回的netlink套接字。然后，处理由skb-&gt;data指向的netlink消息。</p>  <p>以下的内核线程在没有netlink消息在nl_sk中时睡眠，在回调函数input中，我们只要唤醒睡眠的内核线程，如下所示：</p>  <div>   <pre>   1:  void input (struct sock *sk, int len)</pre>    <pre>   2:  {</pre>    <pre>   3:    wake_up_interruptible(sk-&gt;sleep);</pre>    <pre>   4:  }</pre> </div>   <p>这是一个更具有扩展性的用户和内核通信的模型。其也提高了上下文交换的粒度。</p>  <p><strong>在内核中发送netlink消息</strong></p>  <p>真如在用户空间中一样，在发送一个netlink消息时需要设置源和目的netlink消息地址。假设socket缓存中包含了将要发送的netlink消息，本地地址可以通过以下方式设置：</p>  <div>   <pre>   1:  NETLINK_CB(skb).groups = local_groups;</pre>    <pre>   2:  NETLINK_CB(skb).pid = 0;   /* from kernel */</pre> </div>   <p>目的地址可以如下设置：</p>  <div>   <pre>   1:  NETLINK_CB(skb).dst_groups = dst_groups;</pre>    <pre>   2:  NETLINK_CB(skb).dst_pid = dst_pid;</pre> </div>   <p>这些信息不是存储在skb-&gt;data，而是存储在skb中的netlink控制块中。发送一个消息，使用：</p>  <div>   <pre>   1:  int</pre>    <pre>   2:  netlink_unicast(struct sock *ssk, struct sk_buff</pre>    <pre>   3:                  *skb, u32 pid, int nonblock);</pre> </div>   <p>其中ssk是netlink_kernel_create返回的netlink套接字，skb-&gt;data指向netlink将要发送的消息而pid是接受该消息的用户程序id。nonblock用于标识在接收缓存不可用时，API是阻塞还是立即返回失败。</p>  <p>你也可以发送一个多播消息。以下的API用于将消息传送到指定的进程，同时多播至指定的多播组。</p>  <div>   <pre>   1:  void</pre>    <pre>   2:  netlink_broadcast(struct sock *ssk, struct sk_buff</pre>    <pre>   3:           *skb, u32 pid, u32 group, int allocation);</pre> </div>         <p>group是所有接收多播组的bitmask。allocation是内核内存分配的类型。通常，GFP_ATOMIC用于中断上下文而在其他情况下是用GFP_KERNEL.只是因为API可能需要分配一个或者多个套接字缓存来克隆多播消息。</p>  <p><strong>在内核中关闭一个netlink套接字</strong></p>  <p>给定了netlink_kernel_create()函数返回的struct sock *nl_sk,我们可以通过调用以下的API关闭netlink套接字。</p>  <div>   <pre>   1:  sock_release(nl_sk-&gt;socket);</pre> </div>   <p><strong>在内核和用户态使用单播通信</strong></p>  <div>   <pre>   1:  #include &lt;sys/socket.h&gt;</pre>    <pre>   2:  #include &lt;linux/netlink.h&gt;</pre>    <pre>   3:  &nbsp;</pre>    <pre>   4:  #define MAX_PAYLOAD 1024  /* maximum payload size*/</pre>    <pre>   5:  struct sockaddr_nl src_addr, dest_addr;</pre>    <pre>   6:  struct nlmsghdr *nlh = NULL;</pre>    <pre>   7:  struct iovec iov;</pre>    <pre>   8:  int sock_fd;</pre>    <pre>   9:  &nbsp;</pre>    <pre>  10:  void main() {</pre>    <pre>  11:   sock_fd = socket(PF_NETLINK, SOCK_RAW,NETLINK_TEST);</pre>    <pre>  12:  &nbsp;</pre>    <pre>  13:   memset(&amp;src_addr, 0, sizeof(src_addr));</pre>    <pre>  14:   src__addr.nl_family = AF_NETLINK;</pre>    <pre>  15:   src_addr.nl_pid = getpid();  /* self pid */</pre>    <pre>  16:   src_addr.nl_groups = 0;  /* not in mcast groups */</pre>    <pre>  17:   bind(sock_fd, (struct sockaddr*)&amp;src_addr,</pre>    <pre>  18:        sizeof(src_addr));</pre>    <pre>  19:  &nbsp;</pre>    <pre>  20:   memset(&amp;dest_addr, 0, sizeof(dest_addr));</pre>    <pre>  21:   dest_addr.nl_family = AF_NETLINK;</pre>    <pre>  22:   dest_addr.nl_pid = 0;   /* For Linux Kernel */</pre>    <pre>  23:   dest_addr.nl_groups = 0; /* unicast */</pre>    <pre>  24:  &nbsp;</pre>    <pre>  25:   nlh=(struct nlmsghdr *)malloc(</pre>    <pre>  26:                   NLMSG_SPACE(MAX_PAYLOAD));</pre>    <pre>  27:   /* Fill the netlink message header */</pre>    <pre>  28:   nlh-&gt;nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);</pre>    <pre>  29:   nlh-&gt;nlmsg_pid = getpid();  /* self pid */</pre>    <pre>  30:   nlh-&gt;nlmsg_flags = 0;</pre>    <pre>  31:   /* Fill in the netlink message payload */</pre>    <pre>  32:   strcpy(NLMSG_DATA(nlh), "Hello you!");</pre>    <pre>  33:  &nbsp;</pre>    <pre>  34:   iov.iov_base = (void *)nlh;</pre>    <pre>  35:   iov.iov_len = nlh-&gt;nlmsg_len;</pre>    <pre>  36:   msg.msg_name = (void *)&amp;dest_addr;</pre>    <pre>  37:   msg.msg_namelen = sizeof(dest_addr);</pre>    <pre>  38:   msg.msg_iov = &amp;iov;</pre>    <pre>  39:   msg.msg_iovlen = 1;</pre>    <pre>  40:  &nbsp;</pre>    <pre>  41:   sendmsg(fd, &amp;msg, 0);</pre>    <pre>  42:  &nbsp;</pre>    <pre>  43:   /* Read message from kernel */</pre>    <pre>  44:   memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));</pre>    <pre>  45:   recvmsg(fd, &amp;msg, 0);</pre>    <pre>  46:   printf(" Received message payload: %s\n",</pre>    <pre>  47:      NLMSG_DATA(nlh));</pre>    <pre>  48:  &nbsp;</pre>    <pre>  49:   /* Close Netlink Socket */</pre>    <pre>  50:   close(sock_fd);</pre>    <pre>  51:  }</pre> </div>     <div>   <pre>   1:  struct sock *nl_sk = NULL;</pre>    <pre>   2:  &nbsp;</pre>    <pre>   3:  void nl_data_ready (struct sock *sk, int len)</pre>    <pre>   4:  {</pre>    <pre>   5:    wake_up_interruptible(sk-&gt;sleep);</pre>    <pre>   6:  }</pre>    <pre>   7:  &nbsp;</pre>    <pre>   8:  void netlink_test() {</pre>    <pre>   9:   struct sk_buff *skb = NULL;</pre>    <pre>  10:   struct nlmsghdr *nlh = NULL;</pre>    <pre>  11:   int err;</pre>    <pre>  12:   u32 pid;</pre>    <pre>  13:  &nbsp;</pre>    <pre>  14:   nl_sk = netlink_kernel_create(NETLINK_TEST,</pre>    <pre>  15:                                     nl_data_ready);</pre>    <pre>  16:   /* wait for message coming down from user-space */</pre>    <pre>  17:   skb = skb_recv_datagram(nl_sk, 0, 0, &amp;err);</pre>    <pre>  18:  &nbsp;</pre>    <pre>  19:   nlh = (struct nlmsghdr *)skb-&gt;data;</pre>    <pre>  20:   printk("%s: received netlink message payload:%s\n",</pre>    <pre>  21:          __FUNCTION__, NLMSG_DATA(nlh));</pre>    <pre>  22:  &nbsp;</pre>    <pre>  23:   pid = nlh-&gt;nlmsg_pid; /*pid of sending process */</pre>    <pre>  24:   NETLINK_CB(skb).groups = 0; /* not in mcast group */</pre>    <pre>  25:   NETLINK_CB(skb).pid = 0;      /* from kernel */</pre>    <pre>  26:   NETLINK_CB(skb).dst_pid = pid;</pre>    <pre>  27:   NETLINK_CB(skb).dst_groups = 0;  /* unicast */</pre>    <pre>  28:   netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT);</pre>    <pre>  29:   sock_release(nl_sk-&gt;socket);</pre>    <pre>  30:  }</pre> </div>   <p><strong>在内核和用户态使用单播通信</strong></p>  <div>   <pre>   1:  #include &lt;sys/socket.h&gt;</pre>    <pre>   2:  #include &lt;linux/netlink.h&gt;</pre>    <pre>   3:  &nbsp;</pre>    <pre>   4:  #define MAX_PAYLOAD 1024  /* maximum payload size*/</pre>    <pre>   5:  struct sockaddr_nl src_addr, dest_addr;</pre>    <pre>   6:  struct nlmsghdr *nlh = NULL;</pre>    <pre>   7:  struct iovec iov;</pre>    <pre>   8:  int sock_fd;</pre>    <pre>   9:  &nbsp;</pre>    <pre>  10:  void main() {</pre>    <pre>  11:   sock_fd=socket(PF_NETLINK, SOCK_RAW, NETLINK_TEST);</pre>    <pre>  12:  &nbsp;</pre>    <pre>  13:   memset(&amp;src_addr, 0, sizeof(local_addr));</pre>    <pre>  14:   src_addr.nl_family = AF_NETLINK;</pre>    <pre>  15:   src_addr.nl_pid = getpid();  /* self pid */</pre>    <pre>  16:   /* interested in group 1&lt;&lt;0 */</pre>    <pre>  17:   src_addr.nl_groups = 1;</pre>    <pre>  18:   bind(sock_fd, (struct sockaddr*)&amp;src_addr,</pre>    <pre>  19:        sizeof(src_addr));</pre>    <pre>  20:  &nbsp;</pre>    <pre>  21:   memset(&amp;dest_addr, 0, sizeof(dest_addr));</pre>    <pre>  22:  &nbsp;</pre>    <pre>  23:   nlh = (struct nlmsghdr *)malloc(</pre>    <pre>  24:                            NLMSG_SPACE(MAX_PAYLOAD));</pre>    <pre>  25:   memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));</pre>    <pre>  26:  &nbsp;</pre>    <pre>  27:   iov.iov_base = (void *)nlh;</pre>    <pre>  28:   iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);</pre>    <pre>  29:   msg.msg_name = (void *)&amp;dest_addr;</pre>    <pre>  30:   msg.msg_namelen = sizeof(dest_addr);</pre>    <pre>  31:   msg.msg_iov = &amp;iov;</pre>    <pre>  32:   msg.msg_iovlen = 1;</pre>    <pre>  33:  &nbsp;</pre>    <pre>  34:   printf("Waiting for message from kernel\n");</pre>    <pre>  35:  &nbsp;</pre>    <pre>  36:   /* Read message from kernel */</pre>    <pre>  37:   recvmsg(fd, &amp;msg, 0);</pre>    <pre>  38:   printf(" Received message payload: %s\n",</pre>    <pre>  39:          NLMSG_DATA(nlh));</pre>    <pre>  40:   close(sock_fd);</pre>    <pre><p>  41:  }</p><p>&nbsp;</p></pre> </div>   <div>   <pre>   1:  #define MAX_PAYLOAD 1024</pre>    <pre>   2:  struct sock *nl_sk = NULL;</pre>    <pre>   3:  &nbsp;</pre>    <pre>   4:  void netlink_test() {</pre>    <pre>   5:   sturct sk_buff *skb = NULL;</pre>    <pre>   6:   struct nlmsghdr *nlh;</pre>    <pre>   7:   int err;</pre>    <pre>   8:  &nbsp;</pre>    <pre>   9:   nl_sk = netlink_kernel_create(NETLINK_TEST,</pre>    <pre>  10:                                 nl_data_ready);</pre>    <pre>  11:   skb=alloc_skb(NLMSG_SPACE(MAX_PAYLOAD),GFP_KERNEL);</pre>    <pre>  12:   nlh = (struct nlmsghdr *)skb-&gt;data;</pre>    <pre>  13:   nlh-&gt;nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);</pre>    <pre>  14:   nlh-&gt;nlmsg_pid = 0;  /* from kernel */</pre>    <pre>  15:   nlh-&gt;nlmsg_flags = 0;</pre>    <pre>  16:   strcpy(NLMSG_DATA(nlh), "Greeting from kernel!");</pre>    <pre>  17:   /* sender is in group 1&lt;&lt;0 */</pre>    <pre>  18:   NETLINK_CB(skb).groups = 1;</pre>    <pre>  19:   NETLINK_CB(skb).pid = 0;  /* from kernel */</pre>    <pre>  20:   NETLINK_CB(skb).dst_pid = 0;  /* multicast */</pre>    <pre>  21:   /* to mcast group 1&lt;&lt;0 */</pre>    <pre>  22:   NETLINK_CB(skb).dst_groups = 1;</pre>    <pre>  23:  &nbsp;</pre>    <pre>  24:   /*multicast the message to all listening processes*/</pre>    <pre>  25:   netlink_broadcast(nl_sk, skb, 0, 1, GFP_KERNEL);</pre>    <pre>  26:   sock_release(nl_sk-&gt;socket);</pre>    <pre>  27:  }</pre> </div>   <p><strong>Netlink可靠性机制</strong></p>  <p>在基于netlink的通信中，有两种可能的情形会导致消息丢失：</p>  <ol><li>内存耗尽，没有足够多的内存分配给消息</li><li>缓存复写，接收队列中没有空间存储消息，这在内核空间和用户空间之间通信时可能会发生</li></ol>  <p>缓存复写在以下情况很可能会发生：</p>  <ol><li>内核子系统以一个恒定的速度发送netlink消息，但是用户态监听者处理过慢</li><li>用户存储消息的空间过小</li></ol>  <p>&nbsp;&nbsp; 如果netlink传送消息失败，那么recvmsg()函数会返回No&nbsp; buffer space  available(ENOBUFS)错误。那么，用户空间进程知道它丢失了信息，如果内核子系统支持dump操作，它可以重新同步来获取最新的消息。在 dump操作中，netlink通过在每次调用recvmsg()函数时传输一个包的流控机制来防止接收队列的复写。改包消耗一个内存页，其包含了几个多 部分netlink消息。图6中的序列图显示了在一个重新同步的过程中所使用的dump操作。</p>  <p>&nbsp;</p>  <p><a href="http://static.oschina.net/uploads/img/201205/25100854_HRq5.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" alt="image" src="http://static.oschina.net/uploads/img/201205/25100910_jkyr.png" border="0" height="248" width="434" /></a> </p>  <p>另一方面，缓存复写不会发生在用户和内核空间的通信中，因为sendmsg()同步的将netlink消息发送到内核子系统。如果使用的是阻塞套接字，那么netlink在从用户空间到内核空间的通信时完全可靠的，因为内存分配可以等待，所以没有内存耗尽的可能。</p>  <p>netlink也可以提供应答机制。所以如果用户空间进程发送了一个设置了NLM_F_ACK标志的请求，netlink会在netlink错误消息中报告给用户空间刚才请求操作的结果。</p>  <p>从用户空间的角度来看，Netlink套接字在通用的BSD套接字接口之上实现。因此，netlink套接字编程与通用的TCP/IP编程类似。但是，我们也应该考虑几个与netlink相关的特殊问题：</p>  <ol><li>netlink套接字没有像其他协议一样对用户空间隐藏协议细节。事实上，netlink传递的是整个消息，包括netlink头和其他信 息。因此，这就导致了数据处理函数与通用的TCP/IP套接字不同，所以用户态程序必须根据其格式解析和构建netlink信息。然而，没有标准的工具来 完成这些工作，所以你必须实现自己的函数或者使用一些现成的库。</li><li>来自netlink和内核子系统的错误不是通过recvmsg()函数返回的整数值来表现的。事实上，错误信息时被包装在netlink错误 消息中的。唯一的例外是(ENOBUFS)错误，该错误不是包装在netlink消息中，因为报告该错误的原因就是我们没有足够的空间来缓存新的 netlink消息。标准的通用套接字错误，如(EAGAIN),通常和其他轮询原语，例如poll()和select()，也是通过recvmsg() 返回整数值。</li></ol></div></div>原文：<div>http://my.oschina.net/longscu/blog/59534</div><img src ="http://www.blogjava.net/jasmine214--love/aggbug/379752.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2012-06-01 16:25 <a href="http://www.blogjava.net/jasmine214--love/archive/2012/06/01/379752.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>句柄的理解</title><link>http://www.blogjava.net/jasmine214--love/archive/2012/05/31/379689.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Thu, 31 May 2012 12:04:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2012/05/31/379689.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/379689.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2012/05/31/379689.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/379689.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/379689.html</trackback:ping><description><![CDATA[<div><p><span style="font-size:13pt">从广义上，能够从一个数值拎起一大堆数据的东西都可以叫做句柄。句柄的英文是"Handle"，本义就是"柄"，只是在计算机科学中，被特别地翻译成"句柄"，其实还是个"柄"。从一个小东西拎起一大堆东西，这难道不像是个"柄"吗？ </span></p><p><span style="font-size:13pt">然后，指针其实也是一种"句柄"，只是由于指针同时拥有更特殊的含义&#8212;&#8212;实实在在地对应内存里地一个地址&#8212;&#8212;所以，通常不把指针说成是"句柄"。但指针也有着能从一个32位的值引用到一大堆数据的作用，这不是句柄又是什么？ </span></p><p><span style="font-size:13pt">Windows系统中有许多内核对象（这里的对象不完全等价 于"面向对象程序设计"一词中的"对象"，虽然实质上还真差不多），比如打开的文件，创建的线程，程序的窗口，等等。这些重要的对象肯定不是4个字节或者 8个字节足以完全描述的，他们拥有大量的属性。为了保存这样一个"对象"的状态，往往需要上百甚至上千字节的内存空间，那么怎么在程序间或程序内部的子过 程（函数）之间传递这些数据呢？拖着这成百上千的字节拷贝来拷贝去吗？显然会浪费效率。那么怎么办？当然传递这些对象的首地址是一个办法，但这至少有两个 缺点： </span></p><ol style="margin-left: 36pt"><li><div><span style="font-size:13pt">暴露了内核对象本身，使得程序（而不是操作系统内核）也可以任意地修改对象地内部状态（首地址都知道了，还有什么不能改的？），这显然是操作系统内核所不允许的； </span></div></li><li><div><span style="font-size:13pt">操作系统有定期整理内存的责任，如果一些内存整理过一次后，对象被搬走了怎么办？ </span></div></li></ol><p><span style="font-size:13pt">所以，Windows操作系统就采用进一步的间接：在进程的地址空间中设一张表，表里头专门保存一些编号和由这个编号对应一个地址，而由那个地址去引用实际的对象，这个编号跟那个地址在数值上没有任何规律性的联系，纯粹是个映射而已。 </span></p><p><span style="font-size:13pt">在Windows系统中，这个编号就叫做"句柄"。  </span></p><p>&nbsp;</p><p><span style="font-size:13pt">Handle在Windows中的含义很广泛，以下关于谈到的Handle除非特别说明，将仅限于进程、线程的上下文中。 </span></p><p><span style="font-size:13pt">1、先来谈谈Handle </span></p><p><span style="font-size:13pt">Handle本身是一个32位的无符号整数，它用来代表一个内 核对象。它并不指向实际的内核对象，用户模式下的程序永远不可能获得一个内核对象的实际地址（一般情况下）。那么Handle的意义何在？它实际上是作为 一个索引在一个表中查找对应的内核对象的实际地址。那么这个表在哪里呢？每个<span style="text-decoration:underline">进程</span>都有这样的一个表，叫句柄表。该表的第一项就是进程自己的句柄，这也是为什么你调用GetCurrentProcess()总是返回0x7FFFFFFF原因。 </span></p><p><span style="font-size:13pt">简单地说，Handle就是一种用来"间接"代表一个内核对象的整数值。你可以在程序中使用handle来代表你想要操作的内核对象。这里的内核对象包括：事件（Event）、线程、进程、Mutex等等。我们最常见的就是文件句柄（file handle）。 </span></p><p><span style="font-size:13pt">另外要注意的是，Handle仅在其所属的进程中才有意义。将一个进程拥有的handle传给另一个进程没有任何意义，如果非要这么做，则需要使用DuplicateHandle()，在多个进程间传递Handle是另外一个话题了，与这里要讨论的无关。 </span></p><p><span style="font-size:13pt">2、进程ID </span></p><p><span style="font-size: 13pt;">首先，进程ID是一个32位无符号整数，每个进程都有这样的一个ID，并且该ID在系统范围内是唯一的。系统使用该ID来唯一确定一个进程。 </span></p><p><span style="font-size:13pt">深入些说，系统可能使用进程ID来计算代表该进程的内核对象的基地址（及EPROCESS结构的基地址），具体的计算公式你可以去问微软的OS开发人员。 </span></p><p><span style="font-size:13pt">3、HINSTANCE </span></p><p><span style="font-size:13pt">HINSTANCE也是一个32无符号整数，它表示程序加载到内存中的基地址。</span></p></div>原文：<div>http://www.cppblog.com/mymsdn/archive/2011/11/28/74221.html</div><img src ="http://www.blogjava.net/jasmine214--love/aggbug/379689.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2012-05-31 20:04 <a href="http://www.blogjava.net/jasmine214--love/archive/2012/05/31/379689.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>socket简单理解</title><link>http://www.blogjava.net/jasmine214--love/archive/2012/05/31/379688.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Thu, 31 May 2012 11:52:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2012/05/31/379688.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/379688.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2012/05/31/379688.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/379688.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/379688.html</trackback:ping><description><![CDATA[<div>&nbsp; &nbsp; 一.什么是Socket<br />　　1.所谓Socket通常也称作&#8220;套接字&#8221;，用于描述IP地址和端口，是一个通信连的句柄<br />　　2.应用程序通常通过&#8220;套接字&#8221;向网络发送请求或者应答网络请求<p>　　二.Socket基本通信模型</p><p align="center"><img src="http://www.jucoder.com/static/upload/day_111025/201110251121488483.jpg" alt="&lt;a href='/bbs/forum-0-20601-206.html' &gt;android&lt;/a&gt;开发之Socket编程" border="0" height="372" width="500" /></p><p align="left">　　三.使用基于TCP协议的Socket<br />　　一个客户端要发起一次通信，首先必须知道运行服务器端的主机IP地址。然后由网络基础设施利用目标地址，将客户端发送的信息传递到正确的主机上，在<a href="http://www.jucoder.com/bbs/forum-0-0-202.html">java</a>中，地址可以由一个字符串来定义，这个字符串可以使数字型的地址（比如192.168.1.1），也可以是主机名（example.com）。<br />　　在Java当中InetAddress类代表了一个网络目标地址，包括主机名和数字类型的地址信息。下面为大家介绍一下基于TCP协议操作Socket的API：</p><p align="left">　　ServerSocket：这个类是实现了一个服务器端的Socket，利用这个类可以监听来自网络的请求。<br />　　a)创建ServerSocket的方法：<br />　　ServerSocket(Int localPort)<br />　　ServerSocket(int localport,int queueLimit)<br />　　ServerSocket(int localport,int queueLimit,InetAddress localAddr)<br />　　创建一个ServerSocket必须指定一个端口，以便客户端能够向该端口号发送连接请求。端口的有效范围是0-65535<br />　　b)ServerSocket操作<br />　　Socket accept()<br />　　void close<br />　　accept()方法为下一个传入的连接请求创建Socket实例，并将已成功连接的Socket实例返回给服务器套接字，如果没有连接请求，accept()方法将阻塞等待；<br />　　close方法用于关闭套接字</p><p align="left">　　Socket：<br />　　a)创建Socket的方法：<br />　　Socket（InetAddress remoteAddress,int remotePort）<br />　　利用Socket的构造函数，可以创建一个TCP套接字后，先连接到指定的远程地址和端口号。<br />　　b)操作Socket的方法<br />　　InputStream getInputStream()<br />　　OutputStream getOutputStream()<br />　　void close()</p><p align="left">　　操作TCPsocket的图示：&nbsp;</p><p align="center"><img src="http://www.jucoder.com/static/upload/day_111025/201110251122074438.jpg" alt="Android开发之Socket编程" border="0" height="264" width="500" /></p><p align="left">　　使用基于UDP的Socket<br />　　a)创建DatagramPacket<br />　　DatagramSocket(byte [] data,int offset,int length,InetAddress remoteAddr,int remotePort)<br />　　该构造函数创建一个数据报文对象，数据包含在第一个参数当中<br />　　b)创建DatagramSocket创建<br />　　DatagramSocket(int localPort)<br />　　以上构造函数将创建一个UDP套接字；<br />　　c)DatagramSocket：发送和接受<br />　　void send(DatagramPacket packet)<br />　　void receive(DatagramPacket packet)<br />　　send()方法用来发送DatagramPacket实例。一旦创建连接，数据报将发送到该套接字所连接的地址；<br />　　receive()方法将阻塞等待，知道接收到数据报文，并将报文中的数据复制到指定的DatagramPacket实例中</p><p align="left">原文 :<div>http://www.jucoder.com/bbs/thread-4630-0-0.html</div><br /></p></div><img src ="http://www.blogjava.net/jasmine214--love/aggbug/379688.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2012-05-31 19:52 <a href="http://www.blogjava.net/jasmine214--love/archive/2012/05/31/379688.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于C语言中return的一些总结</title><link>http://www.blogjava.net/jasmine214--love/archive/2011/03/09/346028.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Wed, 09 Mar 2011 07:06:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2011/03/09/346028.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/346028.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2011/03/09/346028.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/346028.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/346028.html</trackback:ping><description><![CDATA[<p><font color="#ff0000" size="2"><strong>在函数中，如果碰到return 语句，那么程序就会返回调用该函数的下一条语句执行，也就是说<font color="#0000ff">跳出函数的执行</font>，回到原来的地方继续执行下去。但是如果是在主函数中碰到return语句，那么整个程序就会停止，退出程序的执行。</strong></font></p>
<p><font color="#ff0000" size="2"><strong>--------------------------------------------------------------------------------------------------------------------------------------------------------------------</strong></font></p>
<p><font size="2">return是C++预定义的语句，它提供了种植函数执行的一种放大。当return语句提供了一个值时，这个值就成为函数的返回值. <br />
<br />
说到return,有必要提及主函数的定义,下面是从网络上找到的资料,好好消化吧,对了解主函数中返回值的理解有很大的帮助. <br />
<br />
很多人甚至市面上的一些书籍，都使用了void main( ) ，其实这是错误的。C/C++ 中从来没有定义过void main( ) 。C++
之父 Bjarne Stroustrup 在他的主页上的 FAQ 中明确地写着 The definition void main( ) {
/* ... */ } is not and never has been C++, nor has it even been C.（ void
main( ) 从来就不存在于 C++ 或者 C ）。下面我分别说一下 C 和 C++ 标准中对 main 函数的定义。 </font></p>
<p><br />
<font size="2"><strong>1. C</strong> <br />
在 C89 中，main( )
是可以接受的。Brian W. Kernighan 和 Dennis M. Ritchie 的经典巨著 The C programming
Language 2e（《C 程序设计语言第二版》）用的就是 main( )。不过在最新的 C99 标准中，只有以下两种定义方式是正确的： <br />
</font><font size="2"><font color="#ff0000">int main( void ) <br />
int main( int argc, char *argv[] ) <br />
</font>（参考资料：ISO/IEC 9899:1999 (E) Programming languages — C 5.1.2.2.1 Program startup） <br />
当然，我们也可以做一点小小的改动。例如：char *argv[] 可以写成 char **argv；argv 和 argc 可以改成别的变量名（如 intval 和 charval），不过一定要符合变量的命名规则。 <br />
<br />
如果不需要从命令行中获取参数，请用int main(void) ；否则请用int main( int argc, char *argv[] ) 。<br />
<font color="#ff0000">main 函数的返回值类型必须是 int ，这样返回值才能传递给程序的激活者（如操作系统）。</font><br />
<br />
如果 main 函数的最后没有写 return 语句的话，C99 规定编译器要自动在生成的目标文件中（如 exe 文件）加入return 0;
，表示程序正常退出。不过，我还是建议你最好在main函数的最后加上return
语句，虽然没有这个必要，但这是一个好的习惯。注意，vc6不会在目标文件中加入return 0; ，大概是因为 vc6 是 98
年的产品，所以才不支持这个特性。现在明白我为什么建议你最好加上 return 语句了吧！不过，gcc3.2（Linux 下的 C
编译器）会在生成的目标文件中加入 return 0; 。 </font></p>
<p><font size="2"><strong>2. C++</strong> <br />
C++98 中定义了如下两种 main 函数的定义方式： <br />
int main( ) <br />
int main( int argc, char *argv[] ) <br />
（参考资料：ISO/IEC 14882(1998-9-01)Programming languages — C++ 3.6 Start and termination） <br />
int main( ) 等同于 C99 中的 int main( void ) ；int main( int argc, char
*argv[] ) 的用法也和 C99 中定义的一样。同样，main
函数的返回值类型也必须是int。如果main函数的末尾没写return语句，C++98 规定编译器要自动在生成的目标文件中加入 return
0; 。同样，vc6 也不支持这个特性，但是 g++3.2（Linux 下的 C++ 编译器）支持。 </font></p>
<p><font size="2"><strong>3. 关于 void main</strong> <br />
在 C 和 C++
中，不接收任何参数也不返回任何信息的函数原型为&#8220;void
foo(void);&#8221;。可能正是因为这个，所以很多人都误认为如果不需要程序返回值时可以把main函数定义成void main(void)
。然而这是错误的！main 函数的返回值应该定义为 int 类型，C 和 C++ 标准中都是这样规定的。虽然在一些编译器中，void main
可以通过编译（如 vc6），但并非所有编译器都支持 void main ，因为标准中从来没有定义过 void main 。g++3.2 中如果
main 函数的返回值不是 int 类型，就根本通不过编译。而 gcc3.2 则会发出警告。所以，如果你想你的程序拥有很好的可移植性，请一定要用
int main 。 </font></p>
<p><font size="2"><strong>4. 返回值的作用</strong> <br />
main 函数的返回值用于说明程序的退出状态。如果返回 0，则代表程序正常退出，否则代表程序异常退出。下面我们在 winxp 环境下做一个小实验。首先编译下面的程序： <br />
int main( void ) <br />
{ <br />
return 0; <br />
} <br />
然后打开附件里的&#8220;命令提示符&#8221;，在命令行里运行刚才编译好的可执行文件，然后输入&#8220;echo
%ERRORLEVEL%&#8221;，回车，就可以看到程序的返回值为 0 。假设刚才编译好的文件是 a.exe ，如果输入&#8220;a &amp;&amp;
dir&#8221;，则会列出当前目录下的文件夹和文件。但是如果改成&#8220;return -1&#8221;，或者别的非 0 值，重新编译后输入&#8220;a &amp;&amp;
dir&#8221;，则 dir 不会执行。因为 &amp;&amp; 的含义是：如果 &amp;&amp; 前面的程序正常退出，则继续执行
&amp;&amp; 后面的程序，否则不执行。也就是说，利用程序的返回值，我们可以控制要不要执行下一个程序。<strong>这就是 int main 的好处</strong>。
如果你有兴趣，也可以把 main 函数的返回值类型改成非 int 类型（如 float），重新编译后执行&#8220;a &amp;&amp;
dir&#8221;，看看会出现什么情况，想想为什么会出现那样的情况。顺便提一下，如果输入 a || dir 的话，则表示如果 a 异常退出，则执行 dir
。 </font></p>
<p><br />
<font size="2"><strong>5. 那么 int main(intargc,char*argv[],char*envp[])呢？ <br />
</strong>　　这当然也不是标准 C 里面定义的东西！char*envp[] 是某些编译器提供的扩展功能，用于获取系统的环境变量。因为不是标准，所以并非所有编译器都支持，故而移植性差，不推荐使用。 <br />
到了这里,你应该了解为什么主函数定义为 int返回类型,而且函数体里面有return 0;这个语句了吧. <br />
下面具体说说我对return的应用的理解。<br />
<br />
只要一个函数的返回值是数字型的,那么就可以返回0(即return 0),其实你返回多少都没问题。<font color="#ff0000">一
般情况下，C++做出来的函数都要求返回一个值，当函数执行正常，且达到了一般情况下的目的，那么就返回0表示正确的调用了该函数，这个0就是返回给主调
函数以通知没有出错的；如果函数调用中出错，或者没有按照一般情况执行，那么就返回1，以告知主调函数采取响应策略；如果你在某个函数所在类的定义所在的
头文件中定义了一组状态值（一般都是负整数），那么函数就可以返回不同的值以告之主调函数具体发生了什么异常或错误，这种情况一般用于函数功能独立性较差
的的情况。</font>所以一般不鼓励把函数返回类型定义为void，至少返回应该是int，而在函数的最后加上return 0.语句： <br />
int func(参数列表) <br />
{ <br />
&#8230;&#8230; <br />
&#8230;&#8230; <br />
&#8230;&#8230; <br />
Return 0; <br />
} <br />
</font><font size="2"><font color="#ff0000">在函数中，如果碰到return 语句，那么程序就会返回调用该函数的下一条语句执行，也就是说跳出函数的执行，回到原来的地方继续执行下去。但是如果是在主函数中碰到return语句，那么整个程序就会停止，退出程序的执行。 <br />
</font>　　如果你定义一个函数有返回类型，可以想下面那样调用： <br />
int func() <br />
{ <br />
int value; <br />
&#8230;&#8230; <br />
&#8230;&#8230; <br />
&#8230;&#8230; <br />
return value; <br />
} <br />
int main() <br />
{ <br />
int intvalue; <br />
intvalue=func(); <br />
&#8230;&#8230; <br />
&#8230;&#8230; <br />
teturn 0; <br />
} </font></p>
<br />
<font size="2"><u>return语句后面具体是什么内容，这就要具体情况具体分析了：</u> <br />
（1） 在返回类型是char的函数中，return后应该是char类型的值； <br />
（2） 在返回类型是int的函数中，如果是要停止函数的调用，最好应该为0；其他的按照你的目的而定，只要是int 类型就行了 <br />
（3） 在返回类型是结构类型的函数中，return后应该是结构的一个实例对象。 <br />
总之，函数定义为什么样的返回类型，该函数中return后就应该是相应类型的值。<br />
原文：http://blog.ednchina.com/jiereliyi/113757/message.aspx<br />
</font>
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/346028.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2011-03-09 15:06 <a href="http://www.blogjava.net/jasmine214--love/archive/2011/03/09/346028.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C--strrchr()函数的作用</title><link>http://www.blogjava.net/jasmine214--love/archive/2011/03/09/346021.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Wed, 09 Mar 2011 05:48:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2011/03/09/346021.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/346021.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2011/03/09/346021.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/346021.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/346021.html</trackback:ping><description><![CDATA[函数名: strrchr
<p style="text-indent: 2em;">　　功 能: strrchr()函数的作用是：查找一个字符串在另一个字符串中末次出现的位置，</p>
<p style="text-indent: 2em;">　　并返回从字符串中的这个位置起， 一直到字符串结束的所有字符。</p>
<p style="text-indent: 2em;">　　如果未能找到指定字符，那么函数将返回NULL。 </p>
<p style="text-indent: 2em;">　　用 法: char *strrchr(char *str, char c); </p>
<p style="text-indent: 2em;">　　程序例: </p>
<p style="text-indent: 2em;">　　#include &lt;string.h&gt; </p>
<p style="text-indent: 2em;">　　#include &lt;stdio.h&gt; </p>
<p style="text-indent: 2em;">　　int main(void) </p>
<p style="text-indent: 2em;">　　{ </p>
<p style="text-indent: 2em;">　　char string[15]; </p>
<p style="text-indent: 2em;">　　char *ptr, c = r; </p>
<p style="text-indent: 2em;">　　strcpy(string, "This is a string"); </p>
<p style="text-indent: 2em;">　　ptr = strrchr(string, c); </p>
<p style="text-indent: 2em;">　　if (ptr) </p>
<p style="text-indent: 2em;">　　printf("The character %c is at position: %d\n", c, ptr-string); </p>
<p style="text-indent: 2em;">　　else </p>
<p style="text-indent: 2em;">　　printf("The character was not found\n"); </p>
<p style="text-indent: 2em;">　　return 0; </p>
<p style="text-indent: 2em;">　　} </p>
<p style="text-indent: 2em;">　　运行结果是：The character r is at position：12</p>
<p style="text-indent: 2em;">原文：<br />
</p>
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/346021.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2011-03-09 13:48 <a href="http://www.blogjava.net/jasmine214--love/archive/2011/03/09/346021.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C--fopen() 和 fclose()函数</title><link>http://www.blogjava.net/jasmine214--love/archive/2011/03/09/346005.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Wed, 09 Mar 2011 02:43:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2011/03/09/346005.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/346005.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2011/03/09/346005.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/346005.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/346005.html</trackback:ping><description><![CDATA[<div id="cnblogs_post_body"><span style="font-size: 10pt;"><span style="font-family: Arial;">
<p><strong>fopen()</strong><strong>和fclose()的用法</strong></p>
<p><strong>1．fopen()函数的用法</strong></p>
<p>fopen函数用于打开文件, 其调用格式为:</p>
<p>FILE *fopen(char *filename, *type);</p>
<p>fopen()函数中第一个形式参数表示文件名, 可以包含路径和文件名两部分。如:</p>
<p>"B:TEST.DAT"</p>
<p>"C:\\TC\\TEST.DAT"</p>
<p>注意：如果将路径写成"C:\TC\TEST.DAT"是不正确的, 这一点要特别注意。<br />
<br />
</p>
<p>fopen函数用来打开一个文件，其调用的一般形式为：&nbsp;文件指针名=fopen(文件名，使用文件方式)<br />
<br />
&nbsp;其中，&#8220;文件指针名&#8221;必须是被说明为FILE&nbsp;类型的指针变量，&#8220;文件名&#8221;是被打开文件的文件名。&nbsp;<br />
<br />
&#8220;使用文件方式&#8221;是指文件的类型和操作要求。&#8220;文件名&#8221;是字符串常量或字符串数组。例如：&nbsp;<br />
<br />
FILE&nbsp;*fp；<br />
<br />
fp=("file&nbsp;a","r");<br />
<br />
其意义是在当前目录下打开文件file&nbsp;a，&nbsp;只允许进行&#8220;读&#8221;操作，并使fp指向该文件。<br />
<br />
又如：<br />
<br />
FILE&nbsp;*fphzk<br />
<br />
fphzk=("c:\\hzk16',"rb")<br />
<br />
其意义是打开C驱动器磁盘的根目录下的文件hzk16，&nbsp;这是一个二进制文件，只允许按二进制方式进行读操作。<br />
<br />
两个反斜线&#8220;\\&nbsp;&#8221;中的第一个表示转义字符，第二个表示根目录。使用文件的方式共有12种，下面给出了它们的符号和意义。<br />
<br />
第二个形式参数表示打开文件的类型。关于文件类型的规定参见下表。&nbsp;<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;表&nbsp;文件操作类型</p>
<p>&nbsp;&nbsp;&nbsp; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字符&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 含义</p>
<p>&nbsp;&nbsp;&nbsp; ────────────────────────────</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "r"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打开文字文件只读</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "w"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 创建文字文件只写</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "a"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 增补, 如果文件不存在则创建一个</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "r+"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打开一个文字文件读/写</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "w+"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 创建一个文字文件读/写</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "a+"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 打开或创建一个文件增补</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "b"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 二进制文件(可以和上面每一项合用)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "t"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 文这文件(默认项)</p>
<p>&nbsp;&nbsp;&nbsp; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━<br />
<br />
</p>
<p>   　文件使用方式&nbsp;　　　　　　　意&nbsp;义<br />
<br />
&#8220;rt&#8221;　　　　　　只读打开一个文本文件，只允许读数据&nbsp;<br />
<br />
&#8220;wt&#8221;　　　　　　只写打开或建立一个文本文件，只允许写数据<br />
<br />
&#8220;at&#8221;　　　　　　追加打开一个文本文件，并在文件末尾写数据<br />
<br />
&#8220;rb&#8221;　　　　　　只读打开一个二进制文件，只允许读数据<br />
<br />
&#8220;wb&#8221;　　　　&nbsp;　&nbsp;只写打开或建立一个二进制文件，只允许写数据<br />
<br />
&#8220;ab&#8221;&nbsp;　　　　&nbsp;　追加打开一个二进制文件，并在文件末尾写数据<br />
<br />
&#8220;rt+&#8221;　　　　　&nbsp;读写打开一个文本文件，允许读和写<br />
<br />
&#8220;wt+&#8221;　　　　　&nbsp;读写打开或建立一个文本文件，允许读写<br />
<br />
&#8220;at+&#8221;　　　　　&nbsp;读写打开一个文本文件，允许读，或在文件末追加数&nbsp;据<br />
<br />
&#8220;rb+&#8221;　　　　　&nbsp;读写打开一个二进制文件，允许读和写&nbsp;<br />
<br />
&#8220;wb+&#8221;　　　　　&nbsp;读写打开或建立一个二进制文件，允许读和写<br />
<br />
&#8220;ab+&#8221;&nbsp;　　　　　读写打开一个二进制文件，允许读，或在文件末追加数据<br />
<br />
<br />
<br />
对于文件使用方式有以下几点说明：<br />
<br />
1.&nbsp;文件使用方式由r,w,a,t,b，+六个字符拼成，各字符的含义是：<br />
<br />
r(read):&nbsp;读<br />
<br />
w(write):&nbsp;写<br />
<br />
a(append):&nbsp;追加<br />
<br />
t(text):&nbsp;文本文件，可省略不写<br />
<br />
b(banary):&nbsp;二进制文件<br />
<br />
+:&nbsp;读和写<br />
<br />
<br />
<br />
2.&nbsp;凡用&#8220;r&#8221;打开一个文件时，该文件必须已经存在，&nbsp;且只能从该文件读出。<br />
<br />
<br />
<br />
3.&nbsp;用&#8220;w&#8221;打开的文件只能向该文件写入。&nbsp;若打开的文件不存在，则以指定的文件名建立该文件，若打开的文件已经存在，则将该文件删去，重建一个新文件。<br />
<br />
<br />
<br />
4.&nbsp;若要向一个已存在的文件追加新的信息，只能用&#8220;a&nbsp;&#8221;方式打开文件。<br />
<br />
5.&nbsp;在打开一个文件时，如果出错，fopen将返回一个空指针值NULL。在程序中可以用这一信息来判别是否完成打开文件的工作，并作相应的处理。因此常用以下程序段打开文件：<br />
<br />
if((fp=fopen("c:\\hzk16","rb")==NULL)<br />
<br />
{<br />
<br />
printf("\nerror&nbsp;on&nbsp;open&nbsp;c:\\hzk16&nbsp;file!");<br />
<br />
getch();<br />
<br />
exit(1);<br />
<br />
}<br />
<br />
这段程序的意义是，如果返回的指针为空，表示不能打开C盘根目录下的hzk16文件，则给出提示信息&#8220;error&nbsp;on&nbsp;open&nbsp;c:\&nbsp;hzk16file!&#8221;，下一行getch()的功能是从键盘输入一个字符，但不在屏幕上显示。在这里，该行的作用是等待，&nbsp;只有当用户从键盘敲任一键时，程序才继续执行，&nbsp;因此用户可利用这个等待时间阅读出错提示。敲键后执行exit(1)退出程序。<br />
<br />
<br />
<br />
6.&nbsp;把一个文本文件读入内存时，要将ASCII码转换成二进制码，&nbsp;而把文件以文本方式写入磁盘时，也要把二进制码转换成ASCII码，因此文本文件的读写要花费较多的转换时间。对二进制文件的读写不存在这种转换。<br />
<br />
<br />
<br />
7.&nbsp;标准输入文件(键盘)，标准输出文件(显示器&nbsp;)，标准出错输出(出错信息)是由系统打开的，可直接使用。文件关闭函数ｆｃｌｏｓｅ文件一旦使用完毕，应用关闭文件函数把文件关闭，&nbsp;以避免文件的数据丢失等错误。<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
如果要打开一个CCDOS子目录中, 文件名为CLIB的二进制文件, 可写成:</p>
<p>fopen("c:\\ccdos\\clib", "rb");</p>
<p>如果成功的打开一个文件, fopen()函数返回文件指针,&nbsp;&nbsp; 否则返回空指针(NULL)。由此可判断文件打开是否成功。</p>
<p>2. fclose()函数</p>
<p>&nbsp;&nbsp; fclose()函数用来关闭一个由fopen()函数打开的文件 , 其调用格式为:</p>
<p>&nbsp;&nbsp; nt fclose(FILE *stream);</p>
<p>&nbsp;&nbsp; 该函数返回一个整型数。当文件关闭成功时, 返回0,　否则返回一个非零值。可以根据函数的返回值判断文件是否关闭成功。 </p>
<p>例子：</p>
<p>FILE *fpOut=fopen(&#8220;c:\\a.txt&#8221;,&#8221;wt+&#8221;);</p>
<p>Int a=1;</p>
<p>Fprintf(fpOut,&#8221;%d&#8221;,a);</p>
<p>Fclose(fpOut);<br />
<br />
原文：http://www.cnblogs.com/wangliang651/archive/2006/06/16/427497.html<br />
<br />
</p>
</span></span></div>
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/346005.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2011-03-09 10:43 <a href="http://www.blogjava.net/jasmine214--love/archive/2011/03/09/346005.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C--fseek函数</title><link>http://www.blogjava.net/jasmine214--love/archive/2011/03/08/345951.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Tue, 08 Mar 2011 08:26:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2011/03/08/345951.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/345951.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2011/03/08/345951.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/345951.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/345951.html</trackback:ping><description><![CDATA[<p><span style="font-size: small;">fseek函数是用来设定文件的当前读写位置：</span>
</p>
<p><span style="font-size: small;">函数原型:int fseek(FILE *fp,long offset,int origin);<br />
函数功能:把fp的文件读写位置指针移到指定的位置.</span>
</p>
<p><span style="font-size: small;">fseek(fp,20,SEEK_SET);</span>
</p>
<p><span style="font-size: small;">//意思是把fp文件读写位置指针从文件开始后移20个字节.<br />
<br />
ftell函数是用来获取文件的当前读写位置;<br />
函数原型: long ftell(FILE *fp)<br />
函数功能:得到流式文件的当前读写位置,其返回值是当前读写位置偏离文件头部的字节数.</span>
</p>
<p><span style="font-size: small;">ban=ftell(fp); </span>
</p>
<p><span style="font-size: small;">//是获取fp指定的文件的当前读写位置,并将其值传给变量ban.<br />
<br />
fseek函数与ftell函数综合应用:<br />
分析:可以用fseek函数把位置指针移到文件尾,再用ftell函数获得这时位置指针距文件头的字节数,这个字节数就是文件的长度.</span>
</p>
<pre>
<div class="dp-highlighter">
<div class="bar">
<div class="tools"><a href="http://blog.csdn.net/swliao/archive/2009/09/04/4518012.aspx#">view plain</a><a href="http://blog.csdn.net/swliao/archive/2009/09/04/4518012.aspx#">copy to clipboard</a><a href="http://blog.csdn.net/swliao/archive/2009/09/04/4518012.aspx#">print</a><a href="http://blog.csdn.net/swliao/archive/2009/09/04/4518012.aspx#">?</a></div>
</div>
<ol class="dp-cpp" start="1">
    <li class="alt"><span><span class="preprocessor">#include&nbsp;&lt;stdio.h&gt;</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>main()&nbsp;&nbsp;</span></li>
    <li class="alt"><span>{&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;<span class="datatypes">FILE</span><span>&nbsp;*fp;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="datatypes">char</span><span>&nbsp;filename[80];&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;<span class="datatypes">long</span><span>&nbsp;length;&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;printf(<span class="string">"Input&nbsp;the&nbsp;file&nbsp;name:"</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;gets(filename);&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;fp=fopen(filename,<span class="string">"rb"</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>(fp==NULL)&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(<span class="string">"file&nbsp;not&nbsp;found!\n"</span><span>);&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fseek(fp,OL,SEEK_END);&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;length=ftell(fp);&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(<span class="string">"the&nbsp;file&nbsp;length&nbsp;%1d&nbsp;bytes\n"</span><span>,length);&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fclose(fp);&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<textarea style="display: none;" cols="50" rows="15" name="code" class="cpp">#include &lt;stdio.h&gt;
main()
{
FILE *fp;
char filename[80];
long length;
printf("Input the file name:");
gets(filename);
fp=fopen(filename,"rb");
if(fp==NULL)
printf("file not found!\n");
else
{
fseek(fp,OL,SEEK_END);
length=ftell(fp);
printf("the file length %1d bytes\n",length);
fclose(fp);
}
</textarea>原文：http://blog.csdn.net/swliao/archive/2009/09/04/4518012.aspx</pre>
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/345951.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2011-03-08 16:26 <a href="http://www.blogjava.net/jasmine214--love/archive/2011/03/08/345951.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C--access()函数的用法</title><link>http://www.blogjava.net/jasmine214--love/archive/2011/03/08/345940.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Tue, 08 Mar 2011 06:41:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2011/03/08/345940.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/345940.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2011/03/08/345940.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/345940.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/345940.html</trackback:ping><description><![CDATA[<pre id="best-answer-content" class="reply-text mb10">access 返回值是0的时候，表示存在，而返回-1的时候，表示失败。所以你的用法没问题，错误的是你对返回值的判断，应该是<br />
<br />
if(access(_Filename,0) == 0)<br />
printf("存在");<br />
else<br />
不存在。</pre>
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/345940.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2011-03-08 14:41 <a href="http://www.blogjava.net/jasmine214--love/archive/2011/03/08/345940.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C--system()函数的使用</title><link>http://www.blogjava.net/jasmine214--love/archive/2011/03/08/345937.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Tue, 08 Mar 2011 06:31:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2011/03/08/345937.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/345937.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2011/03/08/345937.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/345937.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/345937.html</trackback:ping><description><![CDATA[<pre id="question-suply">system("某DOS命令")<br />
system函数 是可以调用一些DOS命令<br />
</pre>
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/345937.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2011-03-08 14:31 <a href="http://www.blogjava.net/jasmine214--love/archive/2011/03/08/345937.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c头文件 引号 尖括号区别</title><link>http://www.blogjava.net/jasmine214--love/archive/2011/03/07/345859.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Mon, 07 Mar 2011 02:01:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2011/03/07/345859.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/345859.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2011/03/07/345859.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/345859.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/345859.html</trackback:ping><description><![CDATA[1，系统自带的头文件用尖括号括起来，这样编译器会在系统文件目录下查找。 <br />
#include &lt;xxx.h&gt; <br />
2，用户自定义的文件用双引号括起来，编译器首先会在用户目录下查找，然后在到C++安装目录（比如VC中可以指定和修改库文件查找路径，Unix和Linux中可以通过环境变量来设定）中查找，最后在系统文件中查找。 <br />
#include &#8220;xxx.h&#8221;<br />
原文；http://blog.csdn.net/michaelpp/archive/2009/06/29/4307367.aspx<br />
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/345859.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2011-03-07 10:01 <a href="http://www.blogjava.net/jasmine214--love/archive/2011/03/07/345859.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C语言中的.h文件的作用</title><link>http://www.blogjava.net/jasmine214--love/archive/2011/03/04/345734.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Fri, 04 Mar 2011 09:03:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2011/03/04/345734.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/345734.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2011/03/04/345734.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/345734.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/345734.html</trackback:ping><description><![CDATA[<br />
<div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">C</span><span style="font-size: 12pt;">语言中的</span><span style="font-size: 12pt;">.h</span><span style="font-size: 12pt;">文件和我认识由来已久，其使用方法虽不十分复杂，但我却是经过了几个月的&#8220;不懂&#8221;时期，几年的&#8220;一知半解&#8221;时期才逐渐认识清楚他的本来面目。揪其原因，我的
驽钝和好学而不求甚解固然是原因之一，但另外还有其他原因。原因一：对于较小的项目，其作用不易被充分开发，换句话说就是即使不知道他的详细使用方法，项
目照样进行，程序在计算机上照样跑。</span><span style="font-size: 12pt;">原因二：现在的各种</span><span style="font-size: 12pt;">C</span><span style="font-size: 12pt;">语言书籍都是只对</span><span style="font-size: 12pt;">C</span><span style="font-size: 12pt;">语言的语法进行详细的不能再详细的说明，但对于整个程序的文件组织构架却只字不提，找了好几本比较著名的</span><span style="font-size: 12pt;">C</span><span style="font-size: 12pt;">语言著作，却没有一个把</span><span style="font-size: 12pt;">.h</span><span style="font-size: 12pt;">文件的用法写的比较透彻的。下面我就斗胆提笔，来按照我对</span><span style="font-size: 12pt;">.h</span><span style="font-size: 12pt;">的认识思路，向大家介绍一下。</span></div>
<div style="text-indent: 24pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">让我们的思绪乘着时间机器回到大学一年级。</span><span style="font-size: 12pt;">C</span><span style="font-size: 12pt;">原来老师正在讲台上讲着我们的第一个</span><span style="font-size: 12pt;">C</span><span style="font-size: 12pt;">语言程序</span><span style="font-size: 12pt;">: Hello world!<br />
<br />
</span></div>
<div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;</span><span style="font-size: 12pt;">文件名</span><span style="font-size: 12pt;"> First.c</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">main()</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">{</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp; printf(&#8220;Hello world!&#8221;);</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">}</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 12pt;">例程</span><span style="font-size: 12pt;">-1<br />
<br />
</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">看看上面的程序，没有</span><span style="font-size: 12pt;">.h</span><span style="font-size: 12pt;">文件。是的，就是没有，世界上的万物都是经历从没有到有的过程的，我们对</span><span style="font-size: 12pt;">.h</span><span style="font-size: 12pt;">的认识，我想也需要从这个步骤开始。这时确实不需要</span><span style="font-size: 12pt;">.h</span><span style="font-size: 12pt;">文件，因为这个程序太简单了，根本就不需要。那么如何才能需要呢？让我们把这个程序变得稍微复杂些，请看下面这个，<br />
<br />
</span></div>
<div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">文件名</span><span style="font-size: 12pt;"> First.c</span></div>
<div style="text-indent: 24pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;printStr()</span></div>
<div style="text-indent: 30.85pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">{ </span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp; printf(&#8220;Hello world!&#8221;);</span></div>
<div style="text-indent: 36pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">}</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">main()</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">{</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">printStr();</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">}</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 12pt;">例程</span><span style="font-size: 12pt;">-2<br />
<br />
</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">还是没有</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">那就让我们把这个程序再稍微改动一下</span><span style="font-size: 12pt;">.</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">文件名</span><span style="font-size: 12pt;"> First.c</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">main()</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">{</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">printStr();</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">}</span></div>
<div style="background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 24pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;printStr()</span></div>
<div style="text-indent: 30.85pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">{ </span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp; printf(&#8220;Hello world!&#8221;);</span></div>
<div style="text-indent: 36pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">}</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 12pt;">例程</span><span style="font-size: 12pt;">-3</span></div>
<div style="text-indent: 36pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="background-color: #ffffff;" align="left"><span style="font-size: 12pt;">等等，不就是改变了个顺序嘛</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">但结果确是十分不同的</span><span style="font-size: 12pt;">. </span><span style="font-size: 12pt;">让我们编译一下例程</span><span style="font-size: 12pt;">-2和例程</span><span style="font-size: 12pt;">-3,</span><span style="font-size: 12pt;">你会发现例程</span><span style="font-size: 12pt;">-3</span><span style="font-size: 12pt;">是编译不过的</span><span style="font-size: 12pt;">.</span><span style="font-size: 12pt;">这时需要我们来认识一下另一个</span><span style="font-size: 12pt;">C</span><span style="font-size: 12pt;">语言中的概念</span><span style="font-size: 12pt;">:</span><span style="font-size: 12pt; color: #990199;">作用域. </span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: #990199;">我们在这里只讲述与.h文件相关的顶层作用域, 顶层作用域就是从声明点延伸到源程序文本结束</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">就</span><span style="font-size: 12pt;">printStr()</span><span style="font-size: 12pt;">这个函数来说，他没有单独的声明</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">只有定义</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">那么就从他定义的行开始</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">到</span><span style="font-size: 12pt;">first.c</span><span style="font-size: 12pt;">文件结束</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">也就是说</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">在在例程</span><span style="font-size: 12pt;">-2</span><span style="font-size: 12pt;">的</span><span style="font-size: 12pt;">main()</span><span style="font-size: 12pt;">函数的引用点上</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">已经是他的作用域</span><span style="font-size: 12pt;">. </span><span style="font-size: 12pt;">例程</span><span style="font-size: 12pt;">-3</span><span style="font-size: 12pt;">的</span><span style="font-size: 12pt;">main()</span><span style="font-size: 12pt;">函数的引用点上，还不是他的作用域</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">所以会编译出错</span><span style="font-size: 12pt;">. </span><span style="font-size: 12pt;">这种情况怎么办呢</span><span style="font-size: 12pt;">? </span><span style="font-size: 12pt; color: deeppink;">有两种方法</span><span style="font-size: 12pt;"> ,</span><span style="font-size: 12pt;">一个就是让我们回到例程</span><span style="font-size: 12pt;">-2, </span><span style="font-size: 12pt;">顺序对我们来说没什么</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">谁先谁后不一样呢，只要能编译通过</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">程序能运行</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">就让</span><span style="font-size: 12pt;">main()</span><span style="font-size: 12pt;">文件总是放到最后吧</span><span style="font-size: 12pt;">. </span><span style="font-size: 12pt;">那就让我们来看另一个例程</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">让我们看看这个方法是不是在任何时候都会起作用</span><span style="font-size: 12pt;">.</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">文件名</span><span style="font-size: 12pt;"> First.c<br />
&nbsp;&nbsp; play2()<br />
&nbsp;&nbsp; {</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;.</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;play1();</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;..</span></div>
<div style="text-indent: 42.85pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; play1(){<br />
&nbsp;&nbsp;&nbsp; &#8230;&#8230;&#8230;&#8230;&#8230;..</span></div>
<div style="text-indent: 36pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;play2();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt;"> <br />
&nbsp;&nbsp;&nbsp; &#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;<br />
&nbsp;&nbsp; }<br />
</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">main()</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">{</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">play1();</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">}</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">例程</span><span style="font-size: 12pt;">-4</span></div>
<div style="background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">也许大部分都会看出来了，这就是经常用到的一种算法</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">函数嵌套</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">那么让我们看看</span><span style="font-size: 12pt;">, play1</span><span style="font-size: 12pt;">和</span><span style="font-size: 12pt;">play2</span><span style="font-size: 12pt;">这两个函数哪个放到前面呢</span><span style="font-size: 12pt;">? </span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">这时就需要我们来使用第二种方法</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt; color: deeppink;">使用声明</span><span style="font-size: 12pt;">. </span></div>
<div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">文件名</span><span style="font-size: 12pt;"> First.c</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: red;">play1();</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: red;">play2();</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">play2()</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">{</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;.</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;play1();</span></div>
<div style="text-indent: 42.85pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;..<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; play1()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp; &#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;.</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;play2();</span></div>
<div style="text-indent: 36pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;<br />
&nbsp;&nbsp;&nbsp; }</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">main()</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">{</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">play1();</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">}</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">例程</span><span style="font-size: 12pt;">-4</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">经历了我的半天的唠叨</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">加上四个例程的说明</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">我们终于开始了用量变引起的质变</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">这篇文章的主题</span><span style="font-size: 12pt;">.h</span><span style="font-size: 12pt;">文件快要出现了。</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">一个大型的软件项目</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">可能有几千个</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">上万个</span><span style="font-size: 12pt;">play, </span><span style="font-size: 12pt;">而不只是</span><span style="font-size: 12pt;">play1,play2</span><span style="font-size: 12pt;">这么简单</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">这样就可能有</span><span style="font-size: 12pt;">N</span><span style="font-size: 12pt;">个类似</span><span style="font-size: 12pt;"> <span style="color: red;">play1(); play2(); </span></span><span style="font-size: 12pt; color: black;">这样的声明</span><span style="font-size: 12pt; color: black;">, </span><span style="font-size: 12pt; color: black;">这个时候就需要我们想办法把这样的</span><span style="font-size: 12pt; color: red;">play1(); play2(); </span><span style="font-size: 12pt; color: black;">也另行管理</span><span style="font-size: 12pt; color: black;">, </span><span style="font-size: 12pt; color: black;">而不是把他放在</span><span style="font-size: 12pt; color: black;">.c</span><span style="font-size: 12pt; color: black;">文件中</span><span style="font-size: 12pt; color: black;">, </span><span style="font-size: 12pt; color: black;">于是</span><span style="font-size: 12pt; color: black;">.h</span><span style="font-size: 12pt; color: black;">文件出现了</span><span style="font-size: 12pt; color: black;">.</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">文件名</span><span style="font-size: 12pt;"> First.h</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: red;">play1();</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: red;">play2();</span></div>
<div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">文件名</span><span style="font-size: 12pt;"> First.C</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: red;">#include &#8220;first.h&#8221;</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">play2()</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">{</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;.</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;play1();</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;..</span></div>
<div style="text-indent: 36pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">}<br />
&nbsp;&nbsp;&nbsp; play1();</span></div>
<div style="text-indent: 36pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">{ </span></div>
<div style="text-indent: 42.85pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;..</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp;&nbsp;&nbsp;&nbsp; play2();</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&nbsp; &#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;<br />
</span></div>
<div style="text-indent: 36pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">}</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">main()</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">{</span></div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">play1();</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">}</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">例程</span><span style="font-size: 12pt;">-4</span></div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">各位有可能会说</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">这位</span><span style="font-size: 12pt;">janders</span><span style="font-size: 12pt;">大虾也太罗嗦了，上面这些我也知道</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">你还讲了这么半天</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">请原谅</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">如果说上面的内容</span><span style="font-size: 12pt;">80%</span><span style="font-size: 12pt;">的人都知道的话</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">那么我保证</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">下面的内容</span><span style="font-size: 12pt;">,80%</span><span style="font-size: 12pt;">的人都不完全知道</span><span style="font-size: 12pt;">. </span><span style="font-size: 12pt;">而且这也是我讲述一件事的一贯作风</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">我总是想把一个东西说明白</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">让那些刚刚接触</span><span style="font-size: 12pt;">C</span><span style="font-size: 12pt;">的人也一样明白</span><span style="font-size: 12pt;">.</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">上面是</span><span style="font-size: 12pt;">.h</span><span style="font-size: 12pt;">文件的最基本的功能</span><span style="font-size: 12pt;">,&nbsp;</span><span style="font-size: 12pt;">那么</span><span style="font-size: 12pt;">.h</span><span style="font-size: 12pt;">文件还有什么别的功能呢</span><span style="font-size: 12pt;">? </span><span style="font-size: 12pt;">让我来描述一下我手头的一个项目吧</span><span style="font-size: 12pt;">.</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">这个项目已经做了有</span><span style="font-size: 12pt;">10</span><span style="font-size: 12pt;">年以上了，具体多少年我们部门的人谁都说不太准确</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">况且时间并不是最主要的，不再详查了。</span><span style="font-size: 12pt;">是一个通讯设备的前台软件</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">源文件大小共</span><span style="font-size: 12pt;"> 51.6M, </span><span style="font-size: 12pt;">大小共</span><span style="font-size: 12pt;">1601</span><span style="font-size: 12pt;">个文件</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">编译后大约</span><span style="font-size: 12pt;">10M</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">其庞大可想而知</span><span style="font-size: 12pt;">,&nbsp;</span><span style="font-size: 12pt;">在这里充斥着错综复杂的调用关系</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">如在</span><span style="font-size: 12pt;">second.c</span><span style="font-size: 12pt;">中还有一个函数需要调用</span><span style="font-size: 12pt;">first.c</span><span style="font-size: 12pt;">文件中的</span><span style="font-size: 12pt;">play1</span><span style="font-size: 12pt;">函数</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">如何实现呢</span><span style="font-size: 12pt;">? </span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">Second.h </span><span style="font-size: 12pt;">文件</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">play1();</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">second.c</span><span style="font-size: 12pt;">文件</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">***()</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">{</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&#8230;&#8230;&#8230;&#8230;&#8230;.</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">Play();</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;.</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">}</span></div>
<div style="text-indent: 31.5pt; background-color: #ffffff;" align="left"><span style="font-size: 9pt;">例程</span><span style="font-size: 9pt;">-5</span></div>
<div style="text-indent: 31.5pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">在</span><span style="font-size: 12pt;">second.h</span><span style="font-size: 12pt;">文件内声明</span><span style="font-size: 12pt;">play1</span><span style="font-size: 12pt;">函数，怎么能调用到</span><span style="font-size: 12pt;">first.c</span><span style="font-size: 12pt;">文件中的哪个</span><span style="font-size: 12pt;">play1</span><span style="font-size: 12pt;">函数中呢</span><span style="font-size: 12pt;">? </span><span style="font-size: 12pt;">是不是搞错了，没有搞错</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">这里涉及到</span><span style="font-size: 12pt;">c</span><span style="font-size: 12pt;">语言的另一个特性</span><span style="font-size: 12pt;">:</span><span style="font-size: 12pt;">存储类说明符</span><span style="font-size: 12pt;">.</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">C</span><span style="font-size: 12pt;">语言的存储类说明符有以下几个</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">我来列表说明一下<br />
<br />
&nbsp;&nbsp; </span><br />
<table width="100%" border="1" cellpadding="1" cellspacing="1">
    <tbody>
        <tr>
            <td style="text-align: center;">&nbsp;<strong><span style="font-size: 12pt;">说明符</span></strong></td>
            <td style="text-align: center;">&nbsp;<strong><span style="font-size: 12pt;">用&nbsp;&nbsp;&nbsp; 法</span></strong></td>
        </tr>
        <tr>
            <td style="text-align: center;">&nbsp;<em style="font-weight: bold;"><span style="font-size: 12pt;">Auto</span></em></td>
            <td>&nbsp;<em><span style="font-size: 12pt; color: blue;">只在块内变量声明中被允许</span></em><em><span style="font-size: 12pt; color: blue;">, </span></em><em><span style="font-size: 12pt; color: blue;">表示变量具有本地生存期</span></em><em><span style="font-size: 12pt; color: blue;">.</span></em></td>
        </tr>
        <tr>
            <td style="font-weight: bold; text-align: center;">&nbsp;<em><span style="font-size: 12pt;">Extern</span></em></td>
            <td>&nbsp;<em><span style="font-size: 12pt; color: deeppink;">出现在顶层或块的外部变量函数与变量声明中，表示声明的对象</span></em><em><span style="font-size: 12pt; color: deeppink;">具有静态生存期</span></em><em><span style="font-size: 12pt; color: deeppink;">, </span></em><em><span style="font-size: 12pt; color: deeppink;">连接程序知道其名字</span></em><em><span style="font-size: 12pt; color: deeppink;">.</span></em></td>
        </tr>
        <tr>
            <td style="font-weight: bold; text-align: center;">&nbsp;<em><span style="font-size: 12pt;">Static</span></em></td>
            <td style="font-style: italic; color: #999902;"><font size="3">&nbsp;可以放在函数与变量声明中,在函数定义时,只用于指定函数名,而不将函数导出到链接程序,在函数声明中,表示其后边会有定义声明的函数,存储类型static.在数据声明中,总是表示定义的声明不导出到连接程序.</font></td>
        </tr>
    </tbody>
</table>
</div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left">&nbsp;</div>
<br />
<div style="text-indent: 21pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">无疑</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">在例程</span><span style="font-size: 12pt;">-5</span><span style="font-size: 12pt;">中的</span><span style="font-size: 12pt;">second.h</span><span style="font-size: 12pt;">和</span><span style="font-size: 12pt;">first.h</span><span style="font-size: 12pt;">中</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">需要我们用</span><span style="font-size: 12pt;">extern</span><span style="font-size: 12pt;">标志符来修饰</span><span style="font-size: 12pt;">play1</span><span style="font-size: 12pt;">函数的声明</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">这样</span><span style="font-size: 12pt;">,play1()</span><span style="font-size: 12pt;">函数就可以被导出到连接程序</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">也就是实现了无论在</span><span style="font-size: 12pt;">first.c</span><span style="font-size: 12pt;">文件中调用</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">还是在</span><span style="font-size: 12pt;">second.c</span><span style="font-size: 12pt;">文件中调用</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">连接程序都会很聪明的按照我们的意愿</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">把他连接到</span><span style="font-size: 12pt;">first.c</span><span style="font-size: 12pt;">文件中的</span><span style="font-size: 12pt;">play1</span><span style="font-size: 12pt;">函数的定义上去</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">而不必我们在</span><span style="font-size: 12pt;">second.c</span><span style="font-size: 12pt;">文件中也要再写一个一样的</span><span style="font-size: 12pt;">play1</span><span style="font-size: 12pt;">函数</span><span style="font-size: 12pt;">.</span></div>
<div style="text-indent: 21pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">但随之有一个小问题</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">在例程</span><span style="font-size: 12pt;">-5</span><span style="font-size: 12pt;">中</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">我们并没有用</span><span style="font-size: 12pt;">extern</span><span style="font-size: 12pt;">标志符来修饰</span><span style="font-size: 12pt;">play1</span><span style="font-size: 12pt;">啊</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">这里涉及到另一个问题</span><span style="font-size: 12pt;">, C</span><span style="font-size: 12pt;">语言中有默认的存储类标志符</span><span style="font-size: 12pt;">. <span style="color: deeppink;">C99</span></span><span style="font-size: 12pt; color: deeppink;">中规定</span><span style="font-size: 12pt; color: deeppink;">, </span><span style="font-size: 12pt; color: deeppink;">所有顶层的默认存储类标志符都是</span><span style="font-size: 12pt; color: deeppink;">extern . </span><span style="font-size: 12pt;">原来如此啊</span><span style="font-size: 12pt;">,&nbsp;</span><span style="font-size: 12pt;">哈哈</span><span style="font-size: 12pt;">.&nbsp;</span><span style="font-size: 12pt;">回想一下例程</span><span style="font-size: 12pt;">-4, </span><span style="font-size: 12pt;">也是好险</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">我们在无知的情况下</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">竟然也误打误撞</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">用到了</span><span style="font-size: 12pt;">extern</span><span style="font-size: 12pt;">修饰符</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">否则在</span><span style="font-size: 12pt;">first.h</span><span style="font-size: 12pt;">中声明的</span><span style="font-size: 12pt;">play1</span><span style="font-size: 12pt;">函数如果不被连接程序导出</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">那么我们在在</span><span style="font-size: 12pt;">play2()</span><span style="font-size: 12pt;">中调用他时</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">是找不到其实际定义位置的</span><span style="font-size: 12pt;"> .</span></div>
<div style="text-indent: 21pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">那么我们如何来区分<em><u><span style="color: deeppink;">哪个头文件中的声明在其对应的</span></u></em></span><em><u><span style="font-size: 12pt; color: deeppink;">.c</span></u></em><em><u><span style="font-size: 12pt; color: deeppink;">文件中有定义</span></u></em><em><u><span style="font-size: 12pt; color: deeppink;">,</span></u></em><em><u><span style="font-size: 12pt; color: deeppink;">而哪个又没有呢</span></u></em><em><u><span style="font-size: 12pt; color: deeppink;">?</span></u></em><span style="font-size: 12pt;">这也许不是必须的，因为无论在哪个文件中定义，聪明的连接程序都会义无返顾的帮我们找到，并导出到连接程序</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">但我觉得他确实必要的</span><span style="font-size: 12pt;">. </span><span style="font-size: 12pt;">因为我们需要知道这个函数的具体内容是什么</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">有什么功能</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">有了新需求后我也许要修改他，</span><span style="font-size: 12pt;">我需要在短时间内能找到这个函数的定义</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">那么我来介绍一下在</span><span style="font-size: 12pt;">C</span><span style="font-size: 12pt;">语言中一个人为的规范</span><strong><span style="font-size: 12pt;">:</span></strong></div>
<div style="text-indent: 21pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21pt; background-color: #ffffff;" align="left"><em><span style="font-size: 13.5pt; color: deeppink;">在</span></em><em><span style="font-size: 13.5pt; color: deeppink;">.h</span></em><em><span style="font-size: 13.5pt; color: deeppink;">文件中声明的函数</span></em><em><span style="font-size: 13.5pt; color: deeppink;">,</span></em><em><span style="font-size: 13.5pt; color: deeppink;">如果在其对应的</span></em><em><span style="font-size: 13.5pt; color: deeppink;">.c</span></em><em><span style="font-size: 13.5pt; color: deeppink;">文件中有定义</span></em><em><span style="font-size: 13.5pt; color: deeppink;">,</span></em><em><span style="font-size: 13.5pt; color: deeppink;">那么我们在声明这个函数时</span></em><em><span style="font-size: 13.5pt; color: deeppink;">,</span></em><em><span style="font-size: 13.5pt; color: deeppink;">不使用</span></em><em><span style="font-size: 13.5pt; color: deeppink;">extern</span></em><em><span style="font-size: 13.5pt; color: deeppink;">修饰符</span></em><em><span style="font-size: 13.5pt; color: deeppink;">, </span></em><em><span style="font-size: 13.5pt; color: deeppink;">如果反之</span></em><em><span style="font-size: 13.5pt; color: deeppink;">,</span></em><em><span style="font-size: 13.5pt; color: deeppink;">则必须显示使用</span></em><em><span style="font-size: 13.5pt; color: deeppink;">extern</span></em><em><span style="font-size: 13.5pt; color: deeppink;">修饰符</span></em><em><span style="font-size: 13.5pt; color: deeppink;">.</span></em></div>
<div style="text-indent: 21pt; background-color: #ffffff;" align="left"><strong>&nbsp;</strong></div>
<div style="text-indent: 21pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">这样</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">在</span><span style="font-size: 12pt;">C</span><span style="font-size: 12pt;">语言的</span><span style="font-size: 12pt;">.h</span><span style="font-size: 12pt;">文件中</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">我们会看到两种类型的函数声明</span><span style="font-size: 12pt;">. </span><span style="font-size: 12pt;">带</span><span style="font-size: 12pt;">extern</span><span style="font-size: 12pt;">的</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">还不带</span><span style="font-size: 12pt;">extern</span><span style="font-size: 12pt;">的</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">简单明了</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">一个是引用外部函数，一个是自己生命并定义的函数</span><span style="font-size: 12pt;">.</span></div>
<div style="text-indent: 21pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">最终如下</span><span style="font-size: 12pt;">:</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">Second.h </span><span style="font-size: 12pt;">文件</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: red;">Extern play1();</span></div>
<div style="background-color: #ffffff;" align="left">&nbsp;</div>
<div style="background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">上面洋洋洒洒写了那么多都是针对函数的，而实际上</span><span style="font-size: 12pt; color: black;">.h</span><span style="font-size: 12pt; color: black;">文件却不是为函数所御用的</span><span style="font-size: 12pt; color: black;">. </span><span style="font-size: 12pt; color: black;">打开我们项目的一个</span><span style="font-size: 12pt; color: black;">.h</span><span style="font-size: 12pt; color: black;">文件我们发现除了函数外</span><span style="font-size: 12pt; color: black;">,</span><span style="font-size: 12pt; color: black;">还有其他的东西</span><span style="font-size: 12pt; color: black;">, </span><span style="font-size: 12pt; color: black;">那就是全局变量</span><span style="font-size: 12pt; color: black;">.&nbsp;</span></div>
<div style="text-indent: 21pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">在大型项目中，对全局变量的使用不可避免</span><span style="font-size: 12pt; color: black;">, </span><span style="font-size: 12pt; color: black;">比如</span><span style="font-size: 12pt; color: black;">,</span><span style="font-size: 12pt; color: black;">在</span><span style="font-size: 12pt; color: black;">first.c</span><span style="font-size: 12pt; color: black;">中需要使用一个全局变量</span><span style="font-size: 12pt; color: black;">G_test, </span><span style="font-size: 12pt; color: black;">那么我们可以在</span><span style="font-size: 12pt; color: black;">first.h</span><span style="font-size: 12pt; color: black;">中</span><span style="font-size: 12pt; color: black;">,</span><span style="font-size: 12pt; color: black;">定义</span><span style="font-size: 12pt; color: black;"> TPYE G_test. </span><span style="font-size: 12pt; color: black;">与对函数的使用类似</span><span style="font-size: 12pt; color: black;">, </span><span style="font-size: 12pt; color: black;">在</span><span style="font-size: 12pt; color: black;">second.c</span><span style="font-size: 12pt; color: black;">中我们的开发人员发现他也需要使用这个全局变量</span><span style="font-size: 12pt; color: black;">, </span><span style="font-size: 12pt; color: black;">而且要与</span><span style="font-size: 12pt; color: black;">first.c</span><span style="font-size: 12pt; color: black;">中一样的那个</span><span style="font-size: 12pt; color: black;">, </span><span style="font-size: 12pt; color: black;">如何处理</span><span style="font-size: 12pt; color: black;">? </span><span style="font-size: 12pt; color: black;">对</span><span style="font-size: 12pt; color: black;">,</span><span style="font-size: 12pt; color: black;">我们可以仿照函数中的处理方法</span><span style="font-size: 12pt; color: black;">, </span><span style="font-size: 12pt; color: black;">在</span><span style="font-size: 12pt; color: black;">second.h</span><span style="font-size: 12pt; color: black;">中再次声明</span><span style="font-size: 12pt; color: black;">TPYE G_test, </span><span style="font-size: 12pt; color: black;">根据</span><span style="font-size: 12pt; color: black;">extern</span><span style="font-size: 12pt; color: black;">的用法</span><span style="font-size: 12pt; color: black;">,</span><span style="font-size: 12pt; color: black;">以及</span><span style="font-size: 12pt; color: black;">c</span><span style="font-size: 12pt; color: black;">语言中默认的存储类型</span><span style="font-size: 12pt; color: black;">, </span><span style="font-size: 12pt; color: black;">在两个头文件中声明的</span><span style="font-size: 12pt; color: black;">TPYE G_test,</span><span style="font-size: 12pt; color: black;">其实其存储类型都是</span><span style="font-size: 12pt; color: black;">extern, </span><span style="font-size: 12pt; color: black;">也就是说不必我们操心</span><span style="font-size: 12pt; color: black;">, </span><span style="font-size: 12pt; color: black;">连接程序会帮助我们处理一切</span><span style="font-size: 12pt; color: black;">. </span><span style="font-size: 12pt; color: black;">但我们又如何区分全局变量哪个是定义声明</span><span style="font-size: 12pt; color: black;">,</span><span style="font-size: 12pt; color: black;">哪个是引用声明呢</span><span style="font-size: 12pt; color: black;">?</span><span style="font-size: 12pt; color: black;">这个比函数要复杂一些</span><span style="font-size: 12pt; color: black;">, </span><span style="font-size: 12pt; color: black;">一般在</span><span style="font-size: 12pt; color: black;">C</span><span style="font-size: 12pt; color: black;">语言中有如下几种模型来区分</span><span style="font-size: 12pt; color: black;">:</span></div>
<div style="text-indent: 21pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt; text-align: left; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">1</span><span style="font-size: 12pt; color: black;">、</span><span style="font-size: 12pt; color: black; font-weight: bold;">初始化语句模型</span></div>
<div style="margin: 0cm 0cm 0pt 39pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: deeppink;">顶层声明中，存在初始化语句是，表示这个声明是定义声明，其他声明是引用声明。</span><span style="font-size: 12pt; color: blue;">C</span><span style="font-size: 12pt; color: blue;">语言的所有文件之中，只能有一个定义声明。</span></div>
<div style="margin: 0cm 0cm 0pt 39pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">按照这个模型，我们可以在</span><span style="font-size: 12pt; color: black;">first.h</span><span style="font-size: 12pt; color: black;">中定义如下</span><span style="font-size: 12pt; color: black;">TPYE G_test=1</span><span style="font-size: 12pt; color: black;">；那么就确定在</span><span style="font-size: 12pt; color: black;">first</span><span style="font-size: 12pt; color: black;">中的是定义声明，在其他的所有声明都是引用声明。</span></div>
<div style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt; text-align: left; background-color: #ffffff;" align="left"><strong><span style="font-size: 12pt; color: black;">2</span></strong><strong><span style="font-size: 12pt; color: black;">、</span></strong><strong><span style="font-size: 12pt; color: black;">省略存储类型说明</span></strong></div>
<div style="margin: 0cm 0cm 0pt 39pt; background-color: #ffffff; color: #0001ff;" align="left"><strong><span style="font-size: 12pt;">在这个模型中，所有引用声明要显示的包括存储类</span></strong><strong><span style="font-size: 12pt;">extern</span></strong><strong><span style="font-size: 12pt;">，</span></strong><strong><span style="font-size: 12pt;">而每个外部变量的唯一定义声明中省略存储类说明符。</span></strong></div>
<div style="margin: 0cm 0cm 0pt 39pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">这个与我们对函数的处理方法类似，不再举例说明。</span></div>
<div style="background-color: #ffffff;" align="left">&nbsp;</div>
<div style="background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">&nbsp;&nbsp;&nbsp; </span><span style="font-size: 12pt; color: black;">这里还有一个需要说明，本来与本文并不十分相关，但前一段有个朋友遇到此问题，相信很多人都会遇到，</span><span style="font-size: 12pt; color: black;">那就是数组全局变量。</span></div>
<div style="background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">他遇到的问题如下：</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">在声明定义时，定义数组如下：</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">int G_glob[100];</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">在另一个文件中引用声明如下：</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">int * G_glob;</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">在</span><span style="font-size: 12pt; color: black;">vc</span><span style="font-size: 12pt; color: black;">中，是可以编译通过的，</span><span style="font-size: 12pt; color: black;">这种情况大家都比较模糊并且需要注意，数组与指针类似，但并不等于说对数组的声明起变量就是指针。</span><span style="font-size: 12pt; color: black;">上面所说的的程序在运行时发现了问题，在引用声明的那个文件中，使用这个指针时总是提示内存访问错误，原来我们的连接程序并不把指针与数组等同，连接时，也不把他们当做同一个定义，而是认为是不相关的两个定义，当然会出现错误。正确的使用方法是在引用声明中声明如下：</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: red;">int G_glob[100];</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">并且最好再加上一个</span><span style="font-size: 12pt; color: black;">extern</span><span style="font-size: 12pt; color: black;">，更加明了。</span></div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: red;">extern int G_glob[100];</span></div>
<div style="background-color: #ffffff;" align="left">&nbsp;</div>
<div style="background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">&nbsp;&nbsp;&nbsp; </span><span style="font-size: 12pt; color: black;">另外需要说明的是，在引用声明中由于不需要涉及到内存分配，可以简化如下，这样在需要对全局变量的长度进行修改时，不用把所有的引用声明也全部修改了。</span></div>
<div style="background-color: #ffffff;" align="left">&nbsp;</div>
<div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: red;">extern int G_glob[];</span></div>
<div style="background-color: #ffffff;" align="left">&nbsp;</div>
<div style="background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">&nbsp;&nbsp;&nbsp; C</span><span style="font-size: 12pt; color: black;">语言是现今为止在底层核心编程中，使用最广泛的语言，以前是，以后也不会有太大改变，虽然现在</span><span style="font-size: 12pt; color: black;">java,.net</span><span style="font-size: 12pt; color: black;">等语言和工具对</span><span style="font-size: 12pt; color: black;">c</span><span style="font-size: 12pt; color: black;">有了一定冲击，但我们看到在计算机最为核心的地方，其他语言是无论如何也代替不了的，而这个领域也正是我们对计算机痴迷的程序员所向往的。</span></div>
<span style="font-size: 12pt;"><br />
<br />
</span><hr style="width: 100%; height: 2px;" />
<span style="color: #009902;">好了,看完文章,对与C语言头文件的作用应该有了跟多的理解吧,如果这些你原本都知道了,那么仅当是温习一下而已,如果原本不知道,那么恭喜你,现在又学到一些技巧和知识.</span><br style="color: #009902;" />
<br />
<span style="color: #009902;">对于全局变量的定义和声明,其实还有另外一个解决的方法,聪明的你可能早已经猜到了:),没错,就是用宏定义的技巧实现.比如a.h文件当中有: <br />
#ifdef AAA<br />
&nbsp;int i=0;<br />
#else<br />
&nbsp;int i;<br />
#endif<br />
那么,在a.c文件当中,有如下语句:<br />
......<br />
#define AAA<br />
#include "a.h"</span><br />
<span style="color: #009902;">......<br />
而对于其他的任何包含a.h文件的头文件或者.c源文件,只需要直接包含a.h就行了<br />
......<br />
#include "a.h"</span><br />
<span style="color: #009902;">......<br />
这样就可以达到在a.c文件当中定义变量一次,而在其他的文件当中声明该变量的目的.</span><br />
<span style="color: #009902;">当然了,你完全可以根据自己的需要来决定在哪个需要包含a.h的文件当中定义宏AAA,但是我要说的是<br />
在同一个工程的不同的需要包含a.h的文件当中,你只能定义AAA一次,否则在连接这些目标文件时会出现<br />
重复定义的错误,即使你的单独目标文件编译没有任何的问题.<br />
</span><br />
<span style="color: #009902;">当然,这里说的仅仅是对全局变量的声明技巧,强烈的推介大家在头文件中使用宏定义实现对整个头文件的防止重复包含,当然了,这个技巧大多数的c语言程序员都懂.<br />
#ifndef XXX<br />
#define XXX<br />
<br />
#endif</span><br />
<span style="color: #009902;">这样做会让你的程序更加稳健,很大程度上减少了不必要的麻烦...</span><br />
<br />
最后给出一点点全局变量使用需要注意的问题,这也仅仅是个建议,或者说一种编程习惯 ;)<br />
1) 所有全局变量全部以g_开头,并且尽可能声明成static类型. <br />
2) 尽量杜绝跨文件访问全局变量.如果的确需要在多个文件内访问同一变量,应该由该变量定义所在文件内提供GET/PUT函数实现. <br />
3) 全局变量必须要有一个初始值,全局变量尽量放在一个专门的函数内初始化. <br />
4) 如调用的函数少于三个,请考虑改为局部变量实现. <br />
<br style="color: #80ffff;" />
<span style="color: #ff9902;">如果文中有什么不对的地方,欢迎指正,相互学习:)<br />
原文：http://blogold.chinaunix.net/u2/75758/showart_1715158.html<br />
</span>
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/345734.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2011-03-04 17:03 <a href="http://www.blogjava.net/jasmine214--love/archive/2011/03/04/345734.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从c文件源码中熟悉C－－整理１</title><link>http://www.blogjava.net/jasmine214--love/archive/2010/12/28/341801.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Tue, 28 Dec 2010 09:40:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2010/12/28/341801.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/341801.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2010/12/28/341801.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/341801.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/341801.html</trackback:ping><description><![CDATA[<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:PunctuationKerning/>
<w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing>
<w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
<w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:Compatibility>
<w:SpaceForUL/>
<w:BalanceSingleByteDoubleByteWidth/>
<w:DoNotLeaveBackslashAlone/>
<w:ULTrailSpace/>
<w:DoNotExpandShiftReturn/>
<w:AdjustLineHeightInTable/>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:UseFELayout/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
</w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles deflockedstate="false" latentstylecount="156">
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:普通表格;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:"Times New Roman";
mso-ansi-language:#0400;
mso-fareast-language:#0400;
mso-bidi-language:#0400;}
</style>
<![endif]-->
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">第一，<span class="pmemo"><span lang="EN-US">#define</span></span>宏定义，<span lang="EN-US"><span>&nbsp; </span></span><span style="color: red;">语法：<strong><span lang="EN-US">#define </span>语义名 代号名，</strong></span><span class="pmemo"><span lang="EN-US">#define</span>为<span style="color: red;">预编译处理命令</span>，主要定义常量，此常量可以为任何的字符及其组合，在编译之前，将此常量出现的所有位置，用其代表的字符或字符组合无条件
的替换，然后进行编译。</span><span lang="EN-US">#define CE_STT_FALSE ( 0 )</span>。</span></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-size: 10pt; font-family: 宋体; color: white; background: none repeat scroll 0% 0% blue;">条件编译：<span lang="EN-US">#ifndef</span>、（或者<span lang="EN-US">#ifndef)</span>、<span lang="EN-US">#def</span>、<span lang="EN-US">#endif</span>等宏这几个宏是为了进行条件编译。</span><span style="font-size: 10pt; font-family: 宋体;">一般情况下，源程序中 所有的行都参加编译。但是有时希望对其中一部分内容只在满足一定条件才进行编译，也就是对一部分内容指定编译的条件，这就是<span lang="EN-US">&#8220;</span>条件编译<span lang="EN-US">&#8221;</span>。有时，希望当满 足某条件时对一组语句进行编译，而当条件不满足时则编译另一组语句。</span></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-size: 10pt; font-family: 宋体; color: red;" lang="EN-US">#ifdef SINGLE_PROCESS</span></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-size: 10pt; font-family: 宋体; color: red;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>#define main(x) main_timer(x)</span></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-size: 10pt; font-family: 宋体; color: red;" lang="EN-US">#endif</span></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-size: 10pt; font-family: 宋体;">有人会问：不用条件编译命令而直接用<span lang="EN-US">if</span>语句也能达到要求，用条件编译命令有什么好处呢？的确，此问题完全可以不用条件编
译处理，但那样做目标程序长（因为所有语句都编译），而采用条件编译，可以减少被编译的语句，从而减少目标的长度。当条件编译段比较多时，目标程序长度可 以大大减少。</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">第二，<span class="pmemo"><span lang="EN-US">typedef</span></span>类型重命名：为了更加见名知义 ，<strong><span style="color: red;">语法：<span lang="EN-US">typedef </span>原类型 目标类型，</span></strong><span class="pmemo"><span lang="EN-US">typedef</span>是为已知数据类型增加一个新名称，其原理与使用<span lang="EN-US">int double</span>等保留字一致。</span></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">typedef struct</span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">{</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>UCHAR addr[MAC_ADDR_LEN];</span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">}MAC_ADDR;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">第三，导入头文件到<span lang="EN-US">.c</span>文件中：</span></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">#include "sys_common.h"</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">第四，<span lang="EN-US">static </span>变量和静态函数，</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">在<span lang="EN-US">C</span>中<span lang="EN-US"> static</span>有了第二种含义：用来表示不能被其它文件访问的全局变量和函数。但为了限制全局变量<span lang="EN-US">/</span>函数的作用域<span lang="EN-US">, </span>函数或变量前加<span lang="EN-US">static</span>使得函数成为静态函数。但此处<span lang="EN-US">&#8220;static&#8221;</span>的含义不是指存储方式，而是指对函数的作用域仅局限于本文件<span lang="EN-US">(</span>所以又称内部函
数<span lang="EN-US">)</span>。注意此时<span lang="EN-US">, </span>对于外部<span lang="EN-US">(</span>全局<span lang="EN-US">)</span>变量<span lang="EN-US">, </span>不论是否有<span lang="EN-US">static</span>限制<span lang="EN-US">, </span>它的存储区域都是在静态存储区<span lang="EN-US">, </span>生存期都是全局的<span lang="EN-US">. </span>此时的<span lang="EN-US">static</span>只是起作用域限制作用<span lang="EN-US">, </span>限定作用域在本模块<span lang="EN-US">(</span>文件<span lang="EN-US">)</span>内部<span lang="EN-US">.<br />
</span>使用内部函数的好处是：不同的人编写不同的函数时，不用担心自己定 义的函数，是否会与其它文件中的函数同名。</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">第五，条件语句的使用。常量值放在前面做比较的时候</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">if
(<span style="color: red;">SYS_OK</span> != ret)</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>DHCPRELAY_LOG("HAL_SendPacket
failed. ret= %d\n", (INT)ret);</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">第六，<span lang="EN-US">enum</span>枚举，在使用枚举变量时，主要关心的不是它的值的大小，而是其表示的状 态。在实际应用中，有的变量只有几种可能取值。如人的性别只有两种可能取值，星期只<span lang="EN-US"><br />
</span>有七种可能取值。在<span lang="EN-US"> C </span>语言中对这样取值比较特殊的变量可以定义为枚举类型。所谓枚举<span lang="EN-US"><br />
</span>是指将变量的值一一列举出来，变量只限于列举出来的值的范围内取值。<span lang="EN-US"> <br />
</span>定义 一个变量是枚举类型，可以先定义一个枚举类型名，然后再说明这个变量是该枚<span lang="EN-US"><br />
</span>举类型。</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">例如：<span lang="EN-US"> <br />
enum weekday{sun,mon,tue,wed,thu,fri,sat}</span>；</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">typedef
enum</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">{</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>DHCPV6_IF_FORMAT_NORMAL,</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>DHCPV6_IF_FORMAT_CTC,</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">}
DHCPV6_IF_FORMAT_E;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">第七，<span lang="EN-US">break </span>用法。<span style="color: blue;" lang="EN-US">continue</span><span style="color: black;">值 结束本次循环<span lang="EN-US">,</span>而不是中止整个循环的执行<span lang="EN-US">.</span>而</span><span style="color: blue;" lang="EN-US">break</span><span style="color: black;">语句则是结束整个循环过 程<span lang="EN-US">,</span>不再判断循环条件是否成立<span lang="EN-US">.</span></span></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp; </span>switch(level)</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>case CLI_LEVEL_PUBLIC:</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pPwd = "public";</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>break;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>&#8230;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">第八，<span lang="EN-US">extern</span>，<span lang="EN-US">extern</span>可以置于变量或者<span style="color: red;">函数</span>前，以标示变量或者函数的定义在别的文件中，提示编译器遇到此变量和函数时在其他模块中寻找其定义。</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">extern
GT_STATUS swSetForceSpeed</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">(</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>IN GT_LPORT <span>&nbsp;&nbsp;&nbsp; </span>port,</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>IN<span>&nbsp; </span>GT_PORT_FORCED_SPEED_MODE<span>&nbsp; </span>mode</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">);</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">第九，<span lang="EN-US">return o ;</span>的使用，正常退出。<span style="color: red;">只要一个函数的返回值是数字型的<span lang="EN-US">,</span>那么就可以返回<span lang="EN-US">0(</span>即<span lang="EN-US">return&nbsp;0),</span>其实你返回多少都没问
题。一般情况 下，<span lang="EN-US">C++</span>做出来的函数都要求返回一个值，当函数执行正常，且达到了一般情况下的目的，那么就返回<span lang="EN-US">0</span>表示正确的调用了该函数，这个<span lang="EN-US">0</span>就是返回给主调函数以 通知没有出错的；如果函数调用中出错，或者没有按照一般情况执行，那么就返回<span lang="EN-US">1</span>，以告知主调函数采取响应策略；</span></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">INT
main(void)</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">{</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>VOS_ApplStart("cli",</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&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; </span>APPL_CLI,</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&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; </span>CLI_Init,</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&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; </span>CLI_MsgHandle,</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&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; </span>CLI_Destroy);<span>&nbsp; </span></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span><span style="color: red;">return 0;</span></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">}</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">.</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">第十，三元表达式，可见三元运算符比<span lang="EN-US"> if (){}else{} </span>快一些<span lang="EN-US">&nbsp;</span></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">一元运算符，<span lang="EN-US">~ ! <br />
</span>二元运算符，<span lang="EN-US"> + - * / % <br />
</span>三元运算符<span lang="EN-US"> ?:</span></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">return
(NULL == pListNode)?NULL:(TIMER_DATA_T *)(pListNode-&gt;data);</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: 宋体;">第十一，打印输出，</span><span>-</span><span style="font-family: 宋体;">代表左对齐</span><span style="font-family: 宋体;">；</span><span>5</span><span style="font-family: 宋体;">表示</span><span> </span><span style="font-family: 宋体;">不足</span><span>5</span><span style="font-family: 宋体;">位输出</span><span><span>&nbsp; </span></span><span style="font-family: 宋体;">补足五位数；</span><span>l</span><span style="font-family: 宋体;">表示</span><span>long</span><span style="font-family: 宋体;">型</span><span><span>&nbsp;&nbsp; </span>u</span><span style="font-family: 宋体;">表示无符号</span></p>
<pre><span style="font-size: 10pt;" lang="EN-US">\r</span><span style="font-size: 10pt;">表示回车，即光标回车当前行首</span></pre>
<pre><span style="font-size: 10pt;" lang="EN-US">\n</span><span style="font-size: 10pt;">表示回车换行，即光标前进到下一行的行首</span></pre>
<pre><span style="font-size: 10pt;" lang="EN-US">\0</span><span style="font-size: 10pt;">是字符串结束标志（空字符），在字符数组中遇到它就表示前面的字符串到些为止。</span></pre>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">printf("%-5lu
%-5x %-4lu %-11lu<span>&nbsp; </span>%-10lu\r\n",</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pTimerData-&gt;timerId, </span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pTimerData-&gt;applyAppl,</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pTimerData-&gt;arg,</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pTimerData-&gt;interval,</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pTimerData-&gt;remainTicks);</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">JAVA-------------System.out.println(sort.getSortName());</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">第十二，数组，一维数组可以使用二维数组的写法<span lang="EN-US">{{}</span>，<span lang="EN-US">{}}</span>。</span></p>
<p class="MsoNormal"><span style="color: #009900;" lang="EN-US">char
a[][5]={{'B','A','S','I','C',},{'d','B','A','S','E'}};</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">static
CLI_CMD_T g_CliCmdTable[] =</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">{</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>{"timer print",
"timer\nprint timer", cli_TimerPrint, CLI_LEVEL_DEBUG}</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">};</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">第十三，<span lang="EN-US">sizeof</span>作用，<span lang="EN-US">s</span></span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">izeof </span><span style="font-size: 12pt; font-family: 宋体;">一般形式为：<span lang="EN-US">sizeof</span>（<span lang="EN-US">object</span>），也可以<span lang="EN-US">sizeof var_char,</span>不过大部分<span lang="EN-US">programer</span>习惯用<span lang="EN-US">sizeof()</span>。</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 12pt; font-family: 宋体;">对象可以是表达式或者数据类型名，当对象是表达式时，括号可省略。<span lang="EN-US">sizeof</span>是单目运算符，其运算符的含义是：<span style="color: red;">求出对象在计算机内存中所占用的字节数。</span>
一般来讲，不同的机器，运行不同的对象是不一样的，当目前几乎所有的机器都是<span lang="EN-US">32</span>位，很少<span lang="EN-US">16</span>位的，所以一般考试都是基于<span lang="EN-US">32</span>位的<span lang="EN-US">window</span>和<span lang="EN-US"> linux</span>的。</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">return
CLI_RegCmd("Timer", VIEW_NODE, g_CliCmdTable, <span style="color: red;">sizeof</span>(g_CliCmdTable));</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">第十四，条件语句，<span lang="EN-US">case </span>内嵌套<span lang="EN-US">if </span>表达式及<span lang="EN-US">break</span>的组合使用。</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">case
MSG_TIMER_STOP:</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>TIMER_ID *pTimerId;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pTimerId = (TIMER_ID *)pData;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">&nbsp;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if
(timer_ApplIdMatchingCheck(*pTimerId, srcAppl - VOS_TASK_MAX_NUM) == TRUE)</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ret = timer_Stop(*pTimerId);</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if (SYS_OK != ret)</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>//printf("%s:timer_Stop failed, ret[%lu]\r\n", __FUNCTION__,
ret);</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;</span>}</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>else</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ret =
TIMER_ERR_APPLID_UNMATCHED;</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>VOS_SyncMsgResponse(srcAppl,
MSG_TIMER_STOP, (VOID *)&amp;ret, sizeof(SYS_ERR_TYPE));</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: red;"><span>&nbsp;</span>break;</span></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><br />
</span></p>
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/341801.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2010-12-28 17:40 <a href="http://www.blogjava.net/jasmine214--love/archive/2010/12/28/341801.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux下C语言编程基础(Makefile)[转CU]</title><link>http://www.blogjava.net/jasmine214--love/archive/2010/12/28/341800.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Tue, 28 Dec 2010 09:30:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2010/12/28/341800.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/341800.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2010/12/28/341800.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/341800.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/341800.html</trackback:ping><description><![CDATA[<font class="f14"><span class="myp111"><font>假设我们有下面这样的一个程序，源代码如下： <br />
<br />
<table width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td style="font-size: 9pt;" class="code" bgcolor="#e6e6e6">
            <pre>/* main.c */ <br />
            <br />
            #include "mytool1.h" <br />
            <br />
            #include "mytool2.h" <br />
            <br />
            int main(int argc，char **argv) <br />
            <br />
            { <br />
            <br />
            mytool1_print("hello")； <br />
            <br />
            mytool2_print("hello")； <br />
            <br />
            } <br />
            <br />
            /* mytool1.h */ <br />
            <br />
            #ifndef _MYTOOL_1_H <br />
            <br />
            #define _MYTOOL_1_H <br />
            <br />
            void mytool1_print(char *print_str)； <br />
            <br />
            #endif <br />
            <br />
            /* mytool1.c */ <br />
            <br />
            #include "mytool1.h" <br />
            <br />
            void mytool1_print(char *print_str) <br />
            <br />
            { <br />
            <br />
            printf("This is mytool1 print %s "，print_str)； <br />
            <br />
            } <br />
            <br />
            /* mytool2.h */ <br />
            <br />
            #ifndef _MYTOOL_2_H <br />
            <br />
            #define _MYTOOL_2_H <br />
            <br />
            void mytool2_print(char *print_str)； <br />
            <br />
            #endif <br />
            <br />
            /* mytool2.c */ <br />
            <br />
            #include "mytool2.h" <br />
            <br />
            void mytool2_print(char *print_str) <br />
            <br />
            { <br />
            <br />
            printf("This is mytool2 print %s "，print_str)； <br />
            <br />
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
当然由于这个程序很短，我们可以这样来编译: <br />
<br />
<table width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td style="font-size: 9pt;" class="code" bgcolor="#e6e6e6">
            <pre>gcc -c main.c <br />
            <br />
            gcc -c mytool1.c <br />
            <br />
            gcc -c mytool2.c <br />
            <br />
            gcc -o main main.o mytool1.o mytool2.o</pre>
            </td>
        </tr>
    </tbody>
</table>
</font>
<p><font> </font></p>
<p><font> <span class="myp111"><font>这
样的话我们也可以产生main程序，而且也不是很麻烦。但是如果我们考虑一下如果有一天我们修改了其中的一个文件(比如说mytool1.c)那么我们难
道还要重新输入上面的命令?也许你会说，这个很容易解决啊，我写一个
SHELL脚本，让它帮我去完成不就可以了。是的对于这个程序来说，是可以起到作用的。但是当我们把事情想的更复杂一点，如果我们的程序有几百个源程序的
时候，难道也要编译器重新一个一个的去编译? <br />
<br />
为此，聪明的程序员们想出了一个很好的工具来做这件事情，这就是make。我们只要执行
以下make，就可以把上面的问题解决掉。在我们执行make之前，我们要先编写一个非常重要的文件。--Makefile。对于上面的那个程序来说，可
能的一个Makefile的文件是： <br />
<br />
# 这是上面那个程序的Makefile文件: <br />
<br />
<br />
<table width="400" align="center" border="1" cellpadding="2" cellspacing="0">
    <tbody>
        <tr>
            <td style="font-size: 9pt;" class="code" bgcolor="#e6e6e6">
            <pre>main：main.o mytool1.o mytool2.o <br />
            <br />
            gcc -o main main.o mytool1.o mytool2.o <br />
            <br />
            main.o：main.c mytool1.h mytool2.h <br />
            <br />
            gcc -c main.c <br />
            <br />
            mytool1.o：mytool1.c mytool1.h <br />
            <br />
            gcc -c mytool1.c <br />
            <br />
            mytool2.o：mytool2.c mytool2.h <br />
            <br />
            gcc -c mytool2.c</pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
有了这个Makefile文件，不论我们什么时候修改了源程序当中的什么文件，我们只要执行make命令，我们的编译器都只会去编译和我们修改的文件有关的文件，其它的文件它连理都不想去理的。 <br />
<br />
下面我们学习Makefile是如何编写的。 <br />
<br />
在Makefile中也#开始的行都是注释行.Makefile中最重要的是描述文件的依赖关系的说明。一般的格式是： <br />
<br />
target：components <br />
<br />
TAB rule <br />
<br />
第一行表示的是依赖关系。第二行是规则。 <br />
<br />
比如说我们上面的那个Makefile文件的第二行。 <br />
<br />
main：main.o mytool1.o mytool2.o <br />
<br />
表 示我们的目标(target)main的依赖对象(components)是main.o mytool1.omytool2.o
当倚赖的对象在目标修改后修改的话，就要去执行规则一行所指定的命令。就象我们的上面那个Makefile第三行所说的一样要执行 gcc-o main
main.o mytool1.o mytool2.o 注意规则一行中的TAB表示那里是一个TAB键 <br />
<br />
Makefile有三个非常有用的变量。分别是$@，$^，$&lt;代表的意义分别是： <br />
<br />
$@--目标文件，$^--所有的依赖文件，$&lt;--第一个依赖文件。 <br />
<br />
如果我们使用上面三个变量，那么我们可以简化我们的Makefile文件为： <br />
<br />
# 这是简化后的Makefile <br />
<br />
main：main.o mytool1.o mytool2.o <br />
<br />
gcc -o $@ $^ <br />
<br />
main.o：main.c mytool1.h mytool2.h <br />
<br />
gcc -c $&lt; <br />
<br />
mytool1.o：mytool1.c mytool1.h <br />
<br />
gcc -c $&lt; <br />
<br />
mytool2.o：mytool2.c mytool2.h <br />
<br />
gcc -c $&lt; <br />
<br />
经过简化后,我们的Makefile是简单了一点，不过人们有时候还想简单一点。这里我们学习一个Makefile的缺省规则 <br />
<br />
.c.o： <br />
<br />
gcc -c $&lt; <br />
<br />
这个规则表示所有的 .o文件都是依赖与相应的.c文件的。例如mytool.o依赖于mytool.c这样Makefile还可以变为： <br />
<br />
# 这是再一次简化后的Makefile <br />
<br />
main：main.o mytool1.o mytool2.o <br />
<br />
gcc -o $@ $^ <br />
<br />
.c.o： <br />
<br />
gcc -c $&lt; <br />
<br />
好了，我们的Makefile 也差不多了，如果想知道更多的关于Makefile的规则，可以查看相应的文档。 <br />
</font></span></font></p>
<p><font><span class="myp111"><font>原文：http://hi.baidu.com/mgqw/blog/item/2824bb01b72dfe067bec2c8c.html<br />
</font></span></font></p>
</span></font>
<p align="center"><font class="f14"><br />
</font></p>
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/341800.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2010-12-28 17:30 <a href="http://www.blogjava.net/jasmine214--love/archive/2010/12/28/341800.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C-sizeof解析</title><link>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339335.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Mon, 29 Nov 2010 09:13:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339335.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/339335.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339335.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/339335.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/339335.html</trackback:ping><description><![CDATA[<div>只要参加软件研发的笔试（C/C++)几乎都会涉及到sizeof()的用法，我昨天也遇到了，有的也会，但是真正sizeof()的核心还是
没有领会，今天上网，无聊中就看到了详细的sizeof()的阐述，现在分享给大家。</div>
<div>－－－－－－－－－－－－<strong><font color="#ff0000" face="Arial Black" size="6">sizeof</font></strong>－－－－－－－－－－－－－－－－</div>
<div>sizeof 一般形式为：sizeof（object），也可以sizeof
var_char,不过大部分programer习惯用sizeof()。</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;
对象可以是表达式或者数据类型名，当对象是表达式时，括号可省略。sizeof是单目运算符，其运算符的含义是：求出对象在计算机内存中所占用的字节数。
一般来讲，不同的机器，运行不同的对象是不一样的，当目前几乎所有的机器都是32位，很少16位的，所以一般考试都是基于32位的window和
linux的。</div>
<div>C语言中数据类型不多。</div>
<div>1.整数型的：</div>
<div>short，int，long(我没有考虑符号问题),一般c语言书上讲，int是2个字节的，即16位，范围是
－32768－32767，long是4个字节，范围是－2^32---2^32-1。当时在xp上运行sizeof(int)的时候，会output
4.这就是32位的原因。sizeof（long）也是4.</div>
<div>如下:#include "stdio.h"<br />
#include "string.h"<br />
#include "stdlib.h"<br />
int
main()<br />
{<br />
&nbsp;short int sa=10;<br />
&nbsp;&nbsp; &nbsp;int a=10;<br />
&nbsp;&nbsp; &nbsp;long la=10;<br />
&nbsp;&nbsp;
&nbsp;float f = 20;<br />
&nbsp;&nbsp; &nbsp;double d=20;<br />
&nbsp;&nbsp; &nbsp;char ch='c';<br />
&nbsp;&nbsp; &nbsp;char
str[]="ABC";<br />
&nbsp;&nbsp; &nbsp;char *p=str;<br />
&nbsp;&nbsp; &nbsp;struct str{<br />
&nbsp;&nbsp;double d;<br />
&nbsp;&nbsp;char
ch;<br />
&nbsp;&nbsp;int data;<br />
&nbsp;}str_wu;<br />
&nbsp;struct str1{<br />
&nbsp;&nbsp;char ch;<br />
&nbsp;&nbsp;double
d;<br />
&nbsp;&nbsp;int data;<br />
&nbsp;}str_wu1;<br />
&nbsp;&nbsp;
&nbsp;printf("sizeof(short):%d\n",sizeof(sa));<br />
&nbsp;printf("sizeof(int):%d\n",sizeof(a));<br />
&nbsp;&nbsp;
&nbsp;printf("sizeof(long):%d\n",sizeof(la));<br />
&nbsp;&nbsp;
&nbsp;printf("sizeof(float):%d\n",sizeof(f));<br />
&nbsp;&nbsp;
&nbsp;printf("sizeof(double):%d\n",sizeof(d));<br />
&nbsp;&nbsp;
&nbsp;printf("sizeof(char):%d\n",sizeof(ch));<br />
&nbsp;&nbsp;
&nbsp;printf("sizeof(string):%d\n",sizeof(str));<br />
&nbsp;&nbsp; &nbsp;printf("sizeof(point
address):%d\n",sizeof(p));<br />
&nbsp;&nbsp;
&nbsp;printf("sizeof(Point):%d\n",sizeof(*p));<br />
&nbsp;&nbsp;
&nbsp;printf("sizeof(Struct):%d\n",sizeof(str_wu));<br />
&nbsp;&nbsp;
&nbsp;printf("sizeof(Struct):%d\n",sizeof(str_wu1));<br />
&nbsp;&nbsp; &nbsp;system("pause");<br />
}</div>
<div><img onload="if(this.width  alt="" />650) this.width=650;" onclick='window.open("http://blog.51cto.com/viewpic.php?refimg=" +
this.src)' alt="" src="http://img1.51cto.com/attachment/200810/200810211224596908046.jpg" border="0"></div>
<div>因而int，short的sizeof结果是一样的额。</div>
<div>2.浮点型数据</div>
<div>float，double，long double</div>
<div>上边的图，long double 没有测试（忘了。。。。。）呵呵！</div>
<div>但是应该是16。</div>
<div>3。指针</div>
<div>对于指针，要特别区分，指针指向什么数据，它在内存占的字节数才是它的结果。</div>
<div>比如：指针指向一个字符串，就是字符串的长度，因为一个字符在内存中占一个字节。若指针指向一个数据结构，则结果应该是结构型数据的内存字节
数。</div>
<div>4。结构类型</div>
<div>在上面的程序中，</div>
<div align="left"><strong><font size="3">struct str{<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;
double d;<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;char ch;<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;
int data;<br />
&nbsp;}str_wu;<br />
&nbsp;struct str1{<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;
char ch;<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; double d;<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;
int data;<br />
&nbsp;}str_wu1;<br />
</font></strong><br />
两个不同的结构，但是内部的元素是相同的，都是
double，int，char，只是顺序不一样，就结果不一样。why？</div>
<div align="left">这时因为VC存储数据的时候要对其，具体的情况如下：</div>
<div align="left"><font style="background-color: #ffffff;">类型<br />
<font color="#ff0000">对齐方式（变量存放的起始地址相对于结构的起始地址的偏移量） </font></font></div>
<div><font style="background-color: #ffffff;" color="#ff0000">
Char<br />
偏移量必须为sizeof(char)即1的倍数 </font></div>
<div><font style="background-color: #ffffff;" color="#ff0000">
int <br />
偏移量必须为sizeof(int)即4的倍数 </font></div>
<div><font style="background-color: #ffffff;" color="#ff0000">
float<br />
偏移量必须为sizeof(float)即4的倍数 </font></div>
<div><font style="background-color: #ffffff;" color="#ff0000">
double<br />
偏移量必须为sizeof(double)即8的倍数 </font></div>
<div><font style="background-color: #ffffff;" color="#ff0000">
Short<br />
偏移量必须为sizeof(short)即2的倍数 </font></div>
<div><font color="#0000ff">比如：str_wu，为上面的结构分配空间的时候，VC根据成员变量出现的顺序和对齐方式，先为
第一个成员dda1分配空间，其起始地址跟结构的起始地址相同（刚好偏移量0刚好为sizeof(double)的倍数），该成员变量占用
sizeof(double)=8个字节；接下来为第二个成员dda分配空间，这时下一个可以分配的地址对于结构的起始地址的偏移量为8，是
sizeof(char)的倍数，所以把dda存放在偏移量为8的地方满足对齐方式，该成员变量占用sizeof(char)=1个字节；接下来为第三个
成员type分配空间，这时下一个可以分配的地址对于结构的起始地址的偏移量为9，不是sizeof(int)=4的倍数，为了满足对齐方式对偏移量的约
束问题，VC自动填充3个字节（这三个字节没有放什么东西），这时下一个可以分配的地址对于结构的起始地址的偏移量为12，刚好是
sizeof(int)=4的倍数，所以把type存放在偏移量为12的地方，该成员变量占用sizeof(int)=4个字节；这时整个结构的成员变量
已经都分配了空间，总的占用的空间大小为：8+1+3+4=16，刚好为结构的字节边界数（即结构中占用最大空间的类型所占用的字节数
sizeof(double)=8）的倍数，所以没有空缺的字节需要填充。所以整个结构的大小为：sizeof(str_wu)=8+1+3+4=16，
其中有3个字节是VC自动填充的，没有放任何有意义的东西。 </font></div>
<div><font color="#ff0000" size="4">而str_wu1，同样的道理：如下：sizeof(char)=1,而1不
是8的倍数，因而增加到8，sizeof（double）＝8，现在开始地址是16，16是sizeof（int)的倍数，可以存入。</font></div>
<div><font color="#ff0000" size="4">因而总的地址
数：sizeof（char）＋7＋sizeof（double）＋sizeof（int）＝20，</font></div>
<div><font color="#ff0000" size="4">而20不是8的倍数（sizeof(double)=8),所以需要在增加4
个地址，即总共24。</font></div>
<div><font color="#000000" size="4">－－－－－－－－－－－－－－－－－－－－－－</font></div>
<div><font color="#000000" size="4">sizeof具体的，我所知道的就这些了，那位高手还知道什么，或者我写的有
什么错，希望指出。谢谢！<br />
原文； http://lemonmilk.blog.51cto.com/499577/107155<br />
</font></div>
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/339335.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2010-11-29 17:13 <a href="http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339335.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于C语言中return的一些总结 </title><link>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339321.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Mon, 29 Nov 2010 07:51:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339321.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/339321.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339321.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/339321.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/339321.html</trackback:ping><description><![CDATA[<br />
return是C++预定义的语句，它提供了种植函数执行的一种放大。当return语句提供了一个值时，
这个值就成为函数的返回值.&nbsp;<br />
说到return,有必要提及主函数的定义,下面是从网络上找到的资料,好好消化吧,对了解主函数中返回值的理解有
很大的帮助.&nbsp;<br />
很多人甚至市面上的一些书籍，都使用了void&nbsp;main(&nbsp;)&nbsp;，其实这是错误的。C/C++&nbsp;中从来没有定义过
void&nbsp;main(&nbsp;)&nbsp;。C++&nbsp;之父&nbsp;Bjarne&nbsp;Stroustrup&nbsp;在他的主页上的&nbsp;FAQ&nbsp;中明确地写
着&nbsp;The&nbsp;definition&nbsp;void&nbsp;main(&nbsp;)&nbsp;{&nbsp;/*&nbsp;...&nbsp;*
/&nbsp;}&nbsp;is&nbsp;not&nbsp;and&nbsp;never&nbsp;has&nbsp;been&nbsp;C++,&nbsp;nor&nbsp;has&nbsp;it&nbsp;even&nbsp;been&nbsp;C.
（&nbsp;void&nbsp;main(&nbsp;)&nbsp;从来就不存在于&nbsp;C++&nbsp;或者&nbsp;C&nbsp;）。下面我分别说一下&nbsp;C&nbsp;和&nbsp;C++&nbsp;标准中对&nbsp;main&nbsp;函数的定义。&nbsp;<br />
1.&nbsp;C&nbsp;<br />
在&nbsp;C89&nbsp;中，main(&nbsp;)&nbsp;是
可以接受的。Brian&nbsp;W.&nbsp;Kernighan&nbsp;和&nbsp;Dennis&nbsp;M.&nbsp;Ritchie&nbsp;的经典巨
著&nbsp;The&nbsp;C&nbsp;programming&nbsp;Language&nbsp;2e（《C&nbsp;程序设计语言第二版》）用的就是&nbsp;main(&nbsp;)。不过在最新的&nbsp;C99&nbsp;标准
中，只有以下两种定义方式是正确的：&nbsp;<br />
int&nbsp;main(&nbsp;void&nbsp;)&nbsp;<br />
int&nbsp;main(&nbsp;int&nbsp;argc,&nbsp;char&nbsp;*argv[]&nbsp;)&nbsp;<br />
（参
考资
料：ISO/IEC&nbsp;9899:1999&nbsp;(E)&nbsp;Programming&nbsp;languages&nbsp;—&nbsp;C&nbsp;5.1.2.2.1&nbsp;Program&nbsp;startup）&nbsp;<br />
当
然，我们也可以做一点小小的改动。例如：char&nbsp;*argv[]&nbsp;可以写成&nbsp;char&nbsp;**argv；argv&nbsp;和&nbsp;argc&nbsp;可以改成别的变量名
（如&nbsp;intval&nbsp;和&nbsp;charval），不过一定要符合变量的命名规则。&nbsp;<br />
如果不需要从命令行中获取参数，请用
int&nbsp;main(void)&nbsp;；否则请用int&nbsp;main(&nbsp;int&nbsp;argc,&nbsp;char&nbsp;*argv[]&nbsp;)&nbsp;。&nbsp;<br />
main&nbsp;函数的返回值
类型必须是&nbsp;int&nbsp;，这样返回值才能传递给程序的激活者（如操作系统）。&nbsp;<br />
如果&nbsp;main&nbsp;函数的最后没有写&nbsp;return&nbsp;语句的
话，C99&nbsp;规定编译器要自动在生成的目标文件中（如&nbsp;exe&nbsp;文件）加入return&nbsp;0;&nbsp;，表示程序正常退出。不过，我还是建议你最好在main函
数的最后加上return&nbsp;语句，虽然没有这个必要，但这是一个好的习惯。注意，vc6不会在目标文件中加入return&nbsp;0;&nbsp;，大概是因
为&nbsp;vc6&nbsp;是&nbsp;98&nbsp;年的产品，所以才不支持这个特性。现在明白我为什么建议你最好加上&nbsp;return&nbsp;语句了吧！不过，gcc3.2（Linux&nbsp;下
的&nbsp;C&nbsp;编译器）会在生成的目标文件中加入&nbsp;return&nbsp;0;&nbsp;。&nbsp;<br />
<br />
2.&nbsp;C++&nbsp;<br />
C++98&nbsp;中定义了如下两
种&nbsp;main&nbsp;函数的定义方式：&nbsp;<br />
int&nbsp;main(&nbsp;)&nbsp;<br />
int&nbsp;main(&nbsp;int&nbsp;argc,&nbsp;char&nbsp;*argv[]&nbsp;)&nbsp;<br />
（参
考资
料：ISO/IEC&nbsp;14882(1998-9-01)Programming&nbsp;languages&nbsp;—&nbsp;C++&nbsp;3.6&nbsp;Start&nbsp;and&nbsp;termination）&nbsp;<br />
int&nbsp;main(&nbsp;)&nbsp;等
同于&nbsp;C99&nbsp;中的&nbsp;int&nbsp;main(&nbsp;void&nbsp;)&nbsp;；int&nbsp;main(&nbsp;int&nbsp;argc,&nbsp;char&nbsp;*argv[]&nbsp;)&nbsp;的用法也
和&nbsp;C99&nbsp;中定义的一样。同样，main&nbsp;函数的返回值类型也必须是int。如果main函数的末尾没写return语句，C++98&nbsp;规定编译器要自
动在生成的目标文件中加入&nbsp;return&nbsp;0;&nbsp;。同样，vc6&nbsp;也不支持这个特性，但是&nbsp;g++3.2（Linux&nbsp;下的&nbsp;C++&nbsp;编译器）支持。&nbsp;<br />
<br />
3.&nbsp;关
于&nbsp;void&nbsp;main&nbsp;<br />
在&nbsp;C&nbsp;和&nbsp;C++&nbsp;中，不接收任何参数也不返回任何信息的函数原型为&#8220;void&nbsp;foo(void);&#8221;。可能正是因
为这个，所以很多人都误认为如果不需要程序返回值时可以把main函数定义成void&nbsp;main(void)&nbsp;。然而这是错误的！main&nbsp;函数的返回值
应该定义为&nbsp;int&nbsp;类型，C&nbsp;和&nbsp;C++&nbsp;标准中都是这样规定的。虽然在一些编译器中，void&nbsp;main&nbsp;可以通过编译（如&nbsp;vc6），但并非所有编
译器都支持&nbsp;void&nbsp;main&nbsp;，因为标准中从来没有定义过&nbsp;void&nbsp;main&nbsp;。g++3.2&nbsp;中如果&nbsp;main&nbsp;函数的返回值不是&nbsp;int&nbsp;类
型，就根本通不过编译。而&nbsp;gcc3.2&nbsp;则会发出警告。所以，如果你想你的程序拥有很好的可移植性，请一定要用&nbsp;int&nbsp;main&nbsp;。&nbsp;<br />
<br />
4.&nbsp;返
回值的作用&nbsp;<br />
main&nbsp;函数的返回值用于说明程序的退出状态。如果返回&nbsp;0，则代表程序正常退出，否则代表程序异常退出。下面我们
在&nbsp;winxp&nbsp;环境下做一个小实验。首先编译下面的程序：&nbsp;<br />
int&nbsp;main(&nbsp;void&nbsp;)&nbsp;<br />
{&nbsp;<br />
return&nbsp;0;&nbsp;<br />
}&nbsp;<br />
然
后打开附件里的&#8220;命令提示符&#8221;，在命令行里运行刚才编译好的可执行文件，然后输入&#8220;echo&nbsp;%ERRORLEVEL%&#8221;，回车，就可以看到程序的返回值
为&nbsp;0&nbsp;。假设刚才编译好的文件是&nbsp;a.exe&nbsp;，如果输入&#8220;a&nbsp;&amp;&amp;&nbsp;dir&#8221;，则会列出当前目录下的文件夹和文件。但是如果改成
&#8220;return&nbsp;-1&#8221;，或者别的非&nbsp;0&nbsp;值，重新编译后输入&#8220;a&nbsp;&amp;&amp;&nbsp;dir&#8221;，则&nbsp;dir&nbsp;不会执行。因
为&nbsp;&amp;&amp;&nbsp;的含义是：如果&nbsp;&amp;&amp;&nbsp;前面的程序正常退出，则继续执行&nbsp;&amp;&amp;&nbsp;后面的程序，否则不执行。也
就是说，利用程序的返回值，我们可以控制要不要执行下一个程序。这就是&nbsp;int&nbsp;main&nbsp;的好处。如果你有兴趣，也可以把&nbsp;main&nbsp;函数的返回值类型
改成非&nbsp;int&nbsp;类型（如&nbsp;float），重新编译后执行&#8220;a&nbsp;&amp;&amp;&nbsp;dir&#8221;，看看会出现什么情况，想想为什么会出现那样的情况。顺便
提一下，如果输入&nbsp;a&nbsp;||&nbsp;dir&nbsp;的话，则表示如果&nbsp;a&nbsp;异常退出，则执行&nbsp;dir&nbsp;。&nbsp;<br />
5.&nbsp;那
么&nbsp;intmain(intargc,char*argv[],char*envp[])呢？&nbsp;<br />
这当然也不是标准&nbsp;C&nbsp;里面定义的东
西！char*envp[]&nbsp;是某些编译器提供的扩展功能，用于获取系统的环境变量。因为不是标准，所以并非所有编译器都支持，故而移植性差，不推荐使
用。&nbsp;<br />
到了这里,你应该了解为什么主函数定义为&nbsp;int返回类型,而且函数体里面有return&nbsp;0;这个语句了吧.&nbsp;<br />
下面具体说说我对
return的应用的理解。&nbsp;<br />
<span style="color: red;">只要一个函数的返回值是数字型的,那么就可以返回0(即return&nbsp;0),其实你返回多少都没问题。一般情况
下，C++做出来的函数都要求返回一个值，当函数执行正常，且达到了一般情况下的目的，那么就返回0表示正确的调用了该函数，这个0就是返回给主调函数以
通知没有出错的；如果函数调用中出错，或者没有按照一般情况执行，那么就返回1，</span>以告知主调函数采取响应策略；如果你在某个函数所在类的定义所在的头文件
中定义了一组状态值（一般都是负整数），那么函数就可以返回不同的值以告之主调函数具体发生了什么异常或错误，这种情况一般用于函数功能独立性较差的的情
况。所以一般不鼓励把函数返回类型定义为void，至少返回应该是int，而在函数的最后加上return&nbsp;0.语句：&nbsp;<br />
int&nbsp;func(参数
列表)&nbsp;<br />
{&nbsp;<br />
&#8230;&#8230;&nbsp;<br />
&#8230;&#8230;&nbsp;<br />
&#8230;&#8230;&nbsp;<br />
Return&nbsp;0;&nbsp;<br />
}&nbsp;<br />
在函数中，如果碰到return&nbsp;语
句，那么程序就会返回调用该函数的下一条语句执行，也就是说跳出函数的执行，回到原来的地方继续执行下去。但是如果是在主函数中碰到return语句，那
么整个程序就会停止，退出程序的执行。&nbsp;<br />
如果你定义一个函数有返回类型，可以想下面那样调用：&nbsp;<br />
int&nbsp;func()&nbsp;<br />
{&nbsp;<br />
int&nbsp;value;&nbsp;<br />
&#8230;&#8230;&nbsp;<br />
&#8230;&#8230;&nbsp;<br />
&#8230;&#8230;&nbsp;<br />
return&nbsp;value;&nbsp;<br />
}&nbsp;<br />
int&nbsp;main()&nbsp;<br />
{&nbsp;<br />
int&nbsp;intvalue;&nbsp;<br />
intvalue=func();&nbsp;<br />
&#8230;&#8230;&nbsp;<br />
&#8230;&#8230;&nbsp;<br />
teturn&nbsp;0;&nbsp;<br />
}&nbsp;<br />
return
语句后面具体是什么内容，这就要具体情况具体分析了：&nbsp;<br />
（1）&nbsp;在返回类型是char的函数中，return后应该是char类型的值；&nbsp;<br />
（2）&nbsp;在
返回类型是int的函数中，如果是要停止函数的调用，最好应该为0；其他的按照你的目的而定，只要是int&nbsp;类型就行了&nbsp;<br />
（3）&nbsp;在返回类型是结
构类型的函数中，return后应该是结构的一个实例对象。&nbsp;<br />
总之，函数定义为什么样的返回类型，该函数中return后就应该是相应类型的值。<br />
原文； http://blog.pfan.cn/zean/21232.html<br />
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/339321.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2010-11-29 15:51 <a href="http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339321.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C -extern使用 </title><link>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339319.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Mon, 29 Nov 2010 07:29:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339319.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/339319.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339319.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/339319.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/339319.html</trackback:ping><description><![CDATA[<strong>1 基本解释<br />
<br />
</strong>　　extern可以置于变量或者函数前，以标示变量或者函数的定义在别的文件中，提示
编译器遇到此变量和函数时在其他模块中寻找其定义。<br />
<br />
另外，extern也可用来进行链接指定。<br />
<strong>2
问题：extern 变量</strong><br />
<br />
在一个源文件里定义了一个数组：<br />
<br />
<table width="90%" align="center" bgcolor="#e6e4dd" border="1" bordercolor="#ffcc66">
    <tbody>
        <tr>
            <td>char a[6];</td>
        </tr>
    </tbody>
</table>
<br />
在另外一个文件里用下列语句进行了声明：<br />
<br />
<table width="90%" align="center" bgcolor="#e6e4dd" border="1" bordercolor="#ffcc66">
    <tbody>
        <tr>
            <td>extern char *a；</td>
        </tr>
    </tbody>
</table>
<br />
请问，这样可以吗？ <br />
<br />
答
案与分析：<br />
<br />
1)、不可以，程序运行时会告诉你非法访问。原因在于，指向类型T的指针并不等价于类型T的数组。extern char
*a声明的是一个指针变量而不是字符数组，因此与实际的定义不同，从而造成运行时非法访问。应该将声明改为extern char a[ ]。<br />
<br />
2)、例子分析如下，如果a[] = "abcd",则外部变量a=0x61626364 (abcd的ASCII码值)，*a显然没有意义，如下图：<br />
<img alt="" src="file:///C:/DOCUME%7E1/arm/LOCALS%7E1/Temp/moz-screenshot.jpg" /><br />
<div align="center"><img src="http://blogimg.chinaunix.net/blog/upfile2/080506093605.gif" onload="javascript:if(this.width  alt="" />500)this.width=500;" width="500" border="0"></div>
显然a指向的空间（0x61626364）没有意义，易出现非法内存访问。<br />
&nbsp;
3)、在使用extern时候要严格对应声明时的格式，在实际编程中，这样的错误屡见不鲜。<br />
4)、extern用在变量声明中常常有这样一个
作用，你在*.c文件中声明了一个全局的变量，这个全局的变量如果要被引用，就放在*.h中并用extern来声明。<br />
<strong>3
问题：extern 函数1</strong><br />
<br />
常常见extern放在函数的前面成为函数声明的一部分，那么，C语言的关键字
extern在函数的声明中起什么作用？<br />
<br />
答案与分析：<br />
<br />
如果函数的声明中带有关键字extern，仅仅是暗示这个
函数可能在别的源文件里定义，没有其它作用。即下述两个函数声明没有明显的区别：<br />
<br />
<table width="90%" align="center" bgcolor="#e6e4dd" border="1" bordercolor="#ffcc66">
    <tbody>
        <tr>
            <td>extern int f(); 和int f();</td>
        </tr>
    </tbody>
</table>
<br />
当然，这样的用处还是有
的，就是在程序中取代include &#8220;*.h&#8221;来声明函数，在一些复杂的项目中，我比较习惯在所有的函数声明前添加extern修饰。<br />
<br />
<strong>4 问题：extern 函数2</strong><br />
<br />
当函数提供方单方面修改函数原型时，如果使用方不知情继续沿用
原来的extern申明，这样编译时编译器不会报错。但是在运行过程中，因为少了或者多了输入参数，往往会照成系统错误，这种情况应该如何解决？<br />
<br />
答案与分析：<br />
<br />
目前业界针对这种情况的处理没有一个很完美的方案，通常的做法是提供方在自己的xxx_pub.h中提供对外部接口的
声明，然后调用方include该头文件，从而省去extern这一步。以避免这种错误。<br />
<br />
宝剑有双锋，对extern的应用，不同的
场合应该选择不同的做法。<br />
<br />
<strong>5 问题：extern &#8220;C&#8221;</strong><br />
<br />
在C++环境下使
用C函数的时候，常常会出现编译器无法找到obj模块中的C函数定义，从而导致链接失败的情况，应该如何解决这种情况呢？<br />
<br />
答案与分
析：<br />
<br />
C++语言在编译的时候为了解决函数的多态问题，会将函数名和参数联合起来生成一个中间的函数名称，而C语言则不会，因此会造成
链接时找不到对应函数的情况，此时C函数就需要用extern &#8220;C&#8221;进行链接指定，这告诉编译器，请保持我的名称，不要给我生成用于链接的中间函数名。<br />
<br />
下面是一个标准的写法：<br />
<br />
//在.h文件的头上<br />
#ifdef __cplusplus<br />
#if __cplusplus<br />
extern "C"{<br />
#endif<br />
#endif /* __cplusplus */ <br />
&#8230;<br />
&#8230;<br />
//.h文件结束的地方<br />
#ifdef __cplusplus<br />
#if __cplusplus<br />
}<br />
#endif<br />
#endif /*
__cplusplus */<br />
<br />
原文； <strong>http://blog.chinaunix.net/u2/67661/showart_677178.html</strong><br />
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/339319.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2010-11-29 15:29 <a href="http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339319.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C-枚举</title><link>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339317.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Mon, 29 Nov 2010 07:10:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339317.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/339317.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339317.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/339317.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/339317.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在实际应用中，有的变量只有几种可能取值。如人的性别只有两种可能取值，星期只有七种可能取值。在 C语言中对这样取值比较特殊的变量可以定义为枚举类型。所谓枚举是指将变量的值一一列举出来，变量只限于列举出来的值的范围内取值。 定义一个变量是枚举类型，可以先定义一个枚举类型名，然后再说明这个变量是该枚举类型。例如： enumweekday{sun,mon,tue,wed,t...&nbsp;&nbsp;<a href='http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339317.html'>阅读全文</a><img src ="http://www.blogjava.net/jasmine214--love/aggbug/339317.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2010-11-29 15:10 <a href="http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339317.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C-static变量和函数</title><link>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339315.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Mon, 29 Nov 2010 06:51:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339315.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/339315.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339315.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/339315.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/339315.html</trackback:ping><description><![CDATA[<p>static关键字是C, C++中都存在的关键字, 它主要有三种使用方式, 其中前两种只指在C语言中使用,
第三种在C++中使用(C,C++中具体细微操作不尽相同, 本文以C++为准).<br />
(1)局部静态变量<br />
(2)外部静态变量/函数<br />
(3)
静态数据成员/成员函数</p>
<p>&nbsp;</p>
<p>下面就这三种使用方式及注意事项分别说明</p>
<p>&nbsp;</p>
<p>一、局部静态变量</p>
<p>&nbsp;</p>
<p>在C/C++中, 局部变量按照存储形式可分为三种auto, static, register<br />
(&lt;C语言程序设计(第二
版)&gt;谭浩强, 第174-175页)<br />
与auto类型(普通)局部变量相比, static局部变量有三点不同</p>
<p><br />
1. 存储空间分配不同<br />
auto类型分配在栈上, 属于动态存储类别, 占动态存储区空间, 函数调用结束后自动释放,
而static分配在静态存储区, 在程序整个运行期间都不释放. 两者之间的作用域相同, 但生存期不同.</p>
<p><br />
2. static局部变量在所处模块在初次运行时进行初始化工作, 且只操作一次</p>
<p><br />
3. 对于局部静态变量, 如果不赋初值, 编译期会自动赋初值0或空字符, 而auto类型的初值是不确定的.
(对于C++中的class对象例外, class的对象实例如果不初始化, 则会自动调用默认构造函数, 不管是否是static类型)<br />
特点:
static局部变量的&#8221;记忆性&#8221;与生存期的&#8221;全局性&#8221;<br />
所谓&#8221;记忆性&#8221;是指在两次函数调用时, 在第二次调用进入时,
能保持第一次调用退出时的值. </p>
<p>&nbsp;</p>
<p>示例程序一<br />
#include &lt;iostream&gt;<br />
using namespace std;<br />
void
staticLocalVar()<br />
{<br />
static int a = 0; // 运行期时初始化一次, 下次再调用时,
不进行初始化工作<br />
cout&lt;&lt;"a="&lt;&lt;a&lt;&lt;endl;<br />
++a;<br />
}<br />
int
main()<br />
{<br />
staticLocalVar(); // 第一次调用, 输出a=0<br />
staticLocalVar(); //
第二次调用, 记忆了第一次退出时的值, 输出a=1<br />
return 0;<br />
}</p>
<p>应用:<br />
利用&#8221;记忆性&#8221;, 记录函数调用的次数(示例程序一)<br />
利用生存期的&#8221;全局性&#8221;, 改善&#8221;return a pointer /
reference to a local object&#8221;的问题. Local object的问题在于退出函数, 生存期即结束,.
利用static的作用, 延长变量的生存期.</p>
<p>&nbsp;</p>
<p>示例程序二:<br />
// IP address to string format<br />
// Used in Ethernet Frame
and IP Header analysis<br />
const char * IpToStr(UINT32 IpAddr)<br />
{<br />
static
char strBuff[16]; // static局部变量, 用于返回地址有效<br />
const unsigned char *pChIP
= (const unsigned char *)&amp;IpAddr;<br />
sprintf(strBuff,
"%u.%u.%u.%u", pChIP[0], pChIP[1], pChIP[2], pChIP[3]);<br />
return
strBuff;<br />
}</p>
<p>注意事项:<br />
1. &#8220;记忆性&#8221;, 程序运行很重要的一点就是可重复性, 而static变量的&#8221;记忆性&#8221;破坏了这种可重复性,
造成不同时刻至运行的结果可能不同.<br />
2. &#8220;生存期&#8221;全局性和唯一性. 普通的local变量的存储空间分配在stack上,
因此每次调用函数时, 分配的空间都可能不一样, 而static具有全局唯一性的特点, 每次调用时, 都指向同一块内存, 这就造成一个很重要的问题
----不可重入性!!!<br />
这样在多线程程序设计或递归程序设计中, 要特别注意这个问题.<br />
(不可重入性的例子可以参
见&lt;effective C++ (2nd)&gt;(影印版)第103-105页)<br />
下面针对示例程序二,
分析在多线程情况下的不安全性.(为方便描述, 标上行号)<br />
① const char * IpToStr(UINT32 IpAddr)<br />
②
{<br />
③ static char strBuff[16]; // static局部变量, 用于返回地址有效<br />
④ const
unsigned char *pChIP = (const unsigned char *)&amp;IpAddr;<br />
⑤
sprintf(strBuff, "%u.%u.%u.%u", pChIP[0], pChIP[1], pChIP[2], pChIP[3]);<br />
⑥
return strBuff;<br />
⑦ }<br />
假设现在有两个线程A,B运行期间都需要调用IpToStr()函数,
将32位的IP地址转换成点分10进制的字符串形式. 现A先获得执行机会, 执行IpToStr(), 传入的参数是0x0B090A0A,
顺序执行完应该返回的指针存储区内容是:&#8221;10.10.9.11&#8221;, 现执行到⑥时, 失去执行权, 调度到B线程执行,
B线程传入的参数是0xA8A8A8C0, 执行至⑦, 静态存储区的内容是192.168.168.168. 当再调度到A执行时, 从⑥继续执行,
由于strBuff的全局唯一性, 内容已经被B线程冲掉, 此时返回的将是192.168.168.168字符串,
不再是10.10.9.11字符串.</p>
<p>&nbsp;</p>
<p>二、外部静态变量／函数</p>
<p>&nbsp;</p>
<p>在C中 static有了第二种含义：用来表示不能被其它文件访问的全局变量和函数。但为了限制全局变量/函数的作用域,
函数或变量前加static使得函数成为静态函数。但此处&#8220;static&#8221;的含义不是指存储方式，而是指对函数的作用域仅局限于本文件(所以又称内部函
数)。注意此时, 对于外部(全局)变量, 不论是否有static限制, 它的存储区域都是在静态存储区, 生存期都是全局的.
此时的static只是起作用域限制作用, 限定作用域在本模块(文件)内部.<br />
使用内部函数的好处是：不同的人编写不同的函数时，不用担心自己定
义的函数，是否会与其它文件中的函数同名。</p>
<p>&nbsp;</p>
<p>示例程序三:</p>
<p>//file1.cpp</p>
<p>static int varA;<br />
int varB;<br />
extern void funA()<br />
{<br />
&#8230;&#8230;<br />
}</p>
<p>static void funB()<br />
{<br />
&#8230;&#8230;<br />
}</p>
<p>//file2.cpp</p>
<p>extern int varB; // 使用file1.cpp中定义的全局变量<br />
extern int varA; // 错误!
varA是static类型, 无法在其他文件中使用<br />
extern vod funA(); // 使用file1.cpp中定义的函数<br />
extern
void funB(); // 错误! 无法使用file1.cpp文件中static函数</p>
<p>&nbsp;</p>
<p>三、静态数据成员／成员函数(C++特有)</p>
<p>&nbsp;</p>
<p>C+ +重用了这个关键字，并赋予它与前面不同的第三种含义：表示属于一个类而不是属于此类的任何特定对象的变量和函数.
这是与普通成员函数的最大区别, 也是其应用所在, 比如在对某一个类的对象进行计数时, 计数生成多少个类的实例, 就可以用到静态数据成员.
在这里面, static既不是限定作用域的, 也不是扩展生存期的作用, 而是指示变量/函数在此类中的唯一性.
这也是&#8221;属于一个类而不是属于此类的任何特定对象的变量和函数&#8221;的含义. 因为它是对整个类来说是唯一的, 因此不可能属于某一个实例对象的.
(针对静态数据成员而言, 成员函数不管是否是static, 在内存中只有一个副本, 普通成员函数调用时, 需要传入this指针,
static成员函数调用时, 没有this指针. )</p>
<p>&nbsp;</p>
<p>请看示例程序四(&lt;effective c++ (2nd)&gt;(影印版)第59页)<br />
class EnemyTarget {<br />
public:<br />
EnemyTarget()
{ ++numTargets; }<br />
EnemyTarget(const EnemyTarget&amp;) {
++numTargets; }<br />
~EnemyTarget() { --numTargets; }<br />
static size_t
numberOfTargets() { return numTargets; }<br />
bool destroy(); // returns
success of attempt to destroy EnemyTarget object<br />
private:<br />
static
size_t numTargets; // object counter<br />
};<br />
// class statics must be
defined outside the class;<br />
// initialization is to 0 by default<br />
size_t
EnemyTarget::numTargets;</p>
<p>在这个例子中, 静态数据成员numTargets就是用来计数产生的对象个数的.</p>
<p><br />
另外, 在设计类的多线程操作时, 由于POSIX库下的线程函数pthread_create()要求是全局的,
普通成员函数无法直接做为线程函数, 可以考虑用Static成员函数做线程函数.</p>
<p>原文； http://lagvin.bokee.com/viewdiary.21658934.html<br />
</p>
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/339315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2010-11-29 14:51 <a href="http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C -struct结构体的巨大作用</title><link>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339311.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Mon, 29 Nov 2010 06:31:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339311.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/339311.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339311.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/339311.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/339311.html</trackback:ping><description><![CDATA[<font face="宋体 "><font style="font-size: 12pt;">面对一个人的大型</font></font><font style="font-size: 12pt;"><font face="Times New Roman ">C/C++</font></font><font face="宋体 "><font style="font-size: 12pt;"><span href="http://www.arm16.com/tag.php?name=%B3%CC%D0%F2" onclick="tagshow(event)" class="t_tag">程序</span>时，只看其对</font></font><font style="font-size: 12pt;"><font face="Times New Roman ">struct </font></font><font face="宋体 "><font style="font-size: 12pt;">的使用情况我们就可以对其编写者的编程经验进行评估。因为一个
大型的</font></font><font style="font-size: 12pt;"><font face="Times New
Roman ">C/C++</font></font><font face="宋体 "><font style="font-size: 12pt;">程序，势必要涉及一些</font></font><font style="font-size: 12pt;"><font face="Times New Roman ">(</font></font><font face="宋体 "><font style="font-size: 12pt;">甚至大量</font></font><font style="font-size: 12pt;"><font face="Times New Roman ">)</font></font><font face="宋体 "><font style="font-size: 12pt;">进行数据组合的结构体，这些结构体可以将原本意义属于一个整体的数据组合在一起。从某种程度上来
说，会不会用</font></font><font style="font-size: 12pt;"><font face="Times New
Roman ">struct</font></font><font face="宋体 "><font style="font-size: 12pt;">，怎样用</font></font><font style="font-size: 12pt;"><font face="Times New Roman ">struct </font></font><font face="宋体 "><font style="font-size: 12pt;">是区别一个<span href="http://www.arm16.com/tag.php?name=%BF%AA%B7%A2" onclick="tagshow(event)" class="t_tag">开发</span>人员是否具备丰富开发经历的标志。</font></font><br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">&nbsp; &nbsp;&nbsp; &nbsp;</font></font><font face="宋体 "><font style="font-size: 12pt;">在网络协议、<span href="http://www.arm16.com/tag.php?name=%CD%A8%D0%C5" onclick="tagshow(event)" class="t_tag">通信</span>控制、<span href="http://www.arm16.com/tag.php?name=%C7%B6%C8%EB%CA%BD" onclick="tagshow(event)" class="t_tag">嵌入式</span><span href="http://www.arm16.com/tag.php?name=%CF%B5%CD%B3" onclick="tagshow(event)" class="t_tag">系统</span>的</font></font><font style="font-size: 12pt;"><font face="Times New Roman ">C/C++</font></font><font face="宋体 "><font style="font-size: 12pt;">编程中，我们经常要传送的不是简单的字节流（</font></font><font style="font-size: 12pt;"><font face="Times New Roman ">char</font></font><font face="宋体 "><font style="font-size: 12pt;">型数组），而是多种数据组合起来的一个整体，其表现形式是一个
结构体。经验不足的开发人员往往将所有需要传送的内容依顺序保存在</font></font><font style="font-size: 12pt;"><font face="Times New Roman ">char </font></font><font face="宋体 "><font style="font-size: 12pt;">型数组中，通过<span href="http://www.arm16.com/tag.php?name=%D6%B8%D5%EB" onclick="tagshow(event)" class="t_tag">指针</span>偏移的方法传送网络报文等信息。这样做编程复杂，易
出错，而且一旦控制方式及通信协议有所变化，程序就要进行非常细致的修改。</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">&nbsp; &nbsp;&nbsp; &nbsp;</font></font><font face="宋体 "><font style="font-size: 12pt;">一个有经验的开发者则灵活运用结构体，举一个例子，假设网络或控制协议中需要传送三种报文，其格式分别为</font></font><font style="font-size: 12pt;"><font face="Times New Roman ">packetA</font></font><font face="宋体 "><font style="font-size: 12pt;">、</font></font><font style="font-size: 12pt;"><font face="Times New Roman ">packetB</font></font><font face="宋体 "><font style="font-size: 12pt;">、</font></font><font style="font-size: 12pt;"><font face="Times New Roman ">packetC</font></font><font face="宋体 "><font style="font-size: 12pt;">：</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">struct structA</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">{</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman "><br />
int a;</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman "><br />
char b;</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">};</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">struct structB</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">{</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman "><br />
char a;</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman "><br />
short b;</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">};</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">struct structC</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">{</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman "><br />
int a;</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman "><br />
char b;</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman "><br />
float c;</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">}</font></font></p>
<br />
<p align="left"><font face="宋体 "><font style="font-size: 12pt;">优秀的程序<span href="http://www.arm16.com/tag.php?name=%C9%E8%BC%C6" onclick="tagshow(event)" class="t_tag">设计</span>者这样设计传送的报文：</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">struct CommuPacket</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">{</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman "><br />
int iPacketType; <br />
//</font></font><font face="宋体 "><font style="font-size: 12pt;">报文类型标志</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman "><br />
union <br />
//</font></font><font face="宋体 "><font style="font-size: 12pt;">每次传送的是三种
报文中的一种，使用</font></font><font style="font-size: 12pt;"><font face="Times
New Roman ">union</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman "><br />
{</font></font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman "><br />
struct structA packetA; struct structB packetB;</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman "><br />
struct structC packetC;</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman "><br />
}</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">};</font></font></p>
<br />
<p align="left"><font face="宋体 "><font style="font-size: 12pt;">在进行报文传送
时，直接传送</font></font><font style="font-size: 12pt;"><font face="Times New
Roman ">struct CommuPacket </font></font><font face="宋体 "><font style="font-size: 12pt;">一个整体。</font></font></p>
<br />
<p align="left"><font face="宋体 "><font style="font-size: 12pt;">假设发送<span href="http://www.arm16.com/tag.php?name=%BA%AF%CA%FD" onclick="tagshow(event)" class="t_tag">函数</span>的原形如下：</font></font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman "><br />
// pSendData</font></font><font face="宋体 ">：发送字节流的首地址，</font><font style="font-size: 10.5pt;"><font face="Times New Roman ">iLen</font></font><font face="宋体 ">：要发送的长度</font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman "><br />
Send(char * pSendData, unsigned int iLen);</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">&nbsp; &nbsp;&nbsp; &nbsp;</font></font><font face="宋体 "><font style="font-size: 12pt;">发送方可以直接进行如下调用发送</font></font><font style="font-size: 12pt;"><font face="Times New Roman ">struct CommuPacket </font></font><font face="宋体
"><font style="font-size: 12pt;">的一个<span href="http://www.arm16.com/tag.php?name=%CA%B5%C0%FD" onclick="tagshow(event)" class="t_tag">实例</span></font></font><font style="font-size: 12pt;"><font face="Times New Roman ">sendCommuPacket</font></font><font face="宋体 "><font style="font-size: 12pt;">：</font></font></p>
<br />
<p align="left"><font style="font-size: 12pt;"><font face="Times New
Roman ">Send( (char *)&amp;sendCommuPacket , sizeof(CommuPacket) );</font></font></p>
<br />
<br />
<p align="left"><font face="宋体 "><font style="font-size: 12pt;">假设接收函数的原
形如下：</font></font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman "><br />
// pRecvData</font></font><font face="宋体 ">：发送字节流的首地址，</font><font style="font-size: 10.5pt;"><font face="Times New Roman ">iLen</font></font><font face="宋体 ">：要接收的长度</font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman "><br />
//</font></font><font face="宋体 ">返回值：实际接收到的字节数</font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">unsigned int Recv(char * pRecvData, unsigned int iLen)</font></font><font face="宋体 ">；</font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">&nbsp; &nbsp;&nbsp; &nbsp;</font></font><font face="宋体 ">接收方可以直接进行如下调用将接收到的数据保存在</font><font style="font-size: 10.5pt;"><font face="Times New Roman ">struct
CommuPacket </font></font><font face="宋体 ">的一个实例</font><font style="font-size: 10.5pt;"><font face="Times New Roman ">recvCommuPacket
</font></font><font face="宋体 ">中：</font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">Recv( (char *)&amp;recvCommuPacket , sizeof(CommuPacket) );</font></font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">&nbsp; &nbsp;&nbsp; &nbsp;</font></font><font face="宋体 ">接着判断报文类型进行相应处理：</font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">switch(recvCommuPacket. iPacketType)</font></font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">{</font></font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">case PACKET_A:</font></font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">&#8230; <br />
//A </font></font><font face="宋体 ">类报文处理</font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">break;</font></font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">case PACKET_B:</font></font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">&#8230; <br />
//B </font></font><font face="宋体 ">类报文处理</font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">break;</font></font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">case PACKET_C:</font></font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">&#8230; <br />
//C </font></font><font face="宋体 ">类报文处理</font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">break;</font></font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">}</font></font></p>
<br />
<p align="left"><font face="宋体 ">以上程序中最值得注意的是</font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">Send( (char *)&amp;sendCommuPacket , sizeof(CommuPacket) );</font></font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">Recv( (char *)&amp;recvCommuPacket , sizeof(CommuPacket) );</font></font></p>
<br />
<p align="left"><font face="宋体 ">中的强制类型转换：</font><font style="font-size: 10.5pt;"><font face="Times New Roman ">(char *)&amp;sendCommuPacket</font></font><font face="宋体 ">、</font><font style="font-size: 10.5pt;"><font face="Times
New Roman ">(char *)&amp;recvCommuPacket</font></font><font face="宋体 ">，
先取地址，再转化为</font><font style="font-size: 10.5pt;"><font face="Times New
Roman ">char </font></font><font face="宋体 ">型指针，这样就可以直接利用处理字节流的函数。</font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">&nbsp; &nbsp;&nbsp; &nbsp;</font></font><font face="宋体 ">利用这种强制类型转化，我们还可以方便程序的编写，例如要
对</font><font style="font-size: 10.5pt;"><font face="Times New Roman ">sendCommuPacket
</font></font><font face="宋体 ">所处<span href="http://www.arm16.com/tag.php?name=%C4%DA%B4%E6" onclick="tagshow(event)" class="t_tag">内存</span>初始化为</font><font style="font-size: 10.5pt;"><font face="Times New Roman ">0</font></font><font face="宋体 ">，可以这样调用标准库函数</font><font style="font-size: 10.5pt;"><font face="Times New Roman ">memset()</font></font><font face="宋体 ">：</font></p>
<br />
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman "><br />
memset((char *)&amp;sendCommuPacket,0, sizeof(CommuPacket));</font></font></p>
<p align="left"><br />
</p>
<p align="left"><font style="font-size: 10.5pt;"><font face="Times New
Roman ">原文； http://www.arm16.com/viewthread.php?tid=397<br />
</font></font></p>
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/339311.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2010-11-29 14:31 <a href="http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339311.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>#ifdef #define 条件编译</title><link>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339310.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Mon, 29 Nov 2010 06:11:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339310.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/339310.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339310.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/339310.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/339310.html</trackback:ping><description><![CDATA[<font size="2">#ifndef、（或者#ifndef)、#def、#endif等宏这几个宏是为了进行条件编译。一般情况下，源程序中
所有的行都参加编译。但是有时希望对其中一部分内容只在满足一定条件才进行编译，也就是对一部分内容指定编译的条件，这就是&#8220;条件编译&#8221;。有时，希望当满
足某条件时对一组语句进行编译，而当条件不满足时则编译另一组语句。<br />
&nbsp; 条件编译命令最常见的形式为：<br />
&nbsp; #ifdef 标识符<br />
&nbsp;
程序段1<br />
&nbsp; #else<br />
&nbsp; 程序段2<br />
&nbsp; #endif<br />
&nbsp; <br />
&nbsp;
它的作用是：当标识符已经被定义过(一般是用#define命令定义)，则对程序段1进行编译，否则编译程序段2。<br />
&nbsp;
其中#else部分也可以没有，即：<br />
&nbsp; #ifdef<br />
&nbsp; 程序段1<br />
&nbsp; #denif<br />
&nbsp; <br />
&nbsp;
这里的&#8220;程序段&#8221;可以是语句组，也可以是命令行。这种条件编译可以提高C源程序的通用性。如果一个C源程序在不同计算机系统上系统上运行，而不同的计算机
又有一定的差异。例如，我们有一个数据类型，在Windows平台中，应该使用long类型表示，而在其他平台应该使用float表示，这样往往需要对源
程序作必要的修改，这就降低了程序的通用性。可以用以下的条件编译：<br />
&nbsp; #ifdef WINDOWS<br />
&nbsp; #define MYTYPE
long<br />
&nbsp; #else<br />
&nbsp; #define MYTYPE float<br />
&nbsp; #endif<br />
&nbsp; <br />
&nbsp;
如果在Windows上编译程序，则可以在程序的开始加上<br />
&nbsp; #define WINDOWS<br />
&nbsp; <br />
&nbsp; 这样则编译下面的命令行：<br />
&nbsp;
#define MYTYPE long<br />
&nbsp; <br />
&nbsp; 如果在这组条件编译命令之前曾出现以下命令行：<br />
&nbsp; #define
WINDOWS 0<br />
&nbsp; <br />
&nbsp;
则预编译后程序中的MYTYPE都用float代替。这样，源程序可以不必作任何修改就可以用于不同类型的计算机系统。当然以上介绍的只是一种简单的情
况，可以根据此思路设计出其它的条件编译。<br />
&nbsp;
例如，在调试程序时，常常希望输出一些所需的信息，而在调试完成后不再输出这些信息。可以在源程序中插入以下的条件编译段：<br />
&nbsp; #ifdef
DEBUG<br />
&nbsp; print ("device_open(%p)\n", file);<br />
&nbsp; #endif<br />
&nbsp; <br />
&nbsp;
如果在它的前面有以下命令行：<br />
&nbsp; #define DEBUG<br />
&nbsp; <br />
&nbsp;
则在程序运行时输出file指针的值，以便调试分析。调试完成后只需将这个define命令行删除即可。有人可能觉得不用条件编译也可达此目的，即在调试
时加一批printf语句，调试后一一将printf语句删除去。的确，这是可以的。但是，当调试时加的printf语句比较多时，修改的工作量是很大
的。用条件编译，则不必一一删改printf语句，只需删除前面的一条&#8220;#define
DEBUG&#8221;命令即可，这时所有的用DEBUG作标识符的条件编译段都使其中的printf语句不起作用，即起统一控制的作用，如同一个&#8220;开关&#8221;一样。<br />
&nbsp;
有时也采用下面的形式：<br />
&nbsp; #ifndef 标识符<br />
&nbsp; 程序段1<br />
&nbsp; #else<br />
&nbsp; 程序段2<br />
&nbsp; #endif<br />
&nbsp;
<br />
&nbsp;
只是第一行与第一种形式不同：将&#8220;ifdef&#8221;改为&#8220;ifndef&#8221;。它的作用是：若标识符未被定义则编译程序段1，否则编译程序段2。这种形式与第一种
形式的作用相反。<br />
&nbsp; 以上两种形式用法差不多，根据需要任选一种，视方便而定。<br />
&nbsp;
还有一种形式，就是#if后面的是一个表达式，而不是一个简单的标识符：<br />
&nbsp; #if 表达式<br />
&nbsp; 程序段1<br />
&nbsp; #else<br />
&nbsp;
程序段2<br />
&nbsp; #endif<br />
&nbsp; <br />
&nbsp;
它的作用是：当指定的表达式值为真（非零）时就编译程序段1，否则编译程序段2。可以事先给定一定条件，使程序在不同的条件下执行不同的功能。<br />
&nbsp;
例如：输入一行字母字符，根据需要设置条件编译，使之能将字母全改为大写输出，或全改为小写字母输出。<br />
&nbsp; #define LETTER 1<br />
&nbsp;
main()<br />
&nbsp; {<br />
&nbsp; char str[20]="C Language",c;<br />
&nbsp; int i=0;<br />
&nbsp;
while((c=str[i])!='\0'){<br />
&nbsp; i++;<br />
&nbsp; #if LETTER<br />
&nbsp;
if(c&gt;='a'&amp;&amp;c&lt;='z') c=c-32;<br />
&nbsp; #else<br />
&nbsp;
if(c&gt;='A'&amp;&amp;c&lt;='Z') c=c+32;<br />
&nbsp; #endif<br />
&nbsp;
printf("%c",c);<br />
&nbsp; }<br />
&nbsp; }<br />
&nbsp; <br />
&nbsp; 运行结果为：C LANGUAGE<br />
&nbsp;
现在先定义LETTER为1，这样在预处理条件编译命令时，由于LETTER为真（非零），则对第一个if语句进行编译，运行时使小写字母变大写。如果将
程序第一行改为：<br />
&nbsp; #define LETTER 0<br />
&nbsp; <br />
&nbsp;
则在预处理时，对第二个if语句进行编译处理，使大写字母变成小写字母（大写字母与相应的小写字母的ASCII代码差32）。此时运行情况为：<br />
&nbsp;
c language<br />
&nbsp;
有人会问：不用条件编译命令而直接用if语句也能达到要求，用条件编译命令有什么好处呢？的确，此问题完全可以不用条件编译处理，但那样做目标程序长（因
为所有语句都编译），而采用条件编译，可以减少被编译的语句，从而减少目标的长度。当条件编译段比较多时，目标程序长度可以大大减少。<br />
原文： http://blog.csdn.net/sunshuai03/archive/2005/11/17/531596.aspx<br />
</font>
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/339310.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2010-11-29 14:11 <a href="http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339310.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>typedef 类型重命名 与#define 宏定义 </title><link>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339307.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Mon, 29 Nov 2010 05:59:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339307.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/339307.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339307.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/339307.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/339307.html</trackback:ping><description><![CDATA[在现实生活中，信息的概念可能是长度，数量和面积等。在C语言中，信息被抽象为int、float和double等基本数据类型。从基本数据类型名称上，
不能够看出其所代表的物理属性，并且int、float和double为系统关键字，不可以修改。为了解决用户自定义数据类型名称的需求，C语言中引入类
型重定义语句typedef，可以为数据类型定义新的类型名称，从而丰富数据类型所包含的属性信息。<br />
typedef的语法描述<br />
typedef
类型名称 类型标识符;<br />
typedef为系统保留字，&#8220;类型名称&#8221;为已知数据类型名称，包括基本数据类型和用户自定义数据类型，&#8220;类型标识符&#8221;
为新的类型名称。例如:<br />
typedef double LENGTH;<br />
typedef unsigned int COUNT;<br />
定
义新的类型名称之后，可像基本数据类型那样定义变量。例如：<br />
typedef unsigned int COUNT;<br />
unsigned
int b;<br />
COUNT c;<br />
typedef 的主要应用有如下的几种形式：<br />
1) 为基本数据类型定义新的类型名。例如：<br />
typedef
unsigned int COUNT;<br />
typedef double AREA;<br />
此种应用的主要目的，首先是丰富数据类型中包含的属
性信息，其次是为了系统移植的需要，稍后详细描述。<br />
2) 为自定义数据类型（结构体、公用体和枚举类型）定义简洁的类型名称。例如：<br />
struct
Point<br />
{<br />
double x;<br />
double y;<br />
double z;<br />
};<br />
struct Point
oPoint1={100，100，0};<br />
struct Point oPoint2;<br />
其中结构体struct
Point为新的数据类型，在定义变量的时候均要有保留字struct，而不能像int和double那样直接使用Point来定义变量。如果经过如下的
修改，<br />
typedef struct tagPoint<br />
{<br />
double x;<br />
double y;<br />
double
z;<br />
} Point;<br />
定义变量的方法可以简化为<br />
Point oPoint;<br />
由于定义结构体类型有多种形式，因此可以修改
如下：<br />
typedef struct <br />
{<br />
double x;<br />
double y;<br />
double z;<br />
}
Point;<br />
3) 为数组定义简洁的类型名称。例如，定义三个长度为5的整型数组，<br />
int
a[10]，b[10]，c[10]，d[10];<br />
在C语言中，可以将长度为10的整型数组看作为一个新的数据类型，再利用typedef为其重
定义一个新的名称，可以更加简洁形式定义此种类型的变量，具体的处理方式如下:<br />
typedef int INT_ARRAY_10[10];<br />
typedef
int INT_ARRAY_20[20];<br />
INT_ARRAY_10 a，b，c，d;<br />
INT_ARRAY_20 e;<br />
其中
INT_ARRAY_10和INT_ARRAY_20为新的类型名，10 和20
为数组的长度。a，b，c，d均是长度为10的整型数组，e是长度为20的整型数组。<br />
4)
为指针定义简洁的名称。首先为数据指针定义新的名称，例如<br />
typedef char * STRING;<br />
STRING
csName={&#8220;Jhon&#8221;};<br />
其次，可以为函数指针定义新的名称，例如<br />
typedef int (*MyFUN)(int
a，int b);<br />
其中MyFUN代表 int *XFunction(int a，intb)类型指针的新名称。例如<br />
typedef
int (*MyFUN)(int a，int b);<br />
int Max(int a，int b);<br />
MyFUN *pMyFun;<br />
pMyFun=
Max;<br />
在使用typedef时，应当注意如下的问题：<br />
1)
typedef的目的是为已知数据类型增加一个新的名称。因此并没有引入新的数据类型。<br />
2) typedef
只适于类型名称定义，不适合变量的定义。<br />
3) typedef 与#define具有相似的之处，但是实质不同。<br />
<span class="pmemo">提示 #define AREA double 与 typedef double AREA
可以达到相同的效果。但是其实质不同，
#define为预编译处理命令，主要定义常量，此常量可以为任何的字符及其组合，在编译之前，将此常量出现的所有位置，用其代表的字符或字符组合无条件
的替换，然后进行编译。typedef是为已知数据类型增加一个新名称，其原理与使用int double等保留字一致。<br />
原文： http://blog.chinaunix.net/u2/75045/showart_1120891.html<br />
</span>
<img src ="http://www.blogjava.net/jasmine214--love/aggbug/339307.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2010-11-29 13:59 <a href="http://www.blogjava.net/jasmine214--love/archive/2010/11/29/339307.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>