??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲午夜精品在线,亚洲国产专区一区,在线日韩日本国产亚洲http://m.tkk7.com/jasmine214--love/category/47200.html只有当你的内心L充满快乐、美好的愿望和宁静时Q你才能拥有强壮的体和明朗、快乐或者宁静的面容?/description>zh-cnMon, 16 Jul 2012 11:10:41 GMTMon, 16 Jul 2012 11:10:41 GMT60c全局变量、static、函数指?/title><link>http://m.tkk7.com/jasmine214--love/archive/2012/07/16/383237.html</link><dc:creator>qLv蓝梦</dc:creator><author>qLv蓝梦</author><pubDate>Mon, 16 Jul 2012 08:03:00 GMT</pubDate><guid>http://m.tkk7.com/jasmine214--love/archive/2012/07/16/383237.html</guid><wfw:comment>http://m.tkk7.com/jasmine214--love/comments/383237.html</wfw:comment><comments>http://m.tkk7.com/jasmine214--love/archive/2012/07/16/383237.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/jasmine214--love/comments/commentRss/383237.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/jasmine214--love/services/trackbacks/383237.html</trackback:ping><description><![CDATA[<div><h2>c全局变量、static、函数指?/h2> <div class="1hbrpdh" id="content" text-content="" clearfix"=""> <p>1、static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?<br />    {:全局变量(外部变量)的说明之前再冠以static 构成了静态的全局变量。全局变量本n是静态存储方式, 静态全局变量当然也是静态存储方式?q两者在存储方式上ƈ无不同。这两者的区别虽在于非静态全局变量的作用域是整个源E序Q? 当一个源E序由多个源文gl成Ӟ非静态的全局变量在各个源文g中都是有效的?而静态全局变量则限制了其作用域Q?卛_在定义该变量的源文g内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文g内,只能源文件内的函数公用, 因此可以避免在其它源文g中引起错误?br />    从以上分析可以看出, 把局部变量改变ؓ静态变量后是改变了它的存储方式x变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的用范围?br />    static函数与普通函C用域不同。仅在本文g。只在当前源文g中用的函数应该说明为内部函?static)Q内部函数应该在当前源文件中说明和定义。对于可在当前源文g以外使用的函敎ͼ应该在一个头文g中说明,要用这些函数的源文件要包含q个头文?br />    static全局变量与普通的全局变量有什么区别:static全局变量只初使化一ơ,防止在其他文件单元中被引?<br />    static局部变量和普通局部变量有什么区别:static局部变量只被初始化一ơ,下一ơ依据上一ơ结果|<br />    static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中l持一份拷?br />2、如何引用一个已l定义过的全局变量Q?br />     {:extern<br />     可以用引用头文g的方式,也可以用extern关键字,如果用引用头文g方式来引用某个在头文件中声明的全局变理Q假定你那个变写错了,那么在编译期? 会报错,如果你用extern方式引用Ӟ假定你犯了同L错误Q那么在~译期间不会报错Q而在q接期间报错?/p><p>3、全局变量可不可以定义在可被多?C文g包含的头文g中?Z么?<br />    {:可以Q在不同的C文g中以static形式来声明同名全局变量?br />    可以在不同的C文g中声明同名的全局变量Q前提是其中只能有一个C文g中对此变量赋初|此时q接不会出错?/p><p>4、程序的局部变量存在于Q堆栈)中,全局变量存在于(静态区 Q中Q动态申h据存在于Q?堆)中?br />5、设有以下说明和定义Q?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(”%d”,sizeof(struct date)+sizeof(max));的执行结果是Q___52____<br />    {:DATE是一个union, 变量公用I间. 里面最大的变量cd是int[5], 占用20个字? 所以它的大是20<br />data是一个struct, 每个变量分开占用I间. 依次为int4 + DATE20 + double8 = 32.<br />所以结果是 20 + 32 = 52.<br />当然…在某?6位编辑器? int可能?字节,那么l果?int2 + DATE10 + double8 = 20<br />6. 函数指针<br />     定义Q?void (*fptr)();<br />     或者: typedef void (*FP)(); fp fptr;<br />     把函数的地址赋值给函数指针Q可以采用下面两UŞ式:<br />         fptr=&Function;<br />         fptr=Function;<br />     取地址q算W?amp;不是必需的,因ؓ单单一个函数标识符标可CZ它的地址Q如果是函数调用Q还必须包含一个圆括号括v来的参数表?br />     可以采用如下两种方式来通过指针调用函数Q?br />         x=(*fptr)();<br />         x=fptr();</p> </div></div>转:<div>http://hi.baidu.com/xmxqiyan/item/139d9e3c312833bf134b1419</div><img src ="http://m.tkk7.com/jasmine214--love/aggbug/383237.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/jasmine214--love/" target="_blank">qLv蓝梦</a> 2012-07-16 16:03 <a href="http://m.tkk7.com/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://m.tkk7.com/jasmine214--love/archive/2012/07/16/383235.html</link><dc:creator>qLv蓝梦</dc:creator><author>qLv蓝梦</author><pubDate>Mon, 16 Jul 2012 07:46:00 GMT</pubDate><guid>http://m.tkk7.com/jasmine214--love/archive/2012/07/16/383235.html</guid><wfw:comment>http://m.tkk7.com/jasmine214--love/comments/383235.html</wfw:comment><comments>http://m.tkk7.com/jasmine214--love/archive/2012/07/16/383235.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/jasmine214--love/comments/commentRss/383235.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/jasmine214--love/services/trackbacks/383235.html</trackback:ping><description><![CDATA[<div><a>C语言宏条件编译详?/a></div><div>处理q程扫描源代码,对其q行初步的{换,产生新的源代码提供给~译器。可见预处理q程先于~译器对源代码进行处理?br />在C 语言中,q没有Q何内在的机制来完成如下一些功能:在编译时包含其他源文件、定义宏、根据条件决定编译时是否包含某些代码。要完成q些工作Q就需要用预 处理E序。尽在目前l大多数~译器都包含了预处理E序Q但通常认ؓ它们是独立于~译器的。预处理q程d源代码,查包含预处理指o的语句和宏定义,q?Ҏ代码q行响应的{换。预处理q程q会删除E序中的注释和多余的I白字符?br />预处理指令是?号开头的代码行?号必L该行除了MI白字符外的W一个字W?后是指o关键字,在关键字?号之间允许存在Q意个数的I白字符。整行语句构成了一条预处理指oQ该指o在~译器进行编译之前对源代码做某些转换。下面是部分预处理指令: <p> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 指o <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 用?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> # <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> I指令,无Q何效?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> Qi nclude <wbr> <wbr> <wbr> 包含一个源代码文g<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define <wbr> <wbr> <wbr> <wbr> 定义?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #undef <wbr> <wbr> <wbr> <wbr> <wbr> 取消已定义的?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #if <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 如果l定条g为真Q则~译下面代码<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #ifdef <wbr> <wbr> <wbr> <wbr> <wbr> 如果宏已l定义,则编译下面代?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #ifndef <wbr> <wbr> <wbr> <wbr> 如果宏没有定义,则编译下面代?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #elif <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 如果前面?ifl定条g不ؓ真,当前条g为真Q则~译下面代码<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #endif <wbr> <wbr> <wbr> <wbr> <wbr> l束一?if……#else条g~译?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #error <wbr> <wbr> <wbr> <wbr> <wbr> 停止~译q显C错误信?/p> <p>一、文件包?br /> <wbr> <wbr> <wbr> Qi nclude预处理指令的作用是在指o处展开被包含的文g。包含可以是多重的,也就是说一个被包含的文件中q可以包含其他文件。标准C~译器至支持八重嵌套包含?br /> <wbr> <wbr> <wbr> 预处理过E不查在转换单元中是否已l包含了某个文gq止对它的多次包含。这样就可以在多ơ包含同一个头文gӞ通过l定~译时的条g来达C同的效果。例如:</p> <p> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define AAA<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> Qi nclude "t.c"<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #undef AAA<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> Qi nclude "t.c"</p> <p> <wbr> <wbr> <wbr> Z避免那些只能包含一ơ的头文件被多次包含Q可以在头文件中用编译时条g来进行控制。例如:<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr><br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #ifndef MY_H<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define MY_H<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> ……<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #endif</p> <p> <wbr> <wbr> <wbr> 在程序中包含头文件有两种格式Q?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> Qi nclude <my.h><br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> Qi nclude "my.h"<br /> <wbr> <wbr> <wbr> <wbr> W一U方法是用尖括号把头文g括v来。这U格式告诉预处理E序在编译器自带的或外部库的头文件中搜烦被包含的头文件。第二种Ҏ是用双引h头文件括?来。这U格式告诉预处理E序在当前被~译的应用程序的源代码文件中搜烦被包含的头文Ӟ如果找不刎ͼ再搜索编译器自带的头文g?br /> <wbr> <wbr> <wbr> 采用两种不同包含格式的理由在于,~译器是安装在公共子目录下的Q而被~译的应用程序是在它们自qU有子目录下的。一个应用程序既包含~译器提供的公共头文Ӟ也包含自定义的私有头文g。采用两U不同的包含格式使得~译器能够在很多头文件中区别Zl公q头文件?/p> <p>二、宏<br /> <wbr> <wbr> <wbr> 宏定义了一个代表特定内容的标识W。预处理q程会把源代码中出现的宏标识W替换成宏定义时的倹{宏最常见的用法是定义代表某个值的全局W号。宏的第二种?法是定义带参数的宏,q样的宏可以象函C栯调用Q但它是在调用语句处展开宏,q用调用时的实际参数来代替定义中的Ş式参数?br /> <wbr> <wbr> <wbr> 1.#define指o<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define预处理指令是用来定义宏的。该指o最单的格式是:首先明一个标识符Q然后给个标识符代表的代码。在后面的源代码中,qq些代码来替代该标识W。这U宏把程序中要用到的一些全局值提取出来,赋给一些记忆标识符?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define MAX_NUM 10<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> int array[MAX_NUM];<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> for(i=0;i<MAX_NUM;i++) <wbr><br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr><br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 在这个例子中Q对于阅读该E序的h来说Q符号MAX_NUM有特定的含义,它代表的值给Z数组所能容U的最大元素数目。程序中可以多次使用q个倹{作 ZU约定,习惯上L全部用大写字母来定义宏,q样易于把程序红的宏标识W和一般变量标识符区别开来。如果想要改变数l的大小Q只需要更改宏定义q?~译E序卛_?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 宏表C的值可以是一个常量表辑ּQ其中允许包括前面已l定义的宏标识符。例如:<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define ONE 1<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define TWO 2<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define THREE (ONE+TWO)<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 注意上面的宏定义使用了括受尽它们ƈ不是必须的。但Z谨慎考虑Q还是应该加上括L。例如:<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> six=THREE*TWO;<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 预处理过E把上面的一行代码{换成Q?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> six=(ONE+TWO)*TWO;<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 如果没有那个括号Q就转换成six=ONE+TWO*TWO;了?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 宏还可以代表一个字W串帔RQ例如:<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define VERSION "Version 1.0 Copyright(c) 2003"<br /> <wbr> <wbr> <wbr> 2.带参数的#define指o<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 带参数的宏和函数调用看v来有些相伹{看一个例子:<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define Cube(x) (x)*(x)*(x)<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 可以时Q何数字表辑ּ甚至函数调用来代替参数x。这里再ơ提醒大家注意括L使用。宏展开后完全包含在一Ҏ号中Q而且参数也包含在括号中,q样׃证了宏和参数的完整性。看一个用法:<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> int num=8+2;<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> volume=Cube(num);<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 展开后ؓ(8+2)*(8+2)*(8+2);<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 如果没有那些括号变?+2*8+2*8+2了?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 下面的用法是不安全的Q?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> volume=Cube(num++);<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 如果Cube是一个函敎ͼ上面的写法是可以理解的。但是,因ؓCube是一个宏Q所以会产生副作用。这里的擦书不是单的表达式,它们生意想不到的l果。它们展开后是q样的:<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> volume=(num++)*(num++)*(num++);<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 很显Ӟl果?0*11*12,而不?0*10*10;<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 那么怎样安全的用Cube宏呢Q必L可能产生副作用的操作Ud宏调用的外面q行Q?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> int num=8+2;<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> volume=Cube(num);<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> num++;<br /> <wbr> <wbr> <wbr> 3.#q算W?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 出现在宏定义中的#q算W把跟在其后的参数{换成一个字W串。有时把q种用法?UCؓ字符串化q算W。例如:</p> <p> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define PASTE(n) "adhfkj"#n</p> <p> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> main()<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> {<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> printf("%s/n",PASTE(15));<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> }<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 宏定义中?q算W告诉预处理E序Q把源代码中M传递给该宏的参数{换成一个字W串。所以输出应该是adhfkj15?br /> <wbr> <wbr> <wbr> 4.##q算W?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> ##q算W用于把参数q接C赗预处理E序把出现在##两侧的参数合q成一个符受看下面的例子:</p> <p> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define NUM(a,b,c) a##b##c<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define STR(a,b,c) a##b##c</p> <p> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> main()<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> {<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> printf("%d/n",NUM(1,2,3));<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> printf("%s/n",STR("aa","bb","cc"));<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> }</p> <p> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 最后程序的输出?<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 123<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> aabbcc<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 千万别担心,除非需要或者宏的用法恰好和手头的工作相养I否则很少有程序员会知?#q算W。绝大多数程序员从来没用q它?/p> <p>三、条件编译指?br /> <wbr> <wbr> <wbr> 条g~译指o决定那些代码被~译Q而哪些是不被~译的。可以根据表辑ּ的值或者某个特定的宏是否被定义来确定编译条件?br /> <wbr> <wbr> <wbr> 1.#if指o<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #if指o跟在制造另关键字后的常量表辑ּ。如果表辑ּ为真Q则~译后面的代码,知道出现#else?elif?endif为止Q否则就不编译?br /> <wbr> <wbr> <wbr> 2.#endif指o<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #endif用于l止#if预处理指令?/p> <p> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define DEBUG 0<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> main()<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> {<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #if DEBUG<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> printf("Debugging/n");<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #endif<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> printf("Running/n");<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> }</p> <p> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> ׃E序定义DEBUG宏代?Q所?if条g为假Q不~译后面的代码直?endifQ所以程序直接输出Running?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> 如果L#define语句Q效果是一L?br /> <wbr> <wbr> <wbr> 3.#ifdef?ifndef<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define DEBUG</p> <p> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> main()<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> {<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #ifdef DEBUG<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> printf("yes/n");<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #endif<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #ifndef DEBUG<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> printf("no/n");<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #endif<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> }<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #if defined{h?ifdef; #if !defined{h?ifndef<br /> <wbr> <wbr> <wbr> 4.#else指o<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #else指o用于某个#if指o之后Q当前面?if指o的条件不为真Ӟq?else后面的代码?endif指o中指上面的条g块?/p> <p> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define DEBUG</p> <p> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> main()<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> {<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #ifdef DEBUG<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> printf("Debugging/n");<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #else<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> printf("Not debugging/n");<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #endif<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> printf("Running/n");<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> }</p> <p> <wbr> <wbr> <wbr> 5.#elif指o<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #elif预处理指令综合了#else?if指o的作用?/p> <p> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #define TWO</p> <p> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> main()<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> {<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #ifdef ONE<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> printf("1/n");<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #elif defined TWO<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> printf("2/n");<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #else<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> printf("3/n");<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #endif<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> }<br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> E序很好理解Q最后输出结果是2?/p> <p> <wbr> <wbr> <wbr> 6.其他一些标准指?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #error指oɾ~译器显CZ条错误信息,然后停止~译?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #line指o可以改变~译器用来指告和错误信息的文件号和行受?br /> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> <wbr> #pragma指o没有正式的定义。编译器可以自定义其用途。典型的用法是禁止或允许某些烦h的警告信息?/p></div>转:<div>http://blog.chinaunix.net/space.php?uid=20693685&do=blog&id=1892557</div><img src ="http://m.tkk7.com/jasmine214--love/aggbug/383235.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/jasmine214--love/" target="_blank">qLv蓝梦</a> 2012-07-16 15:46 <a href="http://m.tkk7.com/jasmine214--love/archive/2012/07/16/383235.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>struct sockaddr_nl l构?由来、含义以及用——获取Linux路由?/title><link>http://m.tkk7.com/jasmine214--love/archive/2012/06/15/380877.html</link><dc:creator>qLv蓝梦</dc:creator><author>qLv蓝梦</author><pubDate>Fri, 15 Jun 2012 09:33:00 GMT</pubDate><guid>http://m.tkk7.com/jasmine214--love/archive/2012/06/15/380877.html</guid><wfw:comment>http://m.tkk7.com/jasmine214--love/comments/380877.html</wfw:comment><comments>http://m.tkk7.com/jasmine214--love/archive/2012/06/15/380877.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/jasmine214--love/comments/commentRss/380877.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/jasmine214--love/services/trackbacks/380877.html</trackback:ping><description><![CDATA[<div>Linux 用户态与内核态的交互<br />  ?Linux 2.4 版以后版本的内核中,几乎全部的中断过E与用户态进E的通信都是使用 netlink 套接字实现的Q例如iprote2|络理工具Q它与内核的交互全部用了netlinkQ著名的内核包过滤框架Netfilter在与用户I间的?读,也在最新版本中改变为netlinkQ无疑,它将是Linux用户态与内核态交的主要Ҏ之一。它的通信依据是一个对应于q程的标识,一般定q?E的 ID。当通信的一端处于中断过E时Q该标识?0。当使用 netlink 套接字进行通信Q通信的双斚w是用h进E,则用方法类g消息队列。但通信双方有一端是中断q程Q用方法则不同。netlink 套接字的最大特Ҏ对中断过E的支持Q它在内核空间接收用L间数据时不再需要用戯行启动一个内核线E,而是通过另一个Y中断调用用户事先指定的接收函 数?br />《UNIX Network Programming Volume 1 - 3rd Edition》第18?br />讲到BSD UNIXpȝ中routing socket的应用,q种套接字是按下面方式生成的Q?br />rt_socket = socket(AF_ROUTE, SOCK_RAW, 0);<br />?后就可以用它跟内怺互,q行|络环境理的操作,如读?讄/删除路由表信息,更改|关{等Q但书中所列代码只?.3BSD及以后版本的原始 UNIXpȝ下可用,Linux虽然实现了AF_ROUTE族套接字Q但用法却完全不同。由于网上这斚w知识的资料想对匮乏,现对Linux?routing socket的用做一介绍?br />׃我现在在Magic Linux1.0下工作,所以以下的讲解全部Z2.4.10内核。Linux从v2.2开始引入这一机制Q因此可以肯定从v2.2到v2.4的内栔R是适用的,更新的v2.6我没有试q?br /><br />Linux下虽然也有AF_ROUTE族套接字Q但是这个定义只是个别名Q请?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族套接字像一个连接用L间和内核的双工管道,通过它,用户q程可以修改内核q行?数、读取和讄路由信息、控制特定网卡的up/down状态等{,可以说是一个管理网l资源的l佳途径?br /><br />1 生成所需套接字,q绑定一个sockaddrl构<br /><br />先来看如何生成一个AF_NETLINK族套接字Q?br />sockfd = socket(AF_NETLINK, socket_type, netlink_faimly);<br />q里socket_type可选SOCK_DGRAM或SOCK_RAWQ因为AF_NETLINK族是面向数据报的套接字,所以不能用SOCK_STREAM?br />netlink_family指定要和内核中的哪个子系l进行交互,目前支持Q?br />NETLINK_ROUTE 与\׃息相养I包括查询、设|和删除路由表中的条目等。待会儿我们以q类family举个实际的例子;<br />NETLINK_FIREWALL 接收由IPv4防火墙代码发送的包;<br />NETLINK_ARPD 可以在用L间进行arp~存的管理;<br />NETLINK_ROUTE6 在用L间发送和接收路由表信息更斎ͼ<br />q有几种虽然没有实现Q但已经有了定义Qؓ以后扩展做好了准备?br /><br />接下来要l该套接字绑定一个sockaddrl构Q实际上是一个sockaddr_nll构Q?br />struct sockaddr_nl {<br />sa_family_t nl_family; /*AF_NETLINK*/<br />unsigned short nl_pad; /* 0 */<br />pid_t nl_pid; /* q程pid */<br />u_32 nl_groups; /* 多播l掩?/<br />}nl;<br />q个l构一般按照注释填好就可以了,nl_groups我也不知道怎么用,一般填零了Q表C没有多播。绑定:<br />bind(sockfd, (struct sockaddr*) &nl, sizeof(nl));<br /><br />2 填充所需数据l构Qƈ通过sendmsg()/send(){函数写到套接字里去<br /><br />?此ؓ止,与内栔R信的准备工作就完成了,下面要做的工作是Q选取适当的数据结构进行填充,q作为sendmsg()的参数发送出去,qrecv()收到?消息。这个数据结构就是nlmsghdrQ它只是一个信息头Q后面可以接L长的数据Q这些数据实际上又是针对某一需求所采用的特定数据结构。先来看 nlmsghdrQ?br />struct nlmsghdr {<br />_u32 nlmsg_len; /* Length of msg including header */<br />_u32 nlmsg_type; /* 操作命o */<br />_u16 nlmsg_flags; /* various flags */<br />_u32 nlmsg_seq; /* Sequence number */<br />_u32 nlmsg_pid; /* q程PID */<br />};<br />/* 紧跟着是实际要发送的数据Q长度可以Q?*/<br /><br />nlmsg_type 军_q次要执行的操作Q如查询当前路由表信息,所使用的就是RTM_GETROUTE。标准nlmsg_type包括QNLMSG_NOOP, NLMSG_DONE, NLMSG_ERROR{。根据采用的nlmsg_type不同Q还要选取不同的数据结构来填充到nlmsghdr后面Q?br />操作 数据l构<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 />׃情Ş众多Q我从现在开始将用一个特定的例子来说明问题。我们的目的是从内核dIPV4路由表信息。从上面表看Qnlmsg_type一定用RTM_xxxROUTE操作Q对应的数据l构是rtmsg。既然是dQ那么应该是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操作来说Q我们只需指定两个成员Qrtm_family:AF_INET, rtm_table: RT_TABLE_MAIN。其他成员都初始化ؓ0卛_。将q个l构体跟nlmsghdrl合hQ得到我们自q新结构体Q?br />struct {<br />struct nlmsghdr nl;<br />struct rtmsg rt;<br />}req;<br />填充好rtl构之后Q还要调整nll构相应成员的倹{Linux定义了多个宏来处理nlmsghdr成员的|我们q里用到的是NLMSG_LENGTH(size_t len);<br />req.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));<br />q将计算nlmsghdr长度与rtmsg长度的和Q其中包括了rtmsgq行4字节边界寚w的调_Qƈ存储到nlmsghdr的nlmsg_len成员中。接下来要做的就是将q个新结构体req攑ֈsendmsg()函数的msghdr.iov处,q调用函数?br />sendmsg(sockfd, &msg, 0);<br /><br />3 接收数据Qƈq行分析<br /><br />接下来的操作是recv()操作Q从该套接字d内核q回的数据,q进行分析处理?br />recv(sockfd, p, sizeof(buf) - nll, 0);<br />其中p是指向一个缓冲区buf的指针,nll是已接收到的nlmsghdr数据的长度?br />׃内核q回信息是一个字节流Q需要调用者检查消息结。这是通过查返回的nlmsghdr的nlmsg_type是否{于NLMSG_DONE来完成的。返回的数据格式如下Q?br />-----------------------------------------------------------<br />| nlmsghdr+route entry | nlmsghdr+route entry | ......... <br />-----------------------------------------------------------<br />| 解出route entry<br />V<br />-----------------------------------------------------------<br />| dst_addr | gateway | Output interface| ...............<br />-----------------------------------------------------------<br />?以看出,q回消息由多?nlmsghdr + route entry)l成Q当某个nlmsghdr的nlmsg_type == NLMSG_DONE时就表示信息输出已经完毕。而每一个route entry由多个rtattrl构体组成,每个l构体表C路由的某个属性,如目的地址Q网关等{。根据这个示意图我们p够轻松解析需要的数据了?/div><br />原文Q?div>http://www.douban.com/note/29453304/</div><img src ="http://m.tkk7.com/jasmine214--love/aggbug/380877.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/jasmine214--love/" target="_blank">qLv蓝梦</a> 2012-06-15 17:33 <a href="http://m.tkk7.com/jasmine214--love/archive/2012/06/15/380877.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C语言之static静态变?http://m.tkk7.com/jasmine214--love/archive/2012/06/05/380038.htmlqLv蓝梦qLv蓝梦Tue, 05 Jun 2012 08:43:00 GMThttp://m.tkk7.com/jasmine214--love/archive/2012/06/05/380038.htmlhttp://m.tkk7.com/jasmine214--love/comments/380038.htmlhttp://m.tkk7.com/jasmine214--love/archive/2012/06/05/380038.html#Feedback0http://m.tkk7.com/jasmine214--love/comments/commentRss/380038.htmlhttp://m.tkk7.com/jasmine214--love/services/trackbacks/380038.html

1. static 变量

静态变量的cd 说明W是static?静态变量当然是属于静态存储方式,但是属于静态存储方式的量不一定就是静态变量?例如外部变量虽属于静?存储方式Q但不一定是静态变量,必须?static加以定义后才能成为静态外部变量,或称静态全局变量?br />
2. 静态局部变?br />静态局部变量属于静态存储方式,它具有以下特点:
(1)静态局部变量在函数内定?它的生存期ؓ整个源程序,但是其作用域仍与自动变量相同Q只能在定义该变量的函数内用该变量。退函数后, 管该变量还l箋存在Q但不能使用它?br />
(2)允许Ҏ造类静态局部量赋初?例如数组Q若未赋以初|则由pȝ自动赋以0倹{?br />(3) 对基本类型的静态局部变量若在说明时未赋以初|则系l自动赋?倹{而对自动变量不赋初|则其值是不定的?Ҏ静态局部变量的特点Q?可以 看出它是一U生存期为整个源E序的量。虽然离开定义它的函数后不能用,但如再次调用定义它的函数Ӟ它又可l用, 而且保存了前ơ被调用后留下的 倹{?因此Q当多次调用一个函C要求在调用之间保留某些变量的值时Q可考虑采用静态局部变量。虽然用全局变量也可以达Cq目的,但全局变量有时会造成 意外的副作用Q因此仍以采用局部静态变量ؓ宜?br />
3.静态全局变量
全局变量(外部变量)的说明之前再冠以static 构 成了静态的全局变量。全局变量本n是静态存储方式, 静态全局变量当然也是静态存储方式?q两者在存储方式上ƈ无不同。这两者的区别虽在于非静态全局 变量的作用域是整个源E序Q?当一个源E序由多个源文gl成Ӟ非静态的全局变量在各个源文g中都是有效的?而静态全局变量则限制了其作用域Q? 卛_?定义该变量的源文件内有效Q? 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文g内,只能源文件内的函数公用, 因此 可以避免在其它源文g中引起错误。从以上分析可以看出Q?把局部变量改变ؓ静态变量后是改变了它的存储方式x变了它的生存期。把全局变量改变为静态变? 后是改变了它的作用域Q?限制了它的用范围。因此static q个说明W在不同的地ҎL作用是不同的?br />
4. static 函数…..

内部函数和外部函?br />
当一个源E序由多个源文gl成ӞQ语aҎ函数能否被其它源文g中的函数调用Q将函数分ؓ内部函数和外部函数?br />1 内部函数Q又U静态函敎ͼ
如果在一个源文g中定义的函数Q只能被本文件中的函数调用,而不能被同一E序其它文g中的函数调用Q这U函数称为内部函数?br />定义一个内部函敎ͼ只需在函数类型前再加一?#8220;static”关键字即可,如下所C:
static 函数cd 函数?函数参数?
{……}
关键?#8220;static”Q译成中文就?#8220;静态的”Q所以内部函数又U静态函数。但此处“static”的含义不是指存储方式Q而是指对函数的作用域仅局限于本文件?br />使用内部函数的好处是Q不同的人编写不同的函数Ӟ不用担心自己定义的函敎ͼ是否会与其它文g中的函数同名Q因为同名也没有关系?br />
2 外部函数
外部函数的定义:在定义函数时Q如果没有加关键?#8220;static”Q或冠以关键?#8220;extern”Q表C此函数是外部函敎ͼ
[extern] 函数cd 函数?函数参数?
{……}
调用外部函数Ӟ需要对其进行说明:
[extern] 函数cd 函数?参数cd?[Q函数名2(参数cd?)……]Q?br />
[案例]外部函数应用?br />Q?Q文件mainf.c
main()
{ extern void input(…),process(…),output(…);
input(…); process(…); output(…);
}

Q?Q文件subf1.c
……
extern void input(……) /*定义外部函数*/
{……}
Q?Q文件subf2.c
……
extern void process(……) /*定义外部 函数*/
{……}
Q?Q文件subf3.c
……
extern void output(……) /*定义外部函数*/
{……}

1、概q?br />
  static 声明的变量在C语言中有两方面的特征Q?br />
  1)、变量会被放在程序的全局存储ZQ这样可以在下一ơ调用的时候还可以保持原来的赋倹{这一Ҏ它与堆栈变量和堆变量的区别。  2)、变量用static告知~译器,自己仅仅在变量的作用范围内可见。这一Ҏ它与全局变量的区别?br />
  2、问题:Static的理?br />
  关于static变量Q请选择下面所有说法正的内容Q?br />
  A、若全局变量仅在单个C文g中访问,则可以将q个变量修改为静态全局变量Q以降低模块间的耦合度;

  B、若全局变量仅由单个函数讉KQ则可以这个变量改函数的静态局部变量,以降低模块间的耦合度;

  C、设计和使用讉K动态全局变量、静态全局变量、静态局部变量的函数Ӟ需要考虑重入问题Q?br />
  D、静态全局变量q大Q可那会D堆栈溢出?

  {案与分析:

  对于AQBQ根据本概q部分的说明b)Q我们知道,A,B都是正确的?br />
  对于CQ根据本概q部分的说明a)Q我们知道,C是正的Q所谓的函数重入问题Q下面会详细阐述Q?br />
  对于DQ静态变量放在程序的全局数据区,而不是在堆栈中分配,所以不可能D堆栈溢出QD是错误的?br />
  因此Q答案是A、B、C?br />
  3、问题:不可重入函数

  曄设计q如下一个函敎ͼ在代码检视的时候被提醒有bugQ因个函数是不可重入的,Z么?

unsigned int sum_int( unsigned int base )
{
 unsigned int index;
 static unsigned int sum = 0; // 注意Q是staticcd的?
 for (index = 1; index <= base; index++)
 {
  sum += index;
 }
 return sum;
}

  {案与分析:

  所谓的函数是可重入的(也可以说是可预测的)Q即Q只要输入数据相同就应生相同的输出?br />
   q个函数之所以是不可预测的,是因ؓ函数中用了static变量Q因为static变量的特征,q样的函数被UCؓQ带“内部存储?#8221;功能的的函数?因此如果我们需要一个可重入的函敎ͼ那么Q我们一定要避免函数中用static变量Q这U函C的static变量Q用原则是Q能不用量不用?br />
  上面的函数修改为可重入的函数很单,只要声明sum变量中的static关键字去掉,变量sum卛_Z个auto cd的变量,函数卛_Z个可重入的函数?br />
  当然Q有些时候,在函C是必要使用static变量的,比如当某函数的返回gؓ指针cdӞ则必Lstatic的局部变量的地址作ؓq回|若ؓautocdQ则q回为错指针?/div>原文Q?div>http://www.cnblogs.com/sideandside/archive/2007/03/29/692559.html

qLv蓝梦 2012-06-05 16:43 发表评论
]]>
netlink socket理解http://m.tkk7.com/jasmine214--love/archive/2012/06/01/379752.htmlqLv蓝梦qLv蓝梦Fri, 01 Jun 2012 08:25:00 GMThttp://m.tkk7.com/jasmine214--love/archive/2012/06/01/379752.htmlhttp://m.tkk7.com/jasmine214--love/comments/379752.htmlhttp://m.tkk7.com/jasmine214--love/archive/2012/06/01/379752.html#Feedback0http://m.tkk7.com/jasmine214--love/comments/commentRss/379752.htmlhttp://m.tkk7.com/jasmine214--love/services/trackbacks/379752.html

׃开发和l护内核的复杂性,只用最为关键同时对性能要求最高的代码才会攑֜内核中。其他的诸如GUI,理和控制代码,通常攑֜用户I间q行。这U将实现分离在内核和用户I间的思想在Linux中非常常见。现在的问题是内总码和用户代码如果彼此通信?/p>

{案是内核空间和用户I间存在的各UIPCҎQ例如系l调用,ioctlQproc文gpȝ和netlink socket。这文章讨论netlink socket和讨论其作ؓ一U网l特征IPC的优ѝ?/p>

?/p>

Netlink socket是用于内核和用户I间之间交换信息的特D的IPC机制。它提供了一U全复用的通信链\。和TCP/IP使用的地址族AF_INET?比,Netlink socket使用地址族AF_NETLINKQ每个的netlink socket特征定义协议cd在内核头文g中include/linux/netlink.h

以下是netlink socket当前支持的特征和他们的协议类型的子集Q?/p>

  • NETLINK_ROUTE:用户I间路由damonQ如BGPQOSPF,RIP和内核包转发模块的通信信道。用L间\由damon通过此种netlink协议cd更新内核路由?
  • NETLINK_FIREWALL:接收IPv4防火墙代码发送的?
  • NETLINK_NFLOG:用户I间iptable理工具和内核空间Netfilter模块的通信信道
  • NETLINK_ARPDQ用L间管理arp?

?什么以上的特征使用netlink而不是系l调用,ioctl或者proc文gpȝ来完成通信Qؓ新特性添加系l调用,ioctl和proc文gpȝ相对 而言是一Ҏ较复杂的工作Q我们冒着污染内核和损害系l稳定性的风险。netlink socket相对单:只有一个常量,协议cdQ需要加入到netlink.h中。然后,内核模块和用L序可以通过socketcd的APIq行通信?/p>

?其他socket API一PNetlink是异步的Q它提供了一个socket队列来^滑突发的信息。发送一个netlink消息的系l调用将消息排列到接受者的 netlink队列中然后调用接收者的接收处理函数。接收者,在接收处理函数的上下文中Q可以决定是否立卛_理该消息q是{待在另一个上下文中处理。不?netlinkQ系l调用需要同步处理。因此,如果我们使用了一个系l来传递一条消息到内核Q如果需要处理该条信息的旉很长Q那么内核调度粒度可以会?影响?/p>

在内怸实现的系l调用代码在~译时被静态的链接到内怸Q因此在一个可以动态加载的模块中包括系l调用代码是不合适的。在netlink socket中,内核中的netlink核心和在一个可加蝲的模块中没有~译时的怺依赖?/p>

netlink socket支持多播Q这也是其与其他交互手段相比较的优势之一。一个进E可以将一条消息广播到一个netlinkl地址。Q意多的进E可以监听那个组地址。这提供了一U从内核到用L间进行事件分发接q完的机制?/p>

?会话只能qL间应用发L角度来看Q系l调用和ioctl是单一的IPC。但是,如果一个内核模块有一个用L间应用的紧急消息,没有一U直接的Ҏ 来实现这些功能。通常Q应用需要阶D|的轮询内核来获取状态变化,管密集的轮询会有很大的开销。netlink通过允许内核初始化一个对话来优雅的解?q个问题。我们称之ؓnetlink的复用特性?/p>

最后,netlink提供了bsd socket风格的APIQ而这些API是被软g开发社区所熟知。因此,培训费用相较较小?/p>

和BSD路由socket的关p?/strong>

在BSC TCP/IP的栈实现中,有一U叫做\由套接字的特D的socket。它有AF_ROUTE地址族,PF_ROUTE协议族和SOCK_RAWsocketcd。在bsd中,路由套接字用于在内核路由表中d和删除\由?/p>

在Linux中,路由套接字的实现通过netlink套接字的NETLINK_ROUTE协议cd来支持。netlink套接字提供了bsd路由套接字的功能的超集?/p>

Netlink套接字API

?准的套接字APIQsocket(),sendmsg(),recvmsg()和close()Q可以被用户态程序用。可以通过查询man手册|看这 些函数的具体定义。这儿,我们讨论在netlink上下文中些API选择参数。对于写qTCP/IP套接字程序的人对q些API都应该非常熟悉?/p>

创徏一个套接字Q?/p>

int socket(int domainQint typeQ?int protocol)

domain指代地址族,AF_NETLINKQ套接字cd不是SOCK_RAW是SOCK_DGRAMQ因为netlink是一个面向数据报的服务?/p>

protocol选择该套接字使用那种netlink特征。以下是几种预定义的协议cdQNETLINK_ROUTE,NETLINK_FIREWALL,NETLINK_APRD,NETLINK_ROUTE6_FW。你也可以非常容易的d自己的netlink协议?/p>

?每一个协议类型最多可以定?2个多播组。每一个多播组用一个bit mask来表C,1<<i(0<= i<= 31)Q这在一l进E和内核q程协同完成一Q务时非常有用。发送多播netlink消息可以减少pȝ调用的数量,同时减少用来l护多播l成员信息的?担?/p>

bind()

和TCP/IP套接字一Pnetlink bind()API用来一个本地socket地址和一个打开的socket兌。一个netlink地址l构如下所C:

   1:  struct sockaddr_nl
   2:  {
   3:    sa_family_t    nl_family;  /* AF_NETLINK   */
   4:    unsigned short nl_pad;     /* zero         */
   5:    __u32          nl_pid;     /* process pid */
   6:    __u32          nl_groups;  /* mcast groups mask */
   7:  } nladdr;

当用bind()调用的时候,nl_pid域可以被赋gؓ调用q程的pid。nl_pid在这儿被当做该netlink套接字的本地地址。程序负责找一个独一无二?2位整数在填充该域。一U常见的做法是:

   1:  NL_PID Formula 1:  nl_pid = getpid();

公式一使用q程ID号作为nl_pid的|如果说该q程只需要一个netlink套接字,q是一个自然的选择。当一个进E中的不同线E需要同一个netlink协议多个netlink套接字。公式而可以用来生nl_pidP

   1:  NL_PID Formula 2: pthread_self() << 16 | getpid();

通过q种ҎQ同一个进E中的不同线E可以有同一Unetlink协议cd的netlink套接字。事实上Q即使在同一个线E中Q在可能使用同一U协议类型的多个套接字。开发者必要更有创造力来生一个唯一的nl_pid?/p>

如果应用x受发送给特定多播l的netlink消息Q所有感兴趣的多播组bit应该or在一Pq填充到nl_groups域。否则, nl_groups应该被显式至Ӟ说明该应用只接受到该应用的消息,填充完上q域Q?使用如下方式q行l定Q?/p>

   1:  bind(fd, (struct sockaddr*)&nladdr, sizeof(nladdr));

发送一条netlink消息

Z发送一条netlink消息到内核或者其他的用户I间q程Q另外一个struct sockaddr_nl nladdr需要作为目的地址Q这和用sendmsg()发送一个UDP包是一L。如果该消息是发送至内核的,那么nl_pid和nl_groups 都置?.

如果说消息时发送给另一个进E的单播消息Qnl_pid是另外一个进E的pidDnl_groups为零?/p>

如果消息是发送给一个或多个多播l的多播消息Q所有的目的多播l必bitmask必须orh从而Ş成nl_groups域。当我们填充struct msghdrl构用于sendmsgӞ使用如下Q?/p>

   1:  struct msghdr msg;
   2:  msg.msg_name = (void *)&(nladdr);
   3:  msg.msg_namelen = sizeof(nladdr);

netlink套接字也需要它自己本n的消息头Q这是ؓ了给所有协议类型的netlink消息提供一个统一的^台?/p>

因ؓLinux内核netlink核心假设每个netlink消息中存在着以下的头Q所有应用也必须在其发送的消息中提供这些头信息Q?/p>

   1:  struct nlmsghdr
   2:  {
   3:    __u32 nlmsg_len;   /* Length of message */
   4:    __u16 nlmsg_type;  /* Message type*/
   5:    __u16 nlmsg_flags; /* Additional flags */
   6:    __u32 nlmsg_seq;   /* Sequence number */
   7:    __u32 nlmsg_pid;   /* Sending process PID */
   8:  };

nlmsg_len指整个netlink消息的长度,包括头信息,q也是netlink核心所必须的。nlmsg_type用于应用但是对于 netlink核心而言其是透明的。nlmsg_flags用于l定附加的控制信息,其被netlink核心d和更新。nlmsg_seq?mlmsg_pidQ应用用来跟t消息,q些对于netlink核心也是透明的?/p>

所以一个netlink消息由消息头和消息负载组成。一旦一个消息被加入Q它加入到一个通过nlh指针指向的缓冲区。我们也可以消息发送到struct msghdr msgQ?/p>

   1:  struct iovec iov;
   2:   
   3:  iov.iov_base = (void *)nlh;
   4:  iov.iov_len = nlh->nlmsg_len;
   5:   
   6:  msg.msg_iov = &iov;
   7:  msg.msg_iovlen = 1;

l过以上步骤Q调用sendmsg()函数来发送netlink消息Q?/p>

   1:  sendmsg(fd, &msg, 0);
 
接收netlink消息

一个接收程序必d配一个够大的内存用于保存netlink消息头和消息负蝲。然后其填充struct msghdr msgQ然后用标准的recvmsg()函数来接收netlink消息Q假讄存通过nlh指针指向Q?/p>

   1:  struct sockaddr_nl nladdr;
   2:  struct msghdr msg;
   3:  struct iovec iov;
   4:   
   5:  iov.iov_base = (void *)nlh;
   6:  iov.iov_len = MAX_NL_MSG_LEN;
   7:  msg.msg_name = (void *)&(nladdr);
   8:  msg.msg_namelen = sizeof(nladdr);
   9:   
  10:  msg.msg_iov = &iov;
  11:  msg.msg_iovlen = 1;
  12:  recvmsg(fd, &msg, 0);

当消息被正确的接收之后,nlh应该指向刚刚接收到的netlink消息的头。nladdr应该包含接收消息的目的地址Q其中包括了消息发送者的 pid和多播组。同Ӟ宏NLMSG_DATA(nlh)Q定义在netlink.h中,q回一个指向netlink消息的负载的指针?close(fd)调用关闭fd描述W所标识的socket?/p>

内核I间netlink API

内核I间的netlinkAPI在内怸被netlink核心支持Q即net/core/af_netlink.c。从内核角度看,q些API不同 于用L间的API。这些API可以被内核模块用从而存取netlink套接字与用户I间E序通信。除非你使用现存的netlink套接字协议类型,?则你必须通过在netlink.h中定义一个常量来d你自q协议cd。例如,我们需要添加一个netlink协议cd用于试Q则?netlink.h中加入下面的语句Q?/p>

   1:  #define NETLINK_TEST  17

之后Q亦可以在linux内核中的M地方引用d的协议类型?/p>

在用L_我们使用socket()来创Z个netlink套接字,但是在内核空_我们使用如下的APIQ?/p>

   1:  truct sock *
   2:  netlink_kernel_create(int unit,
   3:             void (*input)(struct sock *sk, int len));

参数unitQ即为netlink协议cdQ如NETLINK_TESTQ回调函C在消息到达netlink套接字时调用。当用户态程序发送一个NETLINK_TEST协议cd的消息给内核Ӟinput()函数被调用。下面是一个实现回调函数的例子Q?/p>

   1:  void input (struct sock *sk, int len)
   2:  {
   3:   struct sk_buff *skb;
   4:   struct nlmsghdr *nlh = NULL;
   5:   u8 *payload = NULL;
   6:   
   7:   while ((skb = skb_dequeue(&sk->receive_queue))
   8:         != NULL) {
   9:   /* process netlink message pointed by skb->data */
  10:   nlh = (struct nlmsghdr *)skb->data;
  11:   payload = NLMSG_DATA(nlh);
  12:   /* process netlink message with header pointed by
  13:    * nlh    and payload pointed by payload
  14:    */
  15:   }
  16:  }

input()函数在发送进E的sendmsg()pȝ调用上下文执行。如果在input中处理netlink消息非常快,那是没有问题的。如果处 理netlink消息需要很长的旉Q我们希望在input()外面处理消息来避免阻塞其他系l调用进入内核。事实上Q我们可以用一个指定的内核U程?来不断执行以下的步骤。用skb=skb_recv_datagram(nl_sk)Q其中nl_sk?netlink_kernel_create()q回的netlink套接字。然后,处理由skb->data指向的netlink消息?/p>

以下的内核线E在没有netlink消息在nl_sk中时睡眠Q在回调函数input中,我们只要唤醒睡眠的内核线E,如下所C:

   1:  void input (struct sock *sk, int len)
   2:  {
   3:    wake_up_interruptible(sk->sleep);
   4:  }

q是一个更h扩展性的用户和内栔R信的模型。其也提高了上下文交换的_度?/p>

在内怸发送netlink消息

真如在用L间中一P在发送一个netlink消息旉要设|源和目的netlink消息地址。假设socket~存中包含了要发送的netlink消息Q本地地址可以通过以下方式讄Q?/p>

   1:  NETLINK_CB(skb).groups = local_groups;
   2:  NETLINK_CB(skb).pid = 0;   /* from kernel */

目的地址可以如下讄Q?/p>

   1:  NETLINK_CB(skb).dst_groups = dst_groups;
   2:  NETLINK_CB(skb).dst_pid = dst_pid;

q些信息不是存储在skb->dataQ而是存储在skb中的netlink控制块中。发送一个消息,使用Q?/p>

   1:  int
   2:  netlink_unicast(struct sock *ssk, struct sk_buff
   3:                  *skb, u32 pid, int nonblock);

其中ssk是netlink_kernel_createq回的netlink套接字,skb->data指向netlink要发送的消息而pid是接受该消息的用L序id。nonblock用于标识在接收缓存不可用ӞAPI是阻塞还是立卌回失败?/p>

你也可以发送一个多播消息。以下的API用于消息传送到指定的进E,同时多播x定的多播l?/p>

   1:  void
   2:  netlink_broadcast(struct sock *ssk, struct sk_buff
   3:           *skb, u32 pid, u32 group, int allocation);

group是所有接收多播组的bitmask。allocation是内核内存分配的cd。通常QGFP_ATOMIC用于中断上下文而在其他情况下是用GFP_KERNEL.只是因ؓAPI可能需要分配一个或者多个套接字~存来克隆多播消息?/p>

在内怸关闭一个netlink套接?/strong>

l定了netlink_kernel_create()函数q回的struct sock *nl_sk,我们可以通过调用以下的API关闭netlink套接字?/p>

   1:  sock_release(nl_sk->socket);

在内核和用户态用单播通信

   1:  #include <sys/socket.h>
   2:  #include <linux/netlink.h>
   3:   
   4:  #define MAX_PAYLOAD 1024  /* maximum payload size*/
   5:  struct sockaddr_nl src_addr, dest_addr;
   6:  struct nlmsghdr *nlh = NULL;
   7:  struct iovec iov;
   8:  int sock_fd;
   9:   
  10:  void main() {
  11:   sock_fd = socket(PF_NETLINK, SOCK_RAW,NETLINK_TEST);
  12:   
  13:   memset(&src_addr, 0, sizeof(src_addr));
  14:   src__addr.nl_family = AF_NETLINK;
  15:   src_addr.nl_pid = getpid();  /* self pid */
  16:   src_addr.nl_groups = 0;  /* not in mcast groups */
  17:   bind(sock_fd, (struct sockaddr*)&src_addr,
  18:        sizeof(src_addr));
  19:   
  20:   memset(&dest_addr, 0, sizeof(dest_addr));
  21:   dest_addr.nl_family = AF_NETLINK;
  22:   dest_addr.nl_pid = 0;   /* For Linux Kernel */
  23:   dest_addr.nl_groups = 0; /* unicast */
  24:   
  25:   nlh=(struct nlmsghdr *)malloc(
  26:                   NLMSG_SPACE(MAX_PAYLOAD));
  27:   /* Fill the netlink message header */
  28:   nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
  29:   nlh->nlmsg_pid = getpid();  /* self pid */
  30:   nlh->nlmsg_flags = 0;
  31:   /* Fill in the netlink message payload */
  32:   strcpy(NLMSG_DATA(nlh), "Hello you!");
  33:   
  34:   iov.iov_base = (void *)nlh;
  35:   iov.iov_len = nlh->nlmsg_len;
  36:   msg.msg_name = (void *)&dest_addr;
  37:   msg.msg_namelen = sizeof(dest_addr);
  38:   msg.msg_iov = &iov;
  39:   msg.msg_iovlen = 1;
  40:   
  41:   sendmsg(fd, &msg, 0);
  42:   
  43:   /* Read message from kernel */
  44:   memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
  45:   recvmsg(fd, &msg, 0);
  46:   printf(" Received message payload: %s\n",
  47:      NLMSG_DATA(nlh));
  48:   
  49:   /* Close Netlink Socket */
  50:   close(sock_fd);
  51:  }
   1:  struct sock *nl_sk = NULL;
   2:   
   3:  void nl_data_ready (struct sock *sk, int len)
   4:  {
   5:    wake_up_interruptible(sk->sleep);
   6:  }
   7:   
   8:  void netlink_test() {
   9:   struct sk_buff *skb = NULL;
  10:   struct nlmsghdr *nlh = NULL;
  11:   int err;
  12:   u32 pid;
  13:   
  14:   nl_sk = netlink_kernel_create(NETLINK_TEST,
  15:                                     nl_data_ready);
  16:   /* wait for message coming down from user-space */
  17:   skb = skb_recv_datagram(nl_sk, 0, 0, &err);
  18:   
  19:   nlh = (struct nlmsghdr *)skb->data;
  20:   printk("%s: received netlink message payload:%s\n",
  21:          __FUNCTION__, NLMSG_DATA(nlh));
  22:   
  23:   pid = nlh->nlmsg_pid; /*pid of sending process */
  24:   NETLINK_CB(skb).groups = 0; /* not in mcast group */
  25:   NETLINK_CB(skb).pid = 0;      /* from kernel */
  26:   NETLINK_CB(skb).dst_pid = pid;
  27:   NETLINK_CB(skb).dst_groups = 0;  /* unicast */
  28:   netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT);
  29:   sock_release(nl_sk->socket);
  30:  }

在内核和用户态用单播通信

   1:  #include <sys/socket.h>
   2:  #include <linux/netlink.h>
   3:   
   4:  #define MAX_PAYLOAD 1024  /* maximum payload size*/
   5:  struct sockaddr_nl src_addr, dest_addr;
   6:  struct nlmsghdr *nlh = NULL;
   7:  struct iovec iov;
   8:  int sock_fd;
   9:   
  10:  void main() {
  11:   sock_fd=socket(PF_NETLINK, SOCK_RAW, NETLINK_TEST);
  12:   
  13:   memset(&src_addr, 0, sizeof(local_addr));
  14:   src_addr.nl_family = AF_NETLINK;
  15:   src_addr.nl_pid = getpid();  /* self pid */
  16:   /* interested in group 1<<0 */
  17:   src_addr.nl_groups = 1;
  18:   bind(sock_fd, (struct sockaddr*)&src_addr,
  19:        sizeof(src_addr));
  20:   
  21:   memset(&dest_addr, 0, sizeof(dest_addr));
  22:   
  23:   nlh = (struct nlmsghdr *)malloc(
  24:                            NLMSG_SPACE(MAX_PAYLOAD));
  25:   memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
  26:   
  27:   iov.iov_base = (void *)nlh;
  28:   iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
  29:   msg.msg_name = (void *)&dest_addr;
  30:   msg.msg_namelen = sizeof(dest_addr);
  31:   msg.msg_iov = &iov;
  32:   msg.msg_iovlen = 1;
  33:   
  34:   printf("Waiting for message from kernel\n");
  35:   
  36:   /* Read message from kernel */
  37:   recvmsg(fd, &msg, 0);
  38:   printf(" Received message payload: %s\n",
  39:          NLMSG_DATA(nlh));
  40:   close(sock_fd);

41: }

 

   1:  #define MAX_PAYLOAD 1024
   2:  struct sock *nl_sk = NULL;
   3:   
   4:  void netlink_test() {
   5:   sturct sk_buff *skb = NULL;
   6:   struct nlmsghdr *nlh;
   7:   int err;
   8:   
   9:   nl_sk = netlink_kernel_create(NETLINK_TEST,
  10:                                 nl_data_ready);
  11:   skb=alloc_skb(NLMSG_SPACE(MAX_PAYLOAD),GFP_KERNEL);
  12:   nlh = (struct nlmsghdr *)skb->data;
  13:   nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
  14:   nlh->nlmsg_pid = 0;  /* from kernel */
  15:   nlh->nlmsg_flags = 0;
  16:   strcpy(NLMSG_DATA(nlh), "Greeting from kernel!");
  17:   /* sender is in group 1<<0 */
  18:   NETLINK_CB(skb).groups = 1;
  19:   NETLINK_CB(skb).pid = 0;  /* from kernel */
  20:   NETLINK_CB(skb).dst_pid = 0;  /* multicast */
  21:   /* to mcast group 1<<0 */
  22:   NETLINK_CB(skb).dst_groups = 1;
  23:   
  24:   /*multicast the message to all listening processes*/
  25:   netlink_broadcast(nl_sk, skb, 0, 1, GFP_KERNEL);
  26:   sock_release(nl_sk->socket);
  27:  }

Netlink可靠性机?/strong>

在基于netlink的通信中,有两U可能的情Ş会导致消息丢失:

  1. 内存耗尽Q没有够多的内存分配给消息
  2. ~存复写Q接攉列中没有I间存储消息Q这在内核空间和用户I间之间通信时可能会发生

~存复写在以下情况很可能会发生:

  1. 内核子系l以一个恒定的速度发送netlink消息Q但是用h监听者处理过?/li>
  2. 用户存储消息的空间过?/li>

   如果netlink传送消息失败,那么recvmsg()函数会返回No  buffer space available(ENOBUFS)错误。那么,用户I间q程知道它丢׃信息Q如果内核子pȝ支持dump操作Q它可以重新同步来获取最新的消息。在 dump操作中,netlink通过在每ơ调用recvmsg()函数时传输一个包的流控机制来防止接收队列的复写。改包消耗一个内存页Q其包含了几个多 部分netlink消息。图6中的序列图显CZ在一个重新同步的q程中所使用的dump操作?/p>

 

image

另一斚wQ缓存复写不会发生在用户和内核空间的通信中,因ؓsendmsg()同步的将netlink消息发送到内核子系l。如果用的是阻塞套接字Q那么netlink在从用户I间到内核空间的通信时完全可靠的Q因为内存分配可以等待,所以没有内存耗尽的可能?/p>

netlink也可以提供应{机制。所以如果用L间进E发送了一个设|了NLM_F_ACK标志的请求,netlink会在netlink错误消息中报告给用户I间刚才h操作的结果?/p>

从用L间的角度来看QNetlink套接字在通用的BSD套接字接口之上实现。因此,netlink套接字编E与通用的TCP/IP~程cM。但是,我们也应该考虑几个与netlink相关的特D问题:

  1. netlink套接字没有像其他协议一样对用户I间隐藏协议l节。事实上Qnetlink传递的是整个消息,包括netlink头和其他?息。因此,q就D了数据处理函C通用的TCP/IP套接字不同,所以用h程序必L据其格式解析和构建netlink信息。然而,没有标准的工h 完成q些工作Q所以你必须实现自己的函数或者用一些现成的库?/li>
  2. 来自netlink和内核子pȝ的错误不是通过recvmsg()函数q回的整数值来表现的。事实上Q错误信息时被包装在netlink错误 消息中的。唯一的例外是(ENOBUFS)错误Q该错误不是包装在netlink消息中,因ؓ报告该错误的原因是我们没有_的空间来~存新的 netlink消息。标准的通用套接字错误,?EAGAIN),通常和其他轮询原语,例如poll()和select()Q也是通过recvmsg() q回整数倹{?/li>
原文Q?div>http://my.oschina.net/longscu/blog/59534

qLv蓝梦 2012-06-01 16:25 发表评论
]]>
句柄的理?/title><link>http://m.tkk7.com/jasmine214--love/archive/2012/05/31/379689.html</link><dc:creator>qLv蓝梦</dc:creator><author>qLv蓝梦</author><pubDate>Thu, 31 May 2012 12:04:00 GMT</pubDate><guid>http://m.tkk7.com/jasmine214--love/archive/2012/05/31/379689.html</guid><wfw:comment>http://m.tkk7.com/jasmine214--love/comments/379689.html</wfw:comment><comments>http://m.tkk7.com/jasmine214--love/archive/2012/05/31/379689.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/jasmine214--love/comments/commentRss/379689.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/jasmine214--love/services/trackbacks/379689.html</trackback:ping><description><![CDATA[<div><p><span style="font-size:13pt">从广义上Q能够从一个数值拎起一大堆数据的东襉K可以叫做句柄。句柄的英文?Handle"Q本义就??Q只是在计算机科学中Q被特别地翻译成"句柄"Q其实还是个"?。从一个小东西拎v一大堆东西Q这N不像是个"?吗? </span></p><p><span style="font-size:13pt">然后Q指针其实也是一U?句柄"Q只是由于指针同时拥有更Ҏ的含?#8212;—实实在在地对应内存里C个地址——所以,通常不把指针说成?句柄"。但指针也有着能从一?2位的值引用到一大堆数据的作用,q不是句柄又是什么? </span></p><p><span style="font-size:13pt">Windowspȝ中有许多内核对象Q这里的对象不完全等??面向对象E序设计"一词中?对象"Q虽然实质上q真差不多)Q比如打开的文Ӟ创徏的线E,E序的窗口,{等。这些重要的对象肯定不是4个字节或?8个字节以完全描q的Q他们拥有大量的属性。ؓ了保存这样一?对象"的状态,往往需要上癄至上千字节的内存I间Q那么怎么在程序间或程序内部的子过 E(函数Q之间传递这些数据呢Q拖着q成百上千的字节拯来拷贝去吗?昄会浪Ҏ率。那么怎么办?当然传递这些对象的首地址是一个办法,但这臛_有两?~点Q?</span></p><ol style="margin-left: 36pt"><li><div><span style="font-size:13pt">暴露了内核对象本w,使得E序Q而不是操作系l内核)也可以Q意地修改对象地内部状态(首地址都知道了Q还有什么不能改的?Q,q显然是操作pȝ内核所不允许的Q?</span></div></li><li><div><span style="font-size:13pt">操作pȝ有定期整理内存的责QQ如果一些内存整理过一ơ后Q对象被搬走了怎么办? </span></div></li></ol><p><span style="font-size:13pt">所以,Windows操作pȝ采用进一步的间接Q在q程的地址I间中设一张表Q表里头专门保存一些编号和p个编号对应一个地址Q而由那个地址d用实际的对象Q这个编可那个地址在数g没有M规律性的联系Q纯_Ҏ个映而已?</span></p><p><span style="font-size:13pt">在Windowspȝ中,q个~号叫?句柄"? </span></p><p> </p><p><span style="font-size:13pt">Handle在Windows中的含义很广泛,以下关于谈到的Handle除非特别说明Q将仅限于进E、线E的上下文中?</span></p><p><span style="font-size:13pt">1、先来谈谈Handle </span></p><p><span style="font-size:13pt">Handle本n是一?2位的无符h敎ͼ它用来代表一个内 核对象。它q不指向实际的内核对象,用户模式下的E序永远不可能获得一个内核对象的实际地址Q一般情况下Q。那么Handle的意义何在?它实际上是作?一个烦引在一个表中查扑֯应的内核对象的实际地址。那么这个表在哪里呢Q每?span style="text-decoration:underline">q程</span>都有q样的一个表Q叫句柄表。该表的W一就是进E自q句柄Q这也是Z么你调用GetCurrentProcess()Lq回0x7FFFFFFF原因?</span></p><p><span style="font-size:13pt">单地_Handle是一U用?间接"代表一个内核对象的整数倹{你可以在程序中使用handle来代表你惌操作的内核对象。这里的内核对象包括Q事ӞEventQ、线E、进E、Mutex{等。我们最常见的就是文件句柄(file handleQ?</span></p><p><span style="font-size:13pt">另外要注意的是,Handle仅在其所属的q程中才有意义。将一个进E拥有的handle传给另一个进E没有Q何意义,如果非要q么做,则需要用DuplicateHandle()Q在多个q程间传递Handle是另外一个话题了Q与q里要讨论的无关?</span></p><p><span style="font-size:13pt">2、进EID </span></p><p><span style="font-size: 13pt;">首先Q进EID是一?2位无W号整数Q每个进E都有这L一个IDQƈ且该ID在系l范围内是唯一的。系l用该ID来唯一定一个进E?</span></p><p><span style="font-size:13pt">深入些说Q系l可能用进EID来计代表该q程的内核对象的基地址Q及EPROCESSl构的基地址Q,具体的计公式你可以去问微Y的OS开发h员?</span></p><p><span style="font-size:13pt">3、HINSTANCE </span></p><p><span style="font-size:13pt">HINSTANCE也是一?2无符h敎ͼ它表C程序加载到内存中的基地址?/span></p></div>原文Q?div>http://www.cppblog.com/mymsdn/archive/2011/11/28/74221.html</div><img src ="http://m.tkk7.com/jasmine214--love/aggbug/379689.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/jasmine214--love/" target="_blank">qLv蓝梦</a> 2012-05-31 20:04 <a href="http://m.tkk7.com/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://m.tkk7.com/jasmine214--love/archive/2012/05/31/379688.html</link><dc:creator>qLv蓝梦</dc:creator><author>qLv蓝梦</author><pubDate>Thu, 31 May 2012 11:52:00 GMT</pubDate><guid>http://m.tkk7.com/jasmine214--love/archive/2012/05/31/379688.html</guid><wfw:comment>http://m.tkk7.com/jasmine214--love/comments/379688.html</wfw:comment><comments>http://m.tkk7.com/jasmine214--love/archive/2012/05/31/379688.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/jasmine214--love/comments/commentRss/379688.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/jasmine214--love/services/trackbacks/379688.html</trackback:ping><description><![CDATA[<div>    一.什么是Socket<br />  1.所谓Socket通常也称?#8220;套接?#8221;Q用于描qIP地址和端口,是一个通信q的句柄<br />  2.应用E序通常通过“套接?#8221;向网l发送请求或者应{网l请?p>  ?Socket基本通信模型</p><p align="center"><img src="http://www.jucoder.com/static/upload/day_111025/201110251121488483.jpg" alt="<a href='/bbs/forum-0-20601-206.html' >android</a>开发之Socket~程" border="0" height="372" width="500" /></p><p align="left">  ?使用ZTCP协议的Socket<br />  一个客L要发起一ơ通信Q首先必ȝ道运行服务器端的LIP地址。然后由|络基础设施利用目标地址Q将客户端发送的信息传递到正确的主ZQ在<a >java</a>中,地址可以׃个字W串来定义,q个字符串可以数字型的地址Q比?92.168.1.1Q,也可以是L名(example.comQ?br />  在Java当中InetAddresscM表了一个网l目标地址Q包括主机名和数字类型的地址信息。下面ؓ大家介绍一下基于TCP协议操作Socket的APIQ?/p><p align="left">  ServerSocketQ这个类是实C一个服务器端的SocketQ利用这个类可以监听来自|络的请求?br />  a)创徏ServerSocket的方法:<br />  ServerSocket(Int localPort)<br />  ServerSocket(int localport,int queueLimit)<br />  ServerSocket(int localport,int queueLimit,InetAddress localAddr)<br />  创徏一个ServerSocket必须指定一个端口,以便客户端能够向该端口号发送连接请求。端口的有效范围?-65535<br />  b)ServerSocket操作<br />  Socket accept()<br />  void close<br />  accept()ҎZ一个传入的q接h创徏Socket实例Qƈ已成功q接的Socket实例q回l服务器套接字,如果没有q接hQaccept()Ҏ阻塞等待;<br />  closeҎ用于关闭套接?/p><p align="left">  SocketQ?br />  a)创徏Socket的方法:<br />  SocketQInetAddress remoteAddress,int remotePortQ?br />  利用Socket的构造函敎ͼ可以创徏一个TCP套接字后Q先q接到指定的q程地址和端口号?br />  b)操作Socket的方?br />  InputStream getInputStream()<br />  OutputStream getOutputStream()<br />  void close()</p><p align="left">  操作TCPsocket的图C: </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">  使用ZUDP的Socket<br />  a)创徏DatagramPacket<br />  DatagramSocket(byte [] data,int offset,int length,InetAddress remoteAddr,int remotePort)<br />  该构造函数创Z个数据报文对象,数据包含在第一个参数当?br />  b)创徏DatagramSocket创徏<br />  DatagramSocket(int localPort)<br />  以上构造函数将创徏一个UDP套接字;<br />  c)DatagramSocketQ发送和接受<br />  void send(DatagramPacket packet)<br />  void receive(DatagramPacket packet)<br />  send()Ҏ用来发送DatagramPacket实例。一旦创接,数据报将发送到该套接字所q接的地址Q?br />  receive()Ҏ阻塞等待,知道接收到数据报文,q将报文中的数据复制到指定的DatagramPacket实例?/p><p align="left">原文 :<div>http://www.jucoder.com/bbs/thread-4630-0-0.html</div><br /></p></div><img src ="http://m.tkk7.com/jasmine214--love/aggbug/379688.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/jasmine214--love/" target="_blank">qLv蓝梦</a> 2012-05-31 19:52 <a href="http://m.tkk7.com/jasmine214--love/archive/2012/05/31/379688.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于C语言中return的一些ȝhttp://m.tkk7.com/jasmine214--love/archive/2011/03/09/346028.htmlqLv蓝梦qLv蓝梦Wed, 09 Mar 2011 07:06:00 GMThttp://m.tkk7.com/jasmine214--love/archive/2011/03/09/346028.htmlhttp://m.tkk7.com/jasmine214--love/comments/346028.htmlhttp://m.tkk7.com/jasmine214--love/archive/2011/03/09/346028.html#Feedback0http://m.tkk7.com/jasmine214--love/comments/commentRss/346028.htmlhttp://m.tkk7.com/jasmine214--love/services/trackbacks/346028.html在函CQ如果碰到return 语句Q那么程序就会返回调用该函数的下一条语句执行,也就是说跛_函数的执?/font>Q回到原来的地方l箋执行下去。但是如果是在主函数中碰到return语句Q那么整个程序就会停止,退出程序的执行?/strong>

--------------------------------------------------------------------------------------------------------------------------------------------------------------------

return是C++预定义的语句Q它提供了种植函数执行的一U放大。当return语句提供了一个值时Q这个值就成ؓ函数的返回?

说到return,有必要提及主函数的定?下面是从|络上找到的资料,好好消化?对了解主函数中返回值的理解有很大的帮助.

很多人甚臛_面上的一些书c,都用了void main( ) Q其实这是错误的。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.Q?void main( ) 从来׃存在?C++ 或?C Q。下面我分别说一?C ?C++ 标准中对 main 函数的定义?


1. C
?C89 中,main( ) 是可以接受的。Brian W. Kernighan ?Dennis M. Ritchie 的经典巨?The C programming Language 2eQ《C E序设计语言W二版》)用的是 main( )。不q在最新的 C99 标准中,只有以下两种定义方式是正的Q?
int main( void )
int main( int argc, char *argv[] )
Q参考资料:ISO/IEC 9899:1999 (E) Programming languages ?C 5.1.2.2.1 Program startupQ?
当然Q我们也可以做一点小的改动。例如:char *argv[] 可以写成 char **argvQargv ?argc 可以Ҏ别的变量名(?intval ?charvalQ,不过一定要W合变量的命名规则?

如果不需要从命o行中获取参数Q请用int main(void) Q否则请用int main( int argc, char *argv[] ) ?br /> main 函数的返回值类型必L int Q这栯回值才能传递给E序的激z者(如操作系l)?/font>

如果 main 函数的最后没有写 return 语句的话QC99 规定~译器要自动在生成的目标文g中(?exe 文gQ加入return 0; Q表C程序正帔R出。不q,我还是徏议你最好在main函数的最后加上return 语句Q虽然没有这个必要,但这是一个好的习惯。注意,vc6不会在目标文件中加入return 0; Q大概是因ؓ vc6 ?98 q的产品Q所以才不支持这个特性。现在明白我Z么徏议你最好加?return 语句了吧Q不q,gcc3.2QLinux 下的 C ~译器)会在生成的目标文件中加入 return 0; ?

2. C++
C++98 中定义了如下两种 main 函数的定义方式:
int main( )
int main( int argc, char *argv[] )
Q参考资料:ISO/IEC 14882(1998-9-01)Programming languages ?C++ 3.6 Start and terminationQ?
int main( ) {同?C99 中的 int main( void ) Qint main( int argc, char *argv[] ) 的用法也?C99 中定义的一栗同Pmain 函数的返回值类型也必须是int。如果main函数的末没写return语句QC++98 规定~译器要自动在生成的目标文g中加?return 0; 。同Pvc6 也不支持q个Ҏ,但是 g++3.2QLinux 下的 C++ ~译器)支持?

3. 关于 void main
?C ?C++ 中,不接收Q何参C不返回Q何信息的函数原型?#8220;void foo(void);”。可能正是因个,所以很多h都误认ؓ如果不需要程序返回值时可以把main函数定义成void main(void) 。然而这是错误的Qmain 函数的返回值应该定义ؓ int cdQC ?C++ 标准中都是这栯定的。虽然在一些编译器中,void main 可以通过~译Q如 vc6Q,但ƈ非所有编译器都支?void main Q因为标准中从来没有定义q?void main 。g++3.2 中如? main 函数的返回g?int cdQ就Ҏ通不q编译。?gcc3.2 则会发出警告。所以,如果你想你的E序拥有很好的可UL性,请一定要? int main ?

4. q回值的作用
main 函数的返回值用于说明程序的退出状态。如果返?0Q则代表E序正常退出,否则代表E序异常退出。下面我们在 winxp 环境下做一个小实验。首先编译下面的E序Q?
int main( void )
{
return 0;
}
然后打开附g里的“命o提示W?#8221;Q在命o行里q行刚才~译好的可执行文Ӟ然后输入“echo %ERRORLEVEL%”Q回车,可以看到程序的q回gؓ 0 。假讑ֈ才编译好的文件是 a.exe Q如果输?#8220;a && dir”Q则会列出当前目录下的文件夹和文件。但是如果改?#8220;return -1”Q或者别的非 0 |重新~译后输?#8220;a && dir”Q则 dir 不会执行。因?&& 的含义是Q如?&& 前面的程序正帔R出,则l执? && 后面的程序,否则不执行。也是_利用E序的返回|我们可以控制要不要执行下一个程序?strong>q就?int main 的好?/strong>? 如果你有兴趣Q也可以?main 函数的返回值类型改成非 int cdQ如 floatQ,重新~译后执?#8220;a && dir”Q看看会出现什么情况,xZ么会出现那样的情c顺便提一下,如果输入 a || dir 的话Q则表示如果 a 异常退出,则执?dir ?


5. 那么 int main(intargc,char*argv[],char*envp[])呢?
  q当然也不是标准 C 里面定义的东西!char*envp[] 是某些编译器提供的扩展功能,用于获取pȝ的环境变量。因Z是标准,所以ƈ非所有编译器都支持,故而移植性差Q不推荐使用?
Cq里,你应该了解ؓ什么主函数定义?intq回cd,而且函数体里面有return 0;q个语句了吧.
下面具体说说我对return的应用的理解?br />
只要一个函数的q回值是数字型的,那么可以返?(即return 0),其实你返回多都没问题?font color="#ff0000">一 般情况下QC++做出来的函数都要求返回一个|当函数执行正常,且达C一般情况下的目的,那么p?表示正确的调用了该函敎ͼq个0是q回l主? 函数以通知没有出错的;如果函数调用中出错,或者没有按照一般情冉|行,那么p?Q以告知主调函数采取响应{略Q如果你在某个函数所在类的定义所在的 头文件中定义了一l状态|一般都是负整数Q,那么函数可以返回不同的g告之主调函数具体发生了什么异常或错误Q这U情况一般用于函数功能独立性较? 的的情况?/font>所以一般不鼓励把函数返回类型定义ؓvoidQ至返回应该是intQ而在函数的最后加上return 0.语句Q?
int func(参数列表)
{
……
……
……
Return 0;
}
在函CQ如果碰到return 语句Q那么程序就会返回调用该函数的下一条语句执行,也就是说跛_函数的执行,回到原来的地方l执行下厅R但是如果是在主函数中碰到return语句Q那么整个程序就会停止,退出程序的执行?
  如果你定义一个函数有q回cdQ可以想下面那样调用Q?
int func()
{
int value;
……
……
……
return value;
}
int main()
{
int intvalue;
intvalue=func();
……
……
teturn 0;
}


return语句后面具体是什么内容,q就要具体情况具体分析了Q?/u>
Q?Q?在返回类型是char的函CQreturn后应该是charcd的|
Q?Q?在返回类型是int的函CQ如果是要停止函数的调用Q最好应该ؓ0Q其他的按照你的目的而定Q只要是int cdp?
Q?Q?在返回类型是l构cd的函CQreturn后应该是l构的一个实例对象?
MQ函数定义ؓ什么样的返回类型,该函Creturn后就应该是相应类型的倹{?br /> 原文Qhttp://blog.ednchina.com/jiereliyi/113757/message.aspx


qLv蓝梦 2011-03-09 15:06 发表评论
]]>
C--strrchr()函数的作?/title><link>http://m.tkk7.com/jasmine214--love/archive/2011/03/09/346021.html</link><dc:creator>qLv蓝梦</dc:creator><author>qLv蓝梦</author><pubDate>Wed, 09 Mar 2011 05:48:00 GMT</pubDate><guid>http://m.tkk7.com/jasmine214--love/archive/2011/03/09/346021.html</guid><wfw:comment>http://m.tkk7.com/jasmine214--love/comments/346021.html</wfw:comment><comments>http://m.tkk7.com/jasmine214--love/archive/2011/03/09/346021.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/jasmine214--love/comments/commentRss/346021.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/jasmine214--love/services/trackbacks/346021.html</trackback:ping><description><![CDATA[函数? strrchr <p style="text-indent: 2em;">  ?? strrchr()函数的作用是Q查找一个字W串在另一个字W串中末ơ出现的位置Q?/p> <p style="text-indent: 2em;">  q返回从字符串中的这个位|vQ?一直到字符串结束的所有字W?/p> <p style="text-indent: 2em;">  如果未能扑ֈ指定字符Q那么函数将q回NULL?</p> <p style="text-indent: 2em;">  ?? char *strrchr(char *str, char c); </p> <p style="text-indent: 2em;">  E序? </p> <p style="text-indent: 2em;">  #include <string.h> </p> <p style="text-indent: 2em;">  #include <stdio.h> </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;">  q行l果是:The character r is at positionQ?2</p> <p style="text-indent: 2em;">原文Q?br /> </p> <img src ="http://m.tkk7.com/jasmine214--love/aggbug/346021.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/jasmine214--love/" target="_blank">qLv蓝梦</a> 2011-03-09 13:48 <a href="http://m.tkk7.com/jasmine214--love/archive/2011/03/09/346021.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C--fopen() ?fclose()函数http://m.tkk7.com/jasmine214--love/archive/2011/03/09/346005.htmlqLv蓝梦qLv蓝梦Wed, 09 Mar 2011 02:43:00 GMThttp://m.tkk7.com/jasmine214--love/archive/2011/03/09/346005.htmlhttp://m.tkk7.com/jasmine214--love/comments/346005.htmlhttp://m.tkk7.com/jasmine214--love/archive/2011/03/09/346005.html#Feedback0http://m.tkk7.com/jasmine214--love/comments/commentRss/346005.htmlhttp://m.tkk7.com/jasmine214--love/services/trackbacks/346005.html

fopen()和fclose()的用?/strong>

1Qfopen()函数的用?/strong>

fopen函数用于打开文g, 其调用格式ؓ:

FILE *fopen(char *filename, *type);

fopen()函数中第一个Ş式参数表C文件名, 可以包含路径和文件名两部分。如:

"B:TEST.DAT"

"C:\\TC\\TEST.DAT"

注意Q如果将路径写成"C:\TC\TEST.DAT"是不正确? q一点要特别注意?br />

fopen函数用来打开一个文Ӟ其调用的一般Ş式ؓQ?nbsp;文g指针?fopen(文g名,使用文g方式)

 其中Q?#8220;文g指针?#8221;必须是被说明为FILE cd的指针变量,“文g?#8221;是被打开文g的文件名?nbsp;

“使用文g方式”是指文g的类型和操作要求?#8220;文g?#8221;是字W串帔R或字W串数组。例如: 

FILE *fpQ?br />
fp=("file a","r");

其意义是在当前目录下打开文gfile aQ?nbsp;只允许进?#8220;?#8221;操作Qƈ使fp指向该文件?br />
又如Q?br />
FILE *fphzk

fphzk=("c:\\hzk16',"rb")

其意义是打开C驱动器磁盘的根目录下的文件hzk16Q?nbsp;q是一个二q制文gQ只允许按二q制方式q行L作?br />
两个反斜U?#8220;\\ ”中的W一个表C{义字W,W二个表C根目录。用文件的方式共有12U,下面l出了它们的W号和意义?br />
W二个Ş式参数表C打开文g的类型。关于文件类型的规定参见下表?nbsp;

















                       ?nbsp;文g操作cd

    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

          字符                含义

    ────────────────────────────

           "r"           打开文字文g只读

           "w"           创徏文字文g只写

           "a"           增补, 如果文g不存在则创徏一?/p>

           "r+"          打开一个文字文件读/?/p>

           "w+"          创徏一个文字文件读/?/p>

           "a+"          打开或创Z个文件增?/p>

           "b"           二进制文?可以和上面每一合?

           "t"           文这文g(默认?

    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 文g使用方式        ?nbsp;?br />
“rt”      只读打开一个文本文Ӟ只允许读数据 

“wt”      只写打开或徏立一个文本文Ӟ只允许写数据

“at”      q加打开一个文本文Ӟq在文g末尾写数?br />
“rb”      只读打开一个二q制文gQ只允许L?br />
“wb”       只写打开或徏立一个二q制文gQ只允许写数?br />
“ab”       q加打开一个二q制文gQƈ在文件末ֆ数据

“rt+”      d打开一个文本文Ӟ允许d?br />
“wt+”      d打开或徏立一个文本文Ӟ允许d

“at+”      d打开一个文本文Ӟ允许读,或在文g末追加数 ?br />
“rb+”      d打开一个二q制文gQ允许读和写 

“wb+”      d打开或徏立一个二q制文gQ允许读和写

“ab+”      d打开一个二q制文gQ允许读Q或在文件末q加数据



对于文g使用方式有以下几点说明:

1. 文g使用方式由r,w,a,t,bQ?六个字符拼成Q各字符的含义是Q?br />
r(read): ?br />
w(write): ?br />
a(append): q加

t(text): 文本文gQ可省略不写

b(banary): 二进制文?br />
+: d?br />


2. 凡用“r”打开一个文件时Q该文g必须已经存在Q?nbsp;且只能从该文件读出?br />


3. ?#8220;w”打开的文件只能向该文件写入?nbsp;若打开的文件不存在Q则以指定的文g名徏立该文gQ若打开的文件已l存在,则将该文件删去,重徏一个新文g?br />


4. 若要向一个已存在的文件追加新的信息,只能?#8220;a ”方式打开文g?br />
5. 在打开一个文件时Q如果出错,fopen返回一个空指针值NULL。在E序中可以用q一信息来判别是否完成打开文g的工作,q作相应的处理。因此常用以下程序段打开文gQ?br />
if((fp=fopen("c:\\hzk16","rb")==NULL)

{

printf("\nerror on open c:\\hzk16 file!");

getch();

exit(1);

}

q段E序的意义是Q如果返回的指针为空Q表CZ能打开C盘根目录下的hzk16文gQ则l出提示信息“error on open c:\ hzk16file!”Q下一行getch()的功能是从键盘输入一个字W,但不在屏q上昄。在q里Q该行的作用是等待, 只有当用户从键盘敲Q一键时Q程序才l箋执行Q?nbsp;因此用户可利用这个等待时间阅d错提C。敲键后执行exit(1)退出程序?br />


6. 把一个文本文件读入内存时Q要ASCII码{换成二进制码Q?nbsp;而把文g以文本方式写入磁盘时Q也要把二进制码转换成ASCII码,因此文本文g的读写要p较多的{换时间。对二进制文件的d不存在这U{换?br />


7. 标准输入文g(键盘)Q标准输出文?昄?nbsp;)Q标准出错输?出错信息)是由pȝ打开的,可直接用。文件关闭函敎ͽclose文件一旦用完毕,应用关闭文g函数把文件关闭, 以避免文件的数据丢失{错误?br />


















如果要打开一个CCDOS子目录中, 文g名ؓCLIB的二q制文g, 可写?

fopen("c:\\ccdos\\clib", "rb");

如果成功的打开一个文? fopen()函数q回文g指针,   否则q回I指?NULL)。由此可判断文g打开是否成功?/p>

2. fclose()函数

   fclose()函数用来关闭一个由fopen()函数打开的文?, 其调用格式ؓ:

   nt fclose(FILE *stream);

   该函数返回一个整型数。当文g关闭成功? q回0, 否则q回一个非零倹{可以根据函数的q回值判断文件是否关闭成功?

例子Q?/p>

FILE *fpOut=fopen(“c:\\a.txt”,”wt+”);

Int a=1;

Fprintf(fpOut,”%d”,a);

Fclose(fpOut);

原文Qhttp://www.cnblogs.com/wangliang651/archive/2006/06/16/427497.html



qLv蓝梦 2011-03-09 10:43 发表评论
]]>
C--fseek函数http://m.tkk7.com/jasmine214--love/archive/2011/03/08/345951.htmlqLv蓝梦qLv蓝梦Tue, 08 Mar 2011 08:26:00 GMThttp://m.tkk7.com/jasmine214--love/archive/2011/03/08/345951.htmlhttp://m.tkk7.com/jasmine214--love/comments/345951.htmlhttp://m.tkk7.com/jasmine214--love/archive/2011/03/08/345951.html#Feedback1http://m.tkk7.com/jasmine214--love/comments/commentRss/345951.htmlhttp://m.tkk7.com/jasmine214--love/services/trackbacks/345951.htmlfseek函数是用来设定文件的当前d位置Q?/span>

函数原型:int fseek(FILE *fp,long offset,int origin);
函数功能:把fp的文件读写位|指针移到指定的位置.

fseek(fp,20,SEEK_SET);

//意思是把fp文gd位置指针从文件开始后U?0个字?

ftell函数是用来获取文件的当前d位置;
函数原型: long ftell(FILE *fp)
函数功能:得到式文g的当前读写位|?其返回值是当前d位置偏离文g头部的字节数.

ban=ftell(fp);

//是获取fp指定的文件的当前d位置,q将其gl变量ban.

fseek函数与ftell函数l合应用:
分析:可以用fseek函数把位|指针移到文件尾,再用ftell函数获得q时位置指针距文件头的字节数,q个字节数就是文件的长度.

  1. #include <stdio.h>  
  2. main()  
  3. {  
  4.    FILE *fp;  
  5.    char filename[80];  
  6.    long length;  
  7.    printf("Input the file name:");  
  8.    gets(filename);  
  9.    fp=fopen(filename,"rb");  
  10.    if(fp==NULL)  
  11.        printf("file not found!\n");  
  12.    else  
  13.    {  
  14.        fseek(fp,OL,SEEK_END);  
  15.        length=ftell(fp);  
  16.        printf("the file length %1d bytes\n",length);  
  17.        fclose(fp);  
  18.    }  
  19. }  
原文Qhttp://blog.csdn.net/swliao/archive/2009/09/04/4518012.aspx


qLv蓝梦 2011-03-08 16:26 发表评论
]]>
C--access()函数的用?/title><link>http://m.tkk7.com/jasmine214--love/archive/2011/03/08/345940.html</link><dc:creator>qLv蓝梦</dc:creator><author>qLv蓝梦</author><pubDate>Tue, 08 Mar 2011 06:41:00 GMT</pubDate><guid>http://m.tkk7.com/jasmine214--love/archive/2011/03/08/345940.html</guid><wfw:comment>http://m.tkk7.com/jasmine214--love/comments/345940.html</wfw:comment><comments>http://m.tkk7.com/jasmine214--love/archive/2011/03/08/345940.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/jasmine214--love/comments/commentRss/345940.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/jasmine214--love/services/trackbacks/345940.html</trackback:ping><description><![CDATA[<pre id="best-answer-content" class="reply-text mb10">access q回值是0的时候,表示存在Q而返?1的时候,表示p|。所以你的用法没问题Q错误的是你对返回值的判断Q应该是<br /> <br /> if(access(_Filename,0) == 0)<br /> printf("存在");<br /> else<br /> 不存在?/pre> <img src ="http://m.tkk7.com/jasmine214--love/aggbug/345940.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/jasmine214--love/" target="_blank">qLv蓝梦</a> 2011-03-08 14:41 <a href="http://m.tkk7.com/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://m.tkk7.com/jasmine214--love/archive/2011/03/08/345937.html</link><dc:creator>qLv蓝梦</dc:creator><author>qLv蓝梦</author><pubDate>Tue, 08 Mar 2011 06:31:00 GMT</pubDate><guid>http://m.tkk7.com/jasmine214--love/archive/2011/03/08/345937.html</guid><wfw:comment>http://m.tkk7.com/jasmine214--love/comments/345937.html</wfw:comment><comments>http://m.tkk7.com/jasmine214--love/archive/2011/03/08/345937.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/jasmine214--love/comments/commentRss/345937.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/jasmine214--love/services/trackbacks/345937.html</trackback:ping><description><![CDATA[<pre id="question-suply">system("某DOS命o")<br /> system函数 是可以调用一些DOS命o<br /> </pre> <img src ="http://m.tkk7.com/jasmine214--love/aggbug/345937.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/jasmine214--love/" target="_blank">qLv蓝梦</a> 2011-03-08 14:31 <a href="http://m.tkk7.com/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://m.tkk7.com/jasmine214--love/archive/2011/03/07/345859.html</link><dc:creator>qLv蓝梦</dc:creator><author>qLv蓝梦</author><pubDate>Mon, 07 Mar 2011 02:01:00 GMT</pubDate><guid>http://m.tkk7.com/jasmine214--love/archive/2011/03/07/345859.html</guid><wfw:comment>http://m.tkk7.com/jasmine214--love/comments/345859.html</wfw:comment><comments>http://m.tkk7.com/jasmine214--love/archive/2011/03/07/345859.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/jasmine214--love/comments/commentRss/345859.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/jasmine214--love/services/trackbacks/345859.html</trackback:ping><description><![CDATA[1Q系l自带的头文件用括hhQ这L译器会在pȝ文g目录下查找?<br /> #include <xxx.h> <br /> 2Q用戯定义的文件用双引hhQ编译器首先会在用户目录下查找,然后在到C++安装目录Q比如VC中可以指定和修改库文件查找\径,Unix和Linux中可以通过环境变量来设定)中查找,最后在pȝ文g中查找?<br /> #include “xxx.h”<br /> 原文Qhttp://blog.csdn.net/michaelpp/archive/2009/06/29/4307367.aspx<br /> <img src ="http://m.tkk7.com/jasmine214--love/aggbug/345859.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/jasmine214--love/" target="_blank">qLv蓝梦</a> 2011-03-07 10:01 <a href="http://m.tkk7.com/jasmine214--love/archive/2011/03/07/345859.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C语言中的.h文g的作?/title><link>http://m.tkk7.com/jasmine214--love/archive/2011/03/04/345734.html</link><dc:creator>qLv蓝梦</dc:creator><author>qLv蓝梦</author><pubDate>Fri, 04 Mar 2011 09:03:00 GMT</pubDate><guid>http://m.tkk7.com/jasmine214--love/archive/2011/03/04/345734.html</guid><wfw:comment>http://m.tkk7.com/jasmine214--love/comments/345734.html</wfw:comment><comments>http://m.tkk7.com/jasmine214--love/archive/2011/03/04/345734.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/jasmine214--love/comments/commentRss/345734.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/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;">文g和我认识由来已久Q其使用Ҏ虽不十分复杂Q但我却是经q了几个月的“不懂”时期Q几q的“一知半?#8221;时期才逐渐认识清楚他的本来面目。揪其原因,我的 驽钝和好学而不求甚解固然是原因之一Q但另外q有其他原因。原因一Q对于较的目Q其作用不易被充分开发,换句话说是即不知道他的详l用方法,? 目照栯行,E序在计机上照栯?/span><span style="font-size: 12pt;">原因二:现在的各U?/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;">语言的语法进行详l的不能再详l的说明Q但对于整个E序的文件组l构架却只字不提Q找了好几本比较著名?/span><span style="font-size: 12pt;">C</span><span style="font-size: 12pt;">语言著作Q却没有一个把</span><span style="font-size: 12pt;">.h</span><span style="font-size: 12pt;">文g的用法写的比较透彻的。下面我斗胆提W,来按照我?/span><span style="font-size: 12pt;">.h</span><span style="font-size: 12pt;">的认识思\Q向大家介绍一下?/span></div> <div style="text-indent: 24pt; background-color: #ffffff;" align="left"> </div> <div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">让我们的思A乘着旉机器回到大学一q?/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;">语言E序</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;"> </span><span style="font-size: 12pt;">文g?/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;">     printf(“Hello world!”);</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;">例程</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;">文g。是的,是没有Q世界上的万物都是经历从没有到有的过E的Q我们对</span><span style="font-size: 12pt;">.h</span><span style="font-size: 12pt;">的认识,我想也需要从q个步骤开始。这时确实不需?/span><span style="font-size: 12pt;">.h</span><span style="font-size: 12pt;">文gQ因个程序太单了Q根本就不需要。那么如何才能需要呢Q让我们把这个程序变得稍微复杂些Q请看下面这个,<br /> <br /> </span></div> <div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">文g?/span><span style="font-size: 12pt;"> First.c</span></div> <div style="text-indent: 24pt; background-color: #ffffff;" align="left"> </div> <div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;"> 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;">     printf(“Hello world!”);</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;">     </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"> </div> <div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">q是没有</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">那就让我们把q个E序再稍微改动一?/span><span style="font-size: 12pt;">.</span></div> <div style="text-indent: 27pt; background-color: #ffffff;" align="left"> </div> <div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">文g?/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"> </div> <div style="text-indent: 24pt; background-color: #ffffff;" align="left"> </div> <div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;"> 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;">     printf(“Hello world!”);</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;">     </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"> </div> <div style="background-color: #ffffff;" align="left"><span style="font-size: 12pt;">{等Q不是改变了个序?/span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">但结果确是十分不同的</span><span style="font-size: 12pt;">. </span><span style="font-size: 12pt;">让我们编译一下例E?/span><span style="font-size: 12pt;">-2和例E?/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;">是编译不q的</span><span style="font-size: 12pt;">.</span><span style="font-size: 12pt;">q时需要我们来认识一下另一?/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文g相关的顶层作用域, 层作用域就是从声明点g伸到源程序文本结?/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;">q个函数来说Q他没有单独的声?/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;">文gl束</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;">函数的引用点上,q不是他的作用域</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">所以会~译出错</span><span style="font-size: 12pt;">. </span><span style="font-size: 12pt;">q种情况怎么办呢</span><span style="font-size: 12pt;">? </span><span style="font-size: 12pt; color: deeppink;">有两U方?/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;">谁先谁后不一样呢Q只要能~译通过</span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">E序能运?/span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">p</span><span style="font-size: 12pt;">main()</span><span style="font-size: 12pt;">文gL攑ֈ最后吧</span><span style="font-size: 12pt;">. </span><span style="font-size: 12pt;">那就让我们来看另一个例E?/span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">让我们看看这个方法是不是在Q何时候都会v作用</span><span style="font-size: 12pt;">.</span></div> <div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">文g?/span><span style="font-size: 12pt;"> First.c<br />    play2()<br />    {</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;"> play1();</span></div> <div style="text-indent: 27pt; 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;"> <br />    }<br />    play1(){<br />     ……………..</span></div> <div style="text-indent: 36pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;"> play2();      </span><span style="font-size: 12pt;"> <br />     ……………………<br />    }<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"> </div> <div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">也许大部分都会看出来了,q就是经常用到的一U算?/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;">q两个函数哪个放到前面呢</span><span style="font-size: 12pt;">? </span></div> <div style="text-indent: 27pt; background-color: #ffffff;" align="left"> </div> <div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">q时需要我们来使用W二U方?/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;">文g?/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;"> ……………….</span></div> <div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;"> play1();</span></div> <div style="text-indent: 42.85pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;"> ………………..<br />     }<br />     play1()<br />     {<br />      …………………….</span></div> <div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;"> play2();</span></div> <div style="text-indent: 36pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;"> ……………………<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="text-indent: 27pt; background-color: #ffffff;" align="left"> </div> <div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">l历了我的半天的唠叨</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">加上四个例程的说?/span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">我们l于开始了用量变引L质变</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">q篇文章的主?/span><span style="font-size: 12pt;">.h</span><span style="font-size: 12pt;">文g快要出现了?/span></div> <div style="text-indent: 27pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">一个大型的软g目</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;">q么?/span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">q样可能有</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;">q样的声?/span><span style="font-size: 12pt; color: black;">, </span><span style="font-size: 12pt; color: black;">q个时候就需要我们想办法把这L</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;">文g?/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;">文g出现?/span><span style="font-size: 12pt; color: black;">.</span></div> <div style="text-indent: 27pt; background-color: #ffffff;" align="left"> </div> <div style="text-indent: 24pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">文g?/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;">文g?/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 “first.h”</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;"> ……………….</span></div> <div style="text-indent: 27pt; 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: 36pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">}<br />     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;">……………………..</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;">  ……………………<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"> </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;">q位</span><span style="font-size: 12pt;">janders</span><span style="font-size: 12pt;">大虾也太|嗦了,上面q些我也知道</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">你还讲了q么半天</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;">的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;">,80%</span><span style="font-size: 12pt;">的h都不完全知道</span><span style="font-size: 12pt;">. </span><span style="font-size: 12pt;">而且q也是我讲述一件事的一贯作?/span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">我Lx一个东西说明白</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;">的h也一h?/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;">文g的最基本的功?/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;">文gq有什么别的功能呢</span><span style="font-size: 12pt;">? </span><span style="font-size: 12pt;">让我来描qC下我手头的一个项目吧</span><span style="font-size: 12pt;">.</span></div> <div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"> </div> <div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">q个目已经做了?/span><span style="font-size: 12pt;">10</span><span style="font-size: 12pt;">q以上了Q具体多年我们部门的h谁都说不太准?/span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">况且旉q不是最主要的,不再详查了?/span><span style="font-size: 12pt;">是一个通讯讑֤的前台Y?/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;">~译后大U?/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;">, </span><span style="font-size: 12pt;">在这里充斥着错综复杂的调用关p?/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;">文g中的</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"> </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;">文g</span></div> <div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"> </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"> </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;">文g</span></div> <div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"> </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;">…………….</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;">……………….</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"> </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;">文g内声?/span><span style="font-size: 12pt;">play1</span><span style="font-size: 12pt;">函数Q怎么能调用到</span><span style="font-size: 12pt;">first.c</span><span style="font-size: 12pt;">文g中的哪个</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;">是不是搞错了Q没有搞?/span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">q里涉及?/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;">存储c说明符</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;">语言的存储类说明W有以下几个</span><span style="font-size: 12pt;">, </span><span style="font-size: 12pt;">我来列表说明一?br /> <br />    </span><br /> <table width="100%" border="1" cellpadding="1" cellspacing="1"> <tbody> <tr> <td style="text-align: center;"> <strong><span style="font-size: 12pt;">说明W?/span></strong></td> <td style="text-align: center;"> <strong><span style="font-size: 12pt;">?nbsp;   ?/span></strong></td> </tr> <tr> <td style="text-align: center;"> <em style="font-weight: bold;"><span style="font-size: 12pt;">Auto</span></em></td> <td> <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;">表示变量h本地生存?/span></em><em><span style="font-size: 12pt; color: blue;">.</span></em></td> </tr> <tr> <td style="font-weight: bold; text-align: center;"> <em><span style="font-size: 12pt;">Extern</span></em></td> <td> <em><span style="font-size: 12pt; color: deeppink;">出现在顶层或块的外部变量函数与变量声明中Q表C声明的对象</span></em><em><span style="font-size: 12pt; color: deeppink;">h静态生存期</span></em><em><span style="font-size: 12pt; color: deeppink;">, </span></em><em><span style="font-size: 12pt; color: deeppink;">q接E序知道其名?/span></em><em><span style="font-size: 12pt; color: deeppink;">.</span></em></td> </tr> <tr> <td style="font-weight: bold; text-align: center;"> <em><span style="font-size: 12pt;">Static</span></em></td> <td style="font-style: italic; color: #999902;"><font size="3"> 可以攑֜函数与变量声明中,在函数定义时,只用于指定函数名,而不函数导出到链接E序,在函数声明中,表示其后边会有定义声明的函数,存储cdstatic.在数据声明中,L表示定义的声明不导出到连接程?</font></td> </tr> </tbody> </table> </div> <div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"> </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;">在例E?/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;">标志W来修饰</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;">q样</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;">也就是实C无论?/span><span style="font-size: 12pt;">first.c</span><span style="font-size: 12pt;">文g中调?/span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">q是?/span><span style="font-size: 12pt;">second.c</span><span style="font-size: 12pt;">文g中调?/span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">q接E序都会很聪明的按照我们的意?/span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">把他q接?/span><span style="font-size: 12pt;">first.c</span><span style="font-size: 12pt;">文g中的</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;">文g中也要再写一个一L</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;">在例E?/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;">我们q没有用</span><span style="font-size: 12pt;">extern</span><span style="font-size: 12pt;">标志W来修饰</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;">q里涉及到另一个问?/span><span style="font-size: 12pt;">, C</span><span style="font-size: 12pt;">语言中有默认的存储类标志W?/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;">所有顶层的默认存储cL志符都是</span><span style="font-size: 12pt; color: deeppink;">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;">回想一下例E?/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;">修饰W?/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;">函数如果不被q接E序导出</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"> </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;">文g中有定义</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;">q也怸是必ȝQ因为无论在哪个文g中定义,聪明的连接程序都会义无返儡帮我们找刎ͼq导出到q接E序</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;">语言中一个h为的规范</span><strong><span style="font-size: 12pt;">:</span></strong></div> <div style="text-indent: 21pt; background-color: #ffffff;" align="left"> </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;">文g中声明的函数</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;">文g中有定义</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;">修饰W?/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;">则必LCZ?/span></em><em><span style="font-size: 13.5pt; color: deeppink;">extern</span></em><em><span style="font-size: 13.5pt; color: deeppink;">修饰W?/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> </strong></div> <div style="text-indent: 21pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">q样</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;">文g?/span><span style="font-size: 12pt;">,</span><span style="font-size: 12pt;">我们会看CU类型的函数声明</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;">q不?/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;">一个是引用外部函数Q一个是自己生命q定义的函数</span><span style="font-size: 12pt;">.</span></div> <div style="text-indent: 21pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt;">最l如?/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;">文g</span></div> <div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"> </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"> </div> <div style="background-color: #ffffff;" align="left"> </div> <div style="text-indent: 21pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">上面z洋z洒写了那么多都是针对函数的Q而实际上</span><span style="font-size: 12pt; color: black;">.h</span><span style="font-size: 12pt; color: black;">文g却不是ؓ函数所御用?/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;">文g我们发现除了函数?/span><span style="font-size: 12pt; color: black;">,</span><span style="font-size: 12pt; color: black;">q有其他的东?/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: 21pt; background-color: #ffffff;" align="left"> </div> <div style="text-indent: 21pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">在大型项目中Q对全局变量的用不可避?/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;">中我们的开发h员发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;">first.c</span><span style="font-size: 12pt; color: black;">中一L那个</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;">语言中默认的存储cd</span><span style="font-size: 12pt; color: black;">, </span><span style="font-size: 12pt; color: black;">在两个头文g中声明的</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;">q接E序会帮助我们处理一?/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;">q个比函数要复杂一?/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"> </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;">层声明中,存在初始化语句是Q表C个声明是定义声明Q其他声明是引用声明?/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;">按照q个模型Q我们可以在</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;">Q那么就定?/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;">省略存储cd说明</span></strong></div> <div style="margin: 0cm 0cm 0pt 39pt; background-color: #ffffff; color: #0001ff;" align="left"><strong><span style="font-size: 12pt;">在这个模型中Q所有引用声明要昄的包括存储类</span></strong><strong><span style="font-size: 12pt;">extern</span></strong><strong><span style="font-size: 12pt;">Q?/span></strong><strong><span style="font-size: 12pt;">而每个外部变量的唯一定义声明中省略存储类说明W?/span></strong></div> <div style="margin: 0cm 0cm 0pt 39pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">q个与我们对函数的处理方法类|不再举例说明?/span></div> <div style="background-color: #ffffff;" align="left"> </div> <div style="background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">    </span><span style="font-size: 12pt; color: black;">q里q有一个需要说明,本来与本文ƈ不十分相养I但前一D|个朋友遇到此问题Q相信很多h都会遇到Q?/span><span style="font-size: 12pt; color: black;">那就是数l全局变量?/span></div> <div style="background-color: #ffffff;" align="left"> </div> <div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">他遇到的问题如下Q?/span></div> <div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">在声明定义时Q定义数l如下:</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"> </div> <div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">在另一个文件中引用声明如下Q?/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"> </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;">q种情况大家都比较模pƈ且需要注意,数组与指针类|但ƈ不等于说Ҏl的声明起变量就是指针?/span><span style="font-size: 12pt; color: black;">上面所说的的程序在q行时发C问题Q在引用声明的那个文件中Q用这个指针时L提示内存讉K错误Q原来我们的q接E序q不把指针与数组{同Q连接时Q也不把他们当做同一个定义,而是认ؓ是不相关的两个定义,当然会出现错误。正的使用Ҏ是在引用声明中声明如下:</span></div> <div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"> </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"> </div> <div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">q且最好再加上一?/span><span style="font-size: 12pt; color: black;">extern</span><span style="font-size: 12pt; color: black;">Q更加明了?/span></div> <div style="text-indent: 21.75pt; background-color: #ffffff;" align="left"> </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"> </div> <div style="background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">    </span><span style="font-size: 12pt; color: black;">另外需要说明的是,在引用声明中׃不需要涉及到内存分配Q可以简化如下,q样在需要对全局变量的长度进行修ҎQ不用把所有的引用声明也全部修改了?/span></div> <div style="background-color: #ffffff;" align="left"> </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"> </div> <div style="background-color: #ffffff;" align="left"><span style="font-size: 12pt; color: black;">    C</span><span style="font-size: 12pt; color: black;">语言是现今ؓ止在底层核心~程中,使用最q泛的语aQ以前是Q以后也不会有太大改变,虽然现在</span><span style="font-size: 12pt; color: black;">java,.net</span><span style="font-size: 12pt; color: black;">{语a和工具对</span><span style="font-size: 12pt; color: black;">c</span><span style="font-size: 12pt; color: black;">有了一定冲击,但我们看到在计算机最为核心的地方Q其他语a是无论如何也代替不了的,而这个领域也正是我们对计机痴迷的程序员所向往的?/span></div> <span style="font-size: 12pt;"><br /> <br /> </span><hr style="width: 100%; height: 2px;" /> <span style="color: #009902;">好了,看完文章,对与C语言头文件的作用应该有了跟多的理解吧,如果q些你原本都知道?那么仅当是温习一下而已,如果原本不知?那么恭喜?现在又学C些技巧和知识.</span><br style="color: #009902;" /> <br /> <span style="color: #009902;">对于全局变量的定义和声明,其实q有另外一个解决的Ҏ,聪明的你可能早已l猜C:),没错,是用宏定义的技巧实?比如a.h文g当中? <br /> #ifdef AAA<br />  int i=0;<br /> #else<br />  int i;<br /> #endif<br /> 那么,在a.c文g当中,有如下语?<br /> ......<br /> #define AAA<br /> #include "a.h"</span><br /> <span style="color: #009902;">......<br /> 而对于其他的M包含a.h文g的头文g或?c源文?只需要直接包含a.hp?br /> ......<br /> #include "a.h"</span><br /> <span style="color: #009902;">......<br /> q样可以达到在a.c文g当中定义变量一?而在其他的文件当中声明该变量的目?</span><br /> <span style="color: #009902;">当然?你完全可以根据自q需要来军_在哪个需要包含a.h的文件当中定义宏AAA,但是我要说的?br /> 在同一个工E的不同的需要包含a.h的文件当?你只能定义AAA一?否则在连接这些目标文件时会出?br /> 重复定义的错?即你的单独目标文g~译没有M的问?<br /> </span><br /> <span style="color: #009902;">当然,q里说的仅仅是对全局变量的声明技?强烈的推介大家在头文件中使用宏定义实现对整个头文件的防止重复包含,当然?q个技巧大多数的c语言E序员都?<br /> #ifndef XXX<br /> #define XXX<br /> <br /> #endif</span><br /> <span style="color: #009902;">q样做会让你的程序更加稳?很大E度上减了不必要的ȝ...</span><br /> <br /> 最后给Z点点全局变量使用需要注意的问题,q也仅仅是个,或者说一U编E习?;)<br /> 1) 所有全局变量全部以g_开?q且可能声明成staticcd. <br /> 2) 量杜绝跨文件访问全局变量.如果的确需要在多个文g内访问同一变量,应该p变量定义所在文件内提供GET/PUT函数实现. <br /> 3) 全局变量必须要有一个初始?全局变量量攑֜一个专门的函数内初始化. <br /> 4) 如调用的函数于三个,误虑改ؓ局部变量实? <br /> <br style="color: #80ffff;" /> <span style="color: #ff9902;">如果文中有什么不对的地方,Ƣ迎指正,怺学习:)<br /> 原文Qhttp://blogold.chinaunix.net/u2/75758/showart_1715158.html<br /> </span> <img src ="http://m.tkk7.com/jasmine214--love/aggbug/345734.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/jasmine214--love/" target="_blank">qLv蓝梦</a> 2011-03-04 17:03 <a href="http://m.tkk7.com/jasmine214--love/archive/2011/03/04/345734.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从c文g源码中熟悉CQ-整理Q?/title><link>http://m.tkk7.com/jasmine214--love/archive/2010/12/28/341801.html</link><dc:creator>qLv蓝梦</dc:creator><author>qLv蓝梦</author><pubDate>Tue, 28 Dec 2010 09:40:00 GMT</pubDate><guid>http://m.tkk7.com/jasmine214--love/archive/2010/12/28/341801.html</guid><wfw:comment>http://m.tkk7.com/jasmine214--love/comments/341801.html</wfw:comment><comments>http://m.tkk7.com/jasmine214--love/archive/2010/12/28/341801.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/jasmine214--love/comments/commentRss/341801.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/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"> </span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">W一Q?span class="pmemo"><span lang="EN-US">#define</span></span>宏定义,<span lang="EN-US"><span>  </span></span><span style="color: red;">语法Q?strong><span lang="EN-US">#define </span>语义?代号名,</strong></span><span id="7nxnpfd" class="pmemo"><span lang="EN-US">#define</span>?span style="color: red;">预编译处理命?/span>Q主要定义常量,此常量可以ؓM的字W及其组合,在编译之前,此帔R出现的所有位|,用其代表的字W或字符l合无条? 的替换,然后q行~译?/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;">条g~译Q?span lang="EN-US">#ifndef</span>、(或?span lang="EN-US">#ifndef)</span>?span lang="EN-US">#def</span>?span lang="EN-US">#endif</span>{宏q几个宏是ؓ了进行条件编译?/span><span style="font-size: 10pt; font-family: 宋体;">一般情况下Q源E序?所有的行都参加~译。但是有时希望对其中一部分内容只在满一定条件才q行~译Q也是对一部分内容指定~译的条Ӟq就?span lang="EN-US">“</span>条g~译<span lang="EN-US">”</span>。有Ӟ希望当满 x条g时对一l语句进行编译,而当条g不满x则编译另一l语句?/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>    </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: 宋体;">有h会问Q不用条件编译命令而直接用<span lang="EN-US">if</span>语句也能辑ֈ要求Q用条g~译命o有什么好处呢Q的,此问题完全可以不用条件编 译处理,但那样做目标E序长(因ؓ所有语句都~译Q,而采用条件编译,可以减少被编译的语句Q从而减目标的长度。当条g~译D|较多Ӟ目标E序长度?以大大减?/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: 宋体;">W二Q?span class="pmemo"><span lang="EN-US">typedef</span></span>cd重命名:Z更加见名知义 Q?strong><span style="color: red;">语法Q?span lang="EN-US">typedef </span>原类?目标cdQ?/span></strong><span id="zldv73p" class="pmemo"><span lang="EN-US">typedef</span>是ؓ已知数据cd增加一个新名称Q其原理与?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>    </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"> </span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">W三Q导入头文g?span lang="EN-US">.c</span>文g中:</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"> </span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">W四Q?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>有了W二U含义:用来表示不能被其它文件访问的全局变量和函数。但Z限制全局变量<span lang="EN-US">/</span>函数的作用域<span lang="EN-US">, </span>函数或变量前?span lang="EN-US">static</span>使得函数成ؓ静态函数。但此处<span lang="EN-US">“static”</span>的含义不是指存储方式Q而是指对函数的作用域仅局限于本文?span lang="EN-US">(</span>所以又U内部函 ?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>文g<span lang="EN-US">)</span>内部<span lang="EN-US">.<br /> </span>使用内部函数的好处是Q不同的人编写不同的函数Ӟ不用担心自己?义的函数Q是否会与其它文件中的函数同名?/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: 宋体;">W五Q条件语句的使用。常量值放在前面做比较的时?/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>        </span>{</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>            </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>        </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: 宋体;">W六Q?span lang="EN-US">enum</span>枚DQ在使用枚D变量Ӟ主要兛_的不是它的值的大小Q而是其表C的?态。在实际应用中,有的变量只有几种可能取倹{如人的性别只有两种可能取|星期?span lang="EN-US"><br /> </span>有七U可能取倹{在<span lang="EN-US"> C </span>语言中对q样取值比较特D的变量可以定义为枚丄型。所谓枚?span lang="EN-US"><br /> </span>是指变量的g一列D出来Q变量只限于列D出来的值的范围内取倹{?span lang="EN-US"> <br /> </span>定义 一个变量是枚DcdQ可以先定义一个枚丄型名Q然后再说明q个变量是该?span lang="EN-US"><br /> </span>丄型?/span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">例如Q?span lang="EN-US"> <br /> enum weekday{sun,mon,tue,wed,thu,fri,sat}</span>Q?/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>    </span>DHCPV6_IF_FORMAT_NORMAL,</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>    </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"> </span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">W七Q?span lang="EN-US">break </span>用法?span style="color: blue;" lang="EN-US">continue</span><span style="color: black;">?l束本次循环<span lang="EN-US">,</span>而不是中止整个@环的执行<span lang="EN-US">.</span>?/span><span style="color: blue;" lang="EN-US">break</span><span style="color: black;">语句则是l束整个循环q?E?span lang="EN-US">,</span>不再判断循环条g是否成立<span lang="EN-US">.</span></span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>  </span>switch(level)</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>    </span>{</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>        </span>case CLI_LEVEL_PUBLIC:</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>        </span>{</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>            </span>pPwd = "public";</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>            </span>break;</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>        </span>}</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>    </span>…</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>    </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: 宋体;">W八Q?span lang="EN-US">extern</span>Q?span lang="EN-US">extern</span>可以|于变量或?span style="color: red;">函数</span>前,以标C变量或者函数的定义在别的文件中Q提C编译器遇到此变量和函数时在其他模块中寻扑օ定义?/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>    </span>IN GT_LPORT <span>    </span>port,</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>    </span>IN<span>  </span>GT_PORT_FORCED_SPEED_MODE<span>  </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"> </span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">W九Q?span lang="EN-US">return o ;</span>的用,正常退出?span style="color: red;">只要一个函数的q回值是数字型的<span lang="EN-US">,</span>那么可以返?span lang="EN-US">0(</span>?span lang="EN-US">return 0),</span>其实你返回多都没问 题。一般情?下,<span lang="EN-US">C++</span>做出来的函数都要求返回一个|当函数执行正常,且达C一般情况下的目的,那么p?span lang="EN-US">0</span>表示正确的调用了该函敎ͼq个<span lang="EN-US">0</span>是q回l主调函C 通知没有出错的;如果函数调用中出错,或者没有按照一般情冉|行,那么p?span lang="EN-US">1</span>Q以告知主调函数采取响应{略Q?/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"> </span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>    </span>VOS_ApplStart("cli",</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>                             </span>APPL_CLI,</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>                             </span>CLI_Init,</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>                             </span>CLI_MsgHandle,</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>                             </span>CLI_Destroy);<span>  </span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>    </span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>    </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: 宋体;">W十Q三元表辑ּQ可见三元运符?span lang="EN-US"> if (){}else{} </span>快一?span lang="EN-US"> </span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">一元运符Q?span lang="EN-US">~ ! <br /> </span>二元q算W,<span lang="EN-US"> + - * / % <br /> </span>三元q算W?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->data);</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"> </span></p> <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: 宋体;">W十一Q打印输出,</span><span>-</span><span style="font-family: 宋体;">代表左对?/span><span style="font-family: 宋体;">Q?/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>  </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>   </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;">表示回RQ即光标回R当前行首</span></pre> <pre><span style="font-size: 10pt;" lang="EN-US">\n</span><span style="font-size: 10pt;">表示回R换行Q即光标前进C一行的行首</span></pre> <pre><span style="font-size: 10pt;" lang="EN-US">\0</span><span style="font-size: 10pt;">是字W串l束标志Q空字符Q,在字W数l中遇到它就表示前面的字W串C为止?/span></pre> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US">printf("%-5lu %-5x %-4lu %-11lu<span>  </span>%-10lu\r\n",</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>               </span>pTimerData->timerId, </span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>               </span>pTimerData->applyAppl,</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>               </span>pTimerData->arg,</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>               </span>pTimerData->interval,</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>               </span>pTimerData->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"> </span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">W十二,数组Q一l数l可以用二l数l的写法<span lang="EN-US">{{}</span>Q?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>    </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"> </span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">W十三,<span lang="EN-US">sizeof</span>作用Q?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: 宋体;">一般Ş式ؓQ?span lang="EN-US">sizeof</span>Q?span lang="EN-US">object</span>Q,也可?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">     </span><span style="font-size: 12pt; font-family: 宋体;">对象可以是表辑ּ或者数据类型名Q当对象是表辑ּӞ括号可省略?span lang="EN-US">sizeof</span>是单目运符Q其q算W的含义是:<span style="color: red;">求出对象在计机内存中所占用的字节数?/span> 一般来Ԍ不同的机器,q行不同的对象是不一LQ当目前几乎所有的机器都是<span lang="EN-US">32</span>位,很少<span lang="EN-US">16</span>位的Q所以一般考试都是Z<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"> </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"> </span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">W十四,条g语句Q?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>        </span>{</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>            </span>TIMER_ID *pTimerId;</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>            </span>pTimerId = (TIMER_ID *)pData;</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>            </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>            </span>{</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>                </span>ret = timer_Stop(*pTimerId);</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>                </span>if (SYS_OK != ret)</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>                </span>{</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>                    </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>               </span><span> </span>}</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>            </span>}</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>            </span>else</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>            </span>{</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>                </span>ret = TIMER_ERR_APPLID_UNMATCHED;</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>            </span>}</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>            </span>VOS_SyncMsgResponse(srcAppl, MSG_TIMER_STOP, (VOID *)&ret, sizeof(SYS_ERR_TYPE));</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>           </span><span style="color: red;"><span> </span>break;</span></span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><span>        </span>}</span></p> <p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;" lang="EN-US"><br /> </span></p> <img src ="http://m.tkk7.com/jasmine214--love/aggbug/341801.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/jasmine214--love/" target="_blank">qLv蓝梦</a> 2010-12-28 17:40 <a href="http://m.tkk7.com/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]http://m.tkk7.com/jasmine214--love/archive/2010/12/28/341800.htmlqLv蓝梦qLv蓝梦Tue, 28 Dec 2010 09:30:00 GMThttp://m.tkk7.com/jasmine214--love/archive/2010/12/28/341800.htmlhttp://m.tkk7.com/jasmine214--love/comments/341800.htmlhttp://m.tkk7.com/jasmine214--love/archive/2010/12/28/341800.html#Feedback0http://m.tkk7.com/jasmine214--love/comments/commentRss/341800.htmlhttp://m.tkk7.com/jasmine214--love/services/trackbacks/341800.html假设我们有下面这L一个程序,源代码如下:

/* main.c */ 

#include "mytool1.h"

#include "mytool2.h"

int main(int argcQchar **argv)

{

mytool1_print("hello")Q?

mytool2_print("hello")Q?

}

/* mytool1.h */

#ifndef _MYTOOL_1_H

#define _MYTOOL_1_H

void mytool1_print(char *print_str)Q?

#endif

/* mytool1.c */

#include "mytool1.h"

void mytool1_print(char *print_str)

{

printf("This is mytool1 print %s "Qprint_str)Q?

}

/* mytool2.h */

#ifndef _MYTOOL_2_H

#define _MYTOOL_2_H

void mytool2_print(char *print_str)Q?

#endif

/* mytool2.c */

#include "mytool2.h"

void mytool2_print(char *print_str)

{

printf("This is mytool2 print %s "Qprint_str)Q?

}


当然׃q个E序很短Q我们可以这h~译:

gcc -c main.c 

gcc -c mytool1.c

gcc -c mytool2.c

gcc -o main main.o mytool1.o mytool2.o

q? L话我们也可以产生mainE序Q而且也不是很ȝ。但是如果我们考虑一下如果有一天我们修改了其中的一个文?比如说mytool1.c)那么我们? 道还要重新输入上面的命o?也许你会_q个很容易解军_Q我写一? SHELL脚本Q让它帮我去完成不就可以了。是的对于这个程序来_是可以vC用的。但是当我们把事情想的更复杂一点,如果我们的程序有几百个源E序? 时候,N也要~译器重C个一个的ȝ?

为此Q聪明的E序员们惛_了一个很好的工具来做qg事情Q这是make。我们只要执? 以下makeQ就可以把上面的问题解决掉。在我们执行make之前Q我们要先编写一个非帔R要的文g?-Makefile。对于上面的那个E序来说Q可 能的一个Makefile的文件是Q?

# q是上面那个E序的Makefile文g:


mainQmain.o mytool1.o mytool2.o 

gcc -o main main.o mytool1.o mytool2.o

main.oQmain.c mytool1.h mytool2.h

gcc -c main.c

mytool1.oQmytool1.c mytool1.h

gcc -c mytool1.c

mytool2.oQmytool2.c mytool2.h

gcc -c mytool2.c


有了q个Makefile文gQ不论我们什么时候修改了源程序当中的什么文Ӟ我们只要执行make命oQ我们的~译器都只会ȝ译和我们修改的文件有关的文gQ其它的文g它连理都不想ȝ的?

下面我们学习Makefile是如何编写的?

在Makefile中也#开始的行都是注释行.Makefile中最重要的是描述文g的依赖关pȝ说明。一般的格式是:

targetQcomponents

TAB rule

W一行表C的是依赖关pR第二行是规则?

比如说我们上面的那个Makefile文g的第二行?

mainQmain.o mytool1.o mytool2.o

?C我们的目标(target)main的依赖对?components)是main.o mytool1.omytool2.o 当倚赖的对象在目标修改后修改的话,pL行规则一行所指定的命令。就象我们的上面那个MakefileW三行所说的一栯执行 gcc-o main main.o mytool1.o mytool2.o 注意规则一行中的TAB表示那里是一个TAB?

Makefile有三个非常有用的变量。分别是$@Q?^Q?<代表的意义分别是Q?

$@--目标文gQ?^--所有的依赖文gQ?<--W一个依赖文件?

如果我们使用上面三个变量Q那么我们可以简化我们的Makefile文g为:

# q是化后的Makefile

mainQmain.o mytool1.o mytool2.o

gcc -o $@ $^

main.oQmain.c mytool1.h mytool2.h

gcc -c $<

mytool1.oQmytool1.c mytool1.h

gcc -c $<

mytool2.oQmytool2.c mytool2.h

gcc -c $<

l过化后,我们的Makefile是简单了一点,不过Z有时候还想简单一炏V这里我们学习一个Makefile的缺省规?

.c.oQ?

gcc -c $<

q个规则表示所有的 .o文g都是依赖与相应的.c文g的。例如mytool.o依赖于mytool.cq样Makefileq可以变为:

# q是再一ơ简化后的Makefile

mainQmain.o mytool1.o mytool2.o

gcc -o $@ $^

.c.oQ?

gcc -c $<

好了Q我们的Makefile 也差不多了,如果想知道更多的关于Makefile的规则,可以查看相应的文档?

原文Qhttp://hi.baidu.com/mgqw/blog/item/2824bb01b72dfe067bec2c8c.html




qLv蓝梦 2010-12-28 17:30 发表评论
]]>
C-sizeof解析http://m.tkk7.com/jasmine214--love/archive/2010/11/29/339335.htmlqLv蓝梦qLv蓝梦Mon, 29 Nov 2010 09:13:00 GMThttp://m.tkk7.com/jasmine214--love/archive/2010/11/29/339335.htmlhttp://m.tkk7.com/jasmine214--love/comments/339335.htmlhttp://m.tkk7.com/jasmine214--love/archive/2010/11/29/339335.html#Feedback0http://m.tkk7.com/jasmine214--love/comments/commentRss/339335.htmlhttp://m.tkk7.com/jasmine214--love/services/trackbacks/339335.html只要参加软g研发的笔试(C/C++)几乎都会涉及到sizeof()的用法,我昨天也遇到了,有的也会Q但是真正sizeof()的核心还? 没有领会Q今天上|,无聊中就看到了详l的sizeof()的阐qͼ现在分nl大家?/div>
Q-Q-Q-Q-Q-Q-sizeofQ-Q-Q-Q-Q-Q-Q-Q-
sizeof 一般Ş式ؓQsizeofQobjectQ,也可以sizeof var_char,不过大部分programer习惯用sizeof()?/div>
     对象可以是表辑ּ或者数据类型名Q当对象是表辑ּӞ括号可省略。sizeof是单目运符Q其q算W的含义是:求出对象在计机内存中所占用的字节数? 一般来Ԍ不同的机器,q行不同的对象是不一LQ当目前几乎所有的机器都是32位,很少16位的Q所以一般考试都是Z32位的window? linux的?/div>
C语言中数据类型不多?/div>
1.整数型的Q?/div>
shortQintQlong(我没有考虑W号问题),一般c语言书上Ԍint?个字节的Q即16位,范围? Q?2768Q?2767Qlong?个字节,范围是-2^32---2^32-1。当时在xp上运行sizeof(int)的时候,会output 4.q就?2位的原因。sizeofQlongQ也?.
如下:#include "stdio.h"
#include "string.h"
#include "stdlib.h"
int main()
{
 short int sa=10;
    int a=10;
    long la=10;
    float f = 20;
    double d=20;
    char ch='c';
    char str[]="ABC";
    char *p=str;
    struct str{
  double d;
  char ch;
  int data;
 }str_wu;
 struct str1{
  char ch;
  double d;
  int data;
 }str_wu1;
    printf("sizeof(short):%d\n",sizeof(sa));
 printf("sizeof(int):%d\n",sizeof(a));
    printf("sizeof(long):%d\n",sizeof(la));
    printf("sizeof(float):%d\n",sizeof(f));
    printf("sizeof(double):%d\n",sizeof(d));
    printf("sizeof(char):%d\n",sizeof(ch));
    printf("sizeof(string):%d\n",sizeof(str));
    printf("sizeof(point address):%d\n",sizeof(p));
    printf("sizeof(Point):%d\n",sizeof(*p));
    printf("sizeof(Struct):%d\n",sizeof(str_wu));
    printf("sizeof(Struct):%d\n",sizeof(str_wu1));
    system("pause");
}
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">
因而intQshort的sizeofl果是一L额?/div>
2.点型数?/div>
floatQdoubleQlong double
上边的图Qlong double 没有试Q忘了。。。。。)呵呵Q?/div>
但是应该?6?/div>
3。指?/div>
对于指针Q要特别区分Q指针指向什么数据,它在内存占的字节数才是它的结果?/div>
比如Q指针指向一个字W串Q就是字W串的长度,因ؓ一个字W在内存中占一个字节。若指针指向一个数据结构,则结果应该是l构型数据的内存字节 数?/div>
4。结构类?/div>
在上面的E序中,
struct str{
                          double d;
                         char ch;
                          int data;
 }str_wu;
 struct str1{
                           char ch;
                            double d;
                             int data;
 }str_wu1;

两个不同的结构,但是内部的元素是相同的,都是 doubleQintQcharQ只是顺序不一Pq果不一栗whyQ?/div>
q时因ؓVC存储数据的时候要对其Q具体的情况如下Q?/div>
cd
寚w方式Q变量存攄起始地址相对于结构的起始地址的偏U量Q?
Char
偏移量必Mؓsizeof(char)?的倍数
int
偏移量必Mؓsizeof(int)?的倍数
float
偏移量必Mؓsizeof(float)?的倍数
double
偏移量必Mؓsizeof(double)?的倍数
Short
偏移量必Mؓsizeof(short)?的倍数
比如Qstr_wuQؓ上面的结构分配空间的时候,VCҎ成员变量出现的顺序和寚w方式Q先? W一个成员dda1分配I间Q其起始地址跟结构的起始地址相同Q刚好偏U量0刚好为sizeof(double)的倍数Q,该成员变量占? sizeof(double)=8个字节;接下来ؓW二个成员dda分配I间Q这时下一个可以分配的地址对于l构的v始地址的偏U量?Q是 sizeof(char)的倍数Q所以把dda存放在偏U量?的地Ҏ_齐方式,该成员变量占用sizeof(char)=1个字节;接下来ؓW三? 成员type分配I间Q这时下一个可以分配的地址对于l构的v始地址的偏U量?Q不是sizeof(int)=4的倍数Qؓ了满_齐方式对偏移量的U? 束问题,VC自动填充3个字节(q三个字节没有放什么东西)Q这时下一个可以分配的地址对于l构的v始地址的偏U量?2Q刚好是 sizeof(int)=4的倍数Q所以把type存放在偏U量?2的地方,该成员变量占用sizeof(int)=4个字节;q时整个l构的成员变? 已经都分配了I间Qȝ占用的空间大ؓQ?+1+3+4=16Q刚好ؓl构的字节边界数Q即l构中占用最大空间的cd所占用的字节数 sizeof(double)=8Q的倍数Q所以没有空~的字节需要填充。所以整个结构的大小为:sizeof(str_wu)=8+1+3+4=16Q? 其中?个字节是VC自动填充的,没有放Q何有意义的东ѝ?
而str_wu1Q同L道理Q如下:sizeof(char)=1,?? ?的倍数Q因而增加到8QsizeofQdoubleQ=8Q现在开始地址?6Q?6是sizeofQint)的倍数Q可以存入?/font>
因而ȝ地址 敎ͼsizeofQcharQ+7QsizeofQdoubleQ+sizeofQintQ=20Q?/font>
?0不是8的倍数Qsizeof(double)=8),所以需要在增加4 个地址Q即d24?/font>
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-
sizeof具体的,我所知道的就q些了,那位高手q知道什么,或者我写的? 什么错Q希望指出。谢谢!
原文Q?http://lemonmilk.blog.51cto.com/499577/107155


qLv蓝梦 2010-11-29 17:13 发表评论
]]>关于C语言中return的一些ȝ http://m.tkk7.com/jasmine214--love/archive/2010/11/29/339321.htmlqLv蓝梦qLv蓝梦Mon, 29 Nov 2010 07:51:00 GMThttp://m.tkk7.com/jasmine214--love/archive/2010/11/29/339321.htmlhttp://m.tkk7.com/jasmine214--love/comments/339321.htmlhttp://m.tkk7.com/jasmine214--love/archive/2010/11/29/339321.html#Feedback0http://m.tkk7.com/jasmine214--love/comments/commentRss/339321.htmlhttp://m.tkk7.com/jasmine214--love/services/trackbacks/339321.html return是C++预定义的语句Q它提供了种植函数执行的一U放大。当return语句提供了一个值时Q? q个值就成ؓ函数的返回? 
说到return,有必要提及主函数的定?下面是从|络上找到的资料,好好消化?对了解主函数中返回值的理解? 很大的帮? 
很多人甚臛_面上的一些书c,都用了void main( ) Q其实这是错误的。C/C++ 中从来没有定义过 void main( ) 。C++ 之父 Bjarne Stroustrup 在他的主上?nbsp;FAQ 中明地? 着 The definition void main( ) { /* ... * / } is not and never has been C++, nor has it even been C. Q?nbsp;void main( ) 从来׃存在?nbsp;C++ 或?nbsp;C Q。下面我分别说一?nbsp;C ?nbsp;C++ 标准中对 main 函数的定义?nbsp;
1. C 
?nbsp;C89 中,main( ) ? 可以接受的。Brian W. Kernighan ?nbsp;Dennis M. Ritchie 的经典巨 ?nbsp;The C programming Language 2eQ《C E序设计语言W二版》)用的是 main( )。不q在最新的 C99 标准 中,只有以下两种定义方式是正的Q?nbsp;
int main( void ) 
int main( int argc, char *argv[] ) 
Q参 考资 料:ISO/IEC 9899:1999 (E) Programming languages ?nbsp;C 5.1.2.2.1 Program startupQ?nbsp;
? Ӟ我们也可以做一点小的改动。例如:char *argv[] 可以写成 char **argvQargv ?nbsp;argc 可以Ҏ别的变量? Q如 intval ?nbsp;charvalQ,不过一定要W合变量的命名规则?nbsp;
如果不需要从命o行中获取参数Q请? int main(void) Q否则请用int main( int argc, char *argv[] ) ?nbsp;
main 函数的返回? cd必须?nbsp;int Q这栯回值才能传递给E序的激z者(如操作系l)?nbsp;
如果 main 函数的最后没有写 return 语句? 话,C99 规定~译器要自动在生成的目标文g中(?nbsp;exe 文gQ加入return 0; Q表C程序正帔R出。不q,我还是徏议你最好在main? 数的最后加上return 语句Q虽然没有这个必要,但这是一个好的习惯。注意,vc6不会在目标文件中加入return 0; Q大概是? ?nbsp;vc6 ?nbsp;98 q的产品Q所以才不支持这个特性。现在明白我Z么徏议你最好加?nbsp;return 语句了吧Q不q,gcc3.2QLinux ? ?nbsp;C ~译器)会在生成的目标文件中加入 return 0; ?nbsp;

2. C++ 
C++98 中定义了如下? U?nbsp;main 函数的定义方式: 
int main( ) 
int main( int argc, char *argv[] ) 
Q参 考资 料:ISO/IEC 14882(1998-9-01)Programming languages ?nbsp;C++ 3.6 Start and terminationQ?nbsp;
int main( ) {? 同于 C99 中的 int main( void ) Qint main( int argc, char *argv[] ) 的用法也 ?nbsp;C99 中定义的一栗同Pmain 函数的返回值类型也必须是int。如果main函数的末没写return语句QC++98 规定~译器要? 动在生成的目标文件中加入 return 0; 。同Pvc6 也不支持q个Ҏ,但是 g++3.2QLinux 下的 C++ ~译器)支持?nbsp;

3. ? ?nbsp;void main 
?nbsp;C ?nbsp;C++ 中,不接收Q何参C不返回Q何信息的函数原型?#8220;void foo(void);”。可能正是因 个,所以很多h都误认ؓ如果不需要程序返回值时可以把main函数定义成void main(void) 。然而这是错误的Qmain 函数的返回? 应该定义?nbsp;int cdQC ?nbsp;C++ 标准中都是这栯定的。虽然在一些编译器中,void main 可以通过~译Q如 vc6Q,但ƈ非所有编 译器都支?nbsp;void main Q因为标准中从来没有定义q?nbsp;void main 。g++3.2 中如?nbsp;main 函数的返回g?nbsp;int c? 型,根本通不q编译。?nbsp;gcc3.2 则会发出警告。所以,如果你想你的E序拥有很好的可UL性,请一定要?nbsp;int main ?nbsp;

4. q? 回值的作用 
main 函数的返回值用于说明程序的退出状态。如果返?nbsp;0Q则代表E序正常退出,否则代表E序异常退出。下面我? ?nbsp;winxp 环境下做一个小实验。首先编译下面的E序Q?nbsp;
int main( void ) 

return 0; 

? 后打开附g里的“命o提示W?#8221;Q在命o行里q行刚才~译好的可执行文Ӟ然后输入“echo %ERRORLEVEL%”Q回车,可以看到程序的q回? ?nbsp;0 。假讑ֈ才编译好的文件是 a.exe Q如果输?#8220;a && dir”Q则会列出当前目录下的文件夹和文件。但是如果改? “return -1”Q或者别的非 0 |重新~译后输?#8220;a && dir”Q则 dir 不会执行。因 ?nbsp;&& 的含义是Q如?nbsp;&& 前面的程序正帔R出,则l执?nbsp;&& 后面的程序,否则不执行。也 是_利用E序的返回|我们可以控制要不要执行下一个程序。这是 int main 的好处。如果你有兴,也可以把 main 函数的返回值类? Ҏ?nbsp;int cdQ如 floatQ,重新~译后执?#8220;a && dir”Q看看会出现什么情况,xZ么会出现那样的情c顺? 提一下,如果输入 a || dir 的话Q则表示如果 a 异常退出,则执?nbsp;dir ?nbsp;
5. ? ?nbsp;intmain(intargc,char*argv[],char*envp[])呢? 
q当然也不是标准 C 里面定义的东 西!char*envp[] 是某些编译器提供的扩展功能,用于获取pȝ的环境变量。因Z是标准,所以ƈ非所有编译器都支持,故而移植性差Q不推荐? 用?nbsp;
Cq里,你应该了解ؓ什么主函数定义?nbsp;intq回cd,而且函数体里面有return 0;q个语句了吧. 
下面具体说说我对 return的应用的理解?nbsp;
只要一个函数的q回值是数字型的,那么可以返?(即return 0),其实你返回多都没问题。一般情? 下,C++做出来的函数都要求返回一个|当函数执行正常,且达C一般情况下的目的,那么p?表示正确的调用了该函敎ͼq个0是q回l主调函C 通知没有出错的;如果函数调用中出错,或者没有按照一般情冉|行,那么p?Q?/span>以告知主调函数采取响应策略;如果你在某个函数所在类的定义所在的头文? 中定义了一l状态|一般都是负整数Q,那么函数可以返回不同的g告之主调函数具体发生了什么异常或错误Q这U情况一般用于函数功能独立性较差的的情 c所以一般不鼓励把函数返回类型定义ؓvoidQ至返回应该是intQ而在函数的最后加上return 0.语句Q?nbsp;
int func(参数 列表) 

…… 
…… 
…… 
Return 0; 

在函CQ如果碰到return ? 句,那么E序׃q回调用该函数的下一条语句执行,也就是说跛_函数的执行,回到原来的地方l执行下厅R但是如果是在主函数中碰到return语句Q那 么整个程序就会停止,退出程序的执行?nbsp;
如果你定义一个函数有q回cdQ可以想下面那样调用Q?nbsp;
int func() 

int value; 
…… 
…… 
…… 
return value; 

int main() 

int intvalue; 
intvalue=func(); 
…… 
…… 
teturn 0; 

return 语句后面具体是什么内容,q就要具体情况具体分析了Q?nbsp;
Q?Q?nbsp;在返回类型是char的函CQreturn后应该是charcd的| 
Q?Q?nbsp;? q回cd是int的函CQ如果是要停止函数的调用Q最好应该ؓ0Q其他的按照你的目的而定Q只要是int cdp?nbsp;
Q?Q?nbsp;在返回类型是l? 构类型的函数中,return后应该是l构的一个实例对象?nbsp;
MQ函数定义ؓ什么样的返回类型,该函Creturn后就应该是相应类型的倹{?br /> 原文Q?http://blog.pfan.cn/zean/21232.html


qLv蓝梦 2010-11-29 15:51 发表评论
]]>
C -extern使用 http://m.tkk7.com/jasmine214--love/archive/2010/11/29/339319.htmlqLv蓝梦qLv蓝梦Mon, 29 Nov 2010 07:29:00 GMThttp://m.tkk7.com/jasmine214--love/archive/2010/11/29/339319.htmlhttp://m.tkk7.com/jasmine214--love/comments/339319.htmlhttp://m.tkk7.com/jasmine214--love/archive/2010/11/29/339319.html#Feedback0http://m.tkk7.com/jasmine214--love/comments/commentRss/339319.htmlhttp://m.tkk7.com/jasmine214--love/services/trackbacks/339319.html1 基本解释

  extern可以|于变量或者函数前Q以标示变量或者函数的定义在别的文件中Q提C? ~译器遇到此变量和函数时在其他模块中L其定义?br />
另外Qextern也可用来q行链接指定?br /> 2 问题Qextern 变量

在一个源文g里定义了一个数l:

char a[6];

在另外一个文仉用下列语句进行了声明Q?br />
extern char *aQ?/td>

请问Q这样可以吗Q?

{? 案与分析Q?br />
1)、不可以Q程序运行时会告诉你非法讉K。原因在于,指向cdT的指针ƈ不等价于cdT的数l。extern char *a声明的是一个指针变量而不是字W数l,因此与实际的定义不同Q从而造成q行旉法访问。应该将声明改ؓextern char a[ ]?br />
2)、例子分析如下,如果a[] = "abcd",则外部变量a=0x61626364 (abcd的ASCII码?Q?a昄没有意义Q如下图Q?br />
500)this.width=500;" width="500" border="0">
昄a指向的空_0x61626364Q没有意义,易出现非法内存访问?br />   3)、在使用extern时候要严格对应声明时的格式Q在实际~程中,q样的错误屡见不鲜?br /> 4)、extern用在变量声明中常常有q样一? 作用Q你?.c文g中声明了一个全局的变量,q个全局的变量如果要被引用,放?.h中ƈ用extern来声明?br /> 3 问题Qextern 函数1

常常见extern攑֜函数的前面成为函数声明的一部分Q那么,C语言的关键字 extern在函数的声明中v什么作用?

{案与分析:

如果函数的声明中带有关键字externQ仅仅是暗示q个 函数可能在别的源文g里定义,没有其它作用。即下述两个函数声明没有明显的区别:

extern int f(); 和int f();

当然Q这L用处q是? 的,是在程序中取代include “*.h”来声明函敎ͼ在一些复杂的目中,我比较习惯在所有的函数声明前添加extern修饰?br />
4 问题Qextern 函数2

当函数提供方单方面修改函数原型时Q如果用方不知情l沿? 原来的externxQ这L译时~译器不会报错。但是在q行q程中,因ؓ了或者多了输入参敎ͼ往往会照成系l错误,q种情况应该如何解决Q?br />
{案与分析:

目前业界针对q种情况的处理没有一个很完美的方案,通常的做法是提供方在自己的xxx_pub.h中提供对外部接口? 声明Q然后调用方include该头文gQ从而省去externq一步。以避免q种错误?br />
宝剑有双锋,对extern的应用,不同? 场合应该选择不同的做法?br />
5 问题Qextern “C”

在C++环境下 用C函数的时候,常常会出现编译器无法扑ֈobj模块中的C函数定义Q从而导致链接失败的情况Q应该如何解册U情况呢Q?br />
{案与分 析:

C++语言在编译的时候ؓ了解军_数的多态问题,会将函数名和参数联合h生成一个中间的函数名称Q而C语言则不会,因此会造成 链接时找不到对应函数的情况,此时C函数需要用extern “C”q行链接指定Q这告诉~译器,请保持我的名Uͼ不要l我生成用于链接的中间函数名?br />
下面是一个标准的写法Q?br />
//?h文g的头?br /> #ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif /* __cplusplus */


//.h文gl束的地?br /> #ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

原文Q?http://blog.chinaunix.net/u2/67661/showart_677178.html


qLv蓝梦 2010-11-29 15:29 发表评论
]]>
C-枚Dhttp://m.tkk7.com/jasmine214--love/archive/2010/11/29/339317.htmlqLv蓝梦qLv蓝梦Mon, 29 Nov 2010 07:10:00 GMThttp://m.tkk7.com/jasmine214--love/archive/2010/11/29/339317.htmlhttp://m.tkk7.com/jasmine214--love/comments/339317.htmlhttp://m.tkk7.com/jasmine214--love/archive/2010/11/29/339317.html#Feedback0http://m.tkk7.com/jasmine214--love/comments/commentRss/339317.htmlhttp://m.tkk7.com/jasmine214--love/services/trackbacks/339317.html阅读全文

qLv蓝梦 2010-11-29 15:10 发表评论
]]>
C-static变量和函?/title><link>http://m.tkk7.com/jasmine214--love/archive/2010/11/29/339315.html</link><dc:creator>qLv蓝梦</dc:creator><author>qLv蓝梦</author><pubDate>Mon, 29 Nov 2010 06:51:00 GMT</pubDate><guid>http://m.tkk7.com/jasmine214--love/archive/2010/11/29/339315.html</guid><wfw:comment>http://m.tkk7.com/jasmine214--love/comments/339315.html</wfw:comment><comments>http://m.tkk7.com/jasmine214--love/archive/2010/11/29/339315.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/jasmine214--love/comments/commentRss/339315.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/jasmine214--love/services/trackbacks/339315.html</trackback:ping><description><![CDATA[<p>static关键字是C, C++中都存在的关键字, 它主要有三种使用方式, 其中前两U只指在C语言中? W三U在C++中?C,C++中具体细微操作不相? 本文以C++为准).<br /> (1)局部静态变?br /> (2)外部静态变?函数<br /> (3) 静态数据成?成员函数</p> <p> </p> <p>下面p三种使用方式及注意事分别说?/p> <p> </p> <p>一、局部静态变?/p> <p> </p> <p>在C/C++? 局部变量按照存储Ş式可分ؓ三种auto, static, register<br /> (<C语言E序设计(W二 ?>谭浩? W?74-175?<br /> 与autocd(普?局部变量相? static局部变量有三点不同</p> <p><br /> 1. 存储I间分配不同<br /> autocd分配在栈? 属于动态存储类? 占动态存储区I间, 函数调用l束后自动释? 而static分配在静态存储区, 在程序整个运行期间都不释? 两者之间的作用域相? 但生存期不同.</p> <p><br /> 2. static局部变量在所处模块在初次q行时进行初始化工作, 且只操作一?/p> <p><br /> 3. 对于局部静态变? 如果不赋初? ~译期会自动赋初?或空字符, 而autocd的初值是不确定的. (对于C++中的class对象例外, class的对象实例如果不初始? 则会自动调用默认构造函? 不管是否是staticcd)<br /> 特点: static局部变量的”记忆?#8221;与生存期?#8221;全局?#8221;<br /> 所?#8221;记忆?#8221;是指在两ơ函数调用时, 在第二次调用q入? 能保持第一ơ调用退出时的? </p> <p> </p> <p>CZE序一<br /> #include <iostream><br /> using namespace std;<br /> void staticLocalVar()<br /> {<br /> static int a = 0; // q行期时初始化一? 下次再调用时, 不进行初始化工作<br /> cout<<"a="<<a<<endl;<br /> ++a;<br /> }<br /> int main()<br /> {<br /> staticLocalVar(); // W一ơ调? 输出a=0<br /> staticLocalVar(); // W二ơ调? 记忆了第一ơ退出时的? 输出a=1<br /> return 0;<br /> }</p> <p>应用:<br /> 利用”记忆?#8221;, 记录函数调用的次?CZE序一)<br /> 利用生存期的”全局?#8221;, 改善”return a pointer / reference to a local object”的问? Local object的问题在于退出函? 生存期即l束,. 利用static的作? 廉变量的生存期.</p> <p> </p> <p>CZE序?<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局部变? 用于q回地址有效<br /> const unsigned char *pChIP = (const unsigned char *)&IpAddr;<br /> sprintf(strBuff, "%u.%u.%u.%u", pChIP[0], pChIP[1], pChIP[2], pChIP[3]);<br /> return strBuff;<br /> }</p> <p>注意事项:<br /> 1. “记忆?#8221;, E序q行很重要的一点就是可重复? 而static变量?#8221;记忆?#8221;破坏了这U可重复? 造成不同时刻臌行的l果可能不同.<br /> 2. “生存?#8221;全局性和唯一? 普通的local变量的存储空间分配在stack? 因此每次调用函数? 分配的空间都可能不一? 而statich全局唯一性的特点, 每次调用? 都指向同一块内? q就造成一个很重要的问? ----不可重入?!!<br /> q样在多U程E序设计或递归E序设计? 要特别注意这个问?<br /> (不可重入性的例子可以? ?lt;effective C++ (2nd)>(影印?W?03-105?<br /> 下面针对CZE序? 分析在多U程情况下的不安全?(为方便描q? 标上行号)<br /> ?const char * IpToStr(UINT32 IpAddr)<br /> ? {<br /> ?static char strBuff[16]; // static局部变? 用于q回地址有效<br /> ?const unsigned char *pChIP = (const unsigned char *)&IpAddr;<br /> ? sprintf(strBuff, "%u.%u.%u.%u", pChIP[0], pChIP[1], pChIP[2], pChIP[3]);<br /> ? return strBuff;<br /> ?}<br /> 假设现在有两个线EA,Bq行期间都需要调用IpToStr()函数, ?2位的IP地址转换成点?0q制的字W串形式. 现A先获得执行机? 执行IpToStr(), 传入的参数是0x0B090A0A, 序执行完应该返回的指针存储区内Ҏ:”10.10.9.11”, 现执行到⑥时, 失去执行? 调度到BU程执行, BU程传入的参数是0xA8A8A8C0, 执行至⑦, 静态存储区的内Ҏ192.168.168.168. 当再调度到A执行? 从⑥l箋执行, ׃strBuff的全局唯一? 内容已经被BU程冲掉, 此时q回的将?92.168.168.168字符? 不再?0.10.9.11字符?</p> <p> </p> <p>二、外部静态变量/函数</p> <p> </p> <p>在C?static有了W二U含义:用来表示不能被其它文件访问的全局变量和函数。但Z限制全局变量/函数的作用域, 函数或变量前加static使得函数成ؓ静态函数。但此处“static”的含义不是指存储方式Q而是指对函数的作用域仅局限于本文?所以又U内部函 ?。注意此? 对于外部(全局)变量, 不论是否有static限制, 它的存储区域都是在静态存储区, 生存期都是全局? 此时的static只是起作用域限制作用, 限定作用域在本模?文g)内部.<br /> 使用内部函数的好处是Q不同的人编写不同的函数Ӟ不用担心自己? 义的函数Q是否会与其它文件中的函数同名?/p> <p> </p> <p>CZE序?</p> <p>//file1.cpp</p> <p>static int varA;<br /> int varB;<br /> extern void funA()<br /> {<br /> ……<br /> }</p> <p>static void funB()<br /> {<br /> ……<br /> }</p> <p>//file2.cpp</p> <p>extern int varB; // 使用file1.cpp中定义的全局变量<br /> extern int varA; // 错误! varA是staticcd, 无法在其他文件中使用<br /> extern vod funA(); // 使用file1.cpp中定义的函数<br /> extern void funB(); // 错误! 无法使用file1.cpp文g中static函数</p> <p> </p> <p>三、静态数据成员/成员函数(C++Ҏ)</p> <p> </p> <p>C+ +重用了这个关键字Qƈ赋予它与前面不同的第三种含义Q表C属于一个类而不是属于此cȝM特定对象的变量和函数. q是与普通成员函数的最大区? 也是其应用所? 比如在对某一个类的对象进行计数时, 计数生成多少个类的实? 可以用到静态数据成? 在这里面, static既不是限定作用域? 也不是扩展生存期的作? 而是指示变量/函数在此cM的唯一? q也?#8221;属于一个类而不是属于此cȝM特定对象的变量和函数”的含? 因ؓ它是Ҏ个类来说是唯一? 因此不可能属于某一个实例对象的. (针对静态数据成员而言, 成员函数不管是否是static, 在内存中只有一个副? 普通成员函数调用时, 需要传入this指针, static成员函数调用? 没有this指针. )</p> <p> </p> <p>LCZE序?<effective c++ (2nd)>(影印?W?9?<br /> class EnemyTarget {<br /> public:<br /> EnemyTarget() { ++numTargets; }<br /> EnemyTarget(const EnemyTarget&) { ++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 /> 另外, 在设计类的多U程操作? ׃POSIX库下的线E函数pthread_create()要求是全局? 普通成员函数无法直接做为线E函? 可以考虑用Static成员函数做线E函?</p> <p>原文Q?http://lagvin.bokee.com/viewdiary.21658934.html<br /> </p> <img src ="http://m.tkk7.com/jasmine214--love/aggbug/339315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/jasmine214--love/" target="_blank">qLv蓝梦</a> 2010-11-29 14:51 <a href="http://m.tkk7.com/jasmine214--love/archive/2010/11/29/339315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C -structl构体的巨大作用http://m.tkk7.com/jasmine214--love/archive/2010/11/29/339311.htmlqLv蓝梦qLv蓝梦Mon, 29 Nov 2010 06:31:00 GMThttp://m.tkk7.com/jasmine214--love/archive/2010/11/29/339311.htmlhttp://m.tkk7.com/jasmine214--love/comments/339311.htmlhttp://m.tkk7.com/jasmine214--love/archive/2010/11/29/339311.html#Feedback0http://m.tkk7.com/jasmine214--love/comments/commentRss/339311.htmlhttp://m.tkk7.com/jasmine214--love/services/trackbacks/339311.html面对一个h的大?/font>C/C++E序Ӟ只看其对struct 的用情冉|们就可以对其~写者的~程l验q行评估。因Z? 大型?/font>C/C++E序Q势必要涉及一?/font>(甚至大量)q行数据l合的结构体Q这些结构体可以原本意义属于一个整体的数据l合在一赗从某种E度上来 _会不会用structQ怎样?/font>struct 是区别一?span onclick="tagshow(event)" class="t_tag">开?/span>人员是否具备丰富开发经历的标志?/font>

      在网l协议?span onclick="tagshow(event)" class="t_tag">通信控制?span onclick="tagshow(event)" class="t_tag">嵌入?/span>?/font>C/C++~程中,我们l常要传送的不是单的字节(char型数l)Q而是多种数据l合h的一个整体,其表现Ş式是一? l构体。经验不的开发h员往往所有需要传送的内容依顺序保存在char 型数l中Q通过指针偏移的方法传送网l报文等信息。这样做~程复杂Q易 出错Q而且一旦控制方式及通信协议有所变化Q程序就要进行非常细致的修改?/font>


      一个有l验的开发者则灉|q用l构体,举一个例子,假设|络或控制协议中需要传送三U报文,其格式分别ؓpacketA?/font>packetB?/font>packetCQ?/font>


struct structA


{



int a;



char b;


};


struct structB


{



char a;



short b;


};


struct structC


{



int a;



char b;



float c;


}


优秀的程?span onclick="tagshow(event)" class="t_tag">设计者这栯计传送的报文Q?/font>


struct CommuPacket


{



int iPacketType;
//
报文cd标志



union
//
每次传送的是三U? 报文中的一U,使用union



{



struct structA packetA; struct structB packetB;



struct structC packetC;



}


};


在进行报文传? Ӟ直接传?/font>struct CommuPacket 一个整体?/font>


假设发?span onclick="tagshow(event)" class="t_tag">函数的原形如下:



// pSendData
Q发送字节流的首地址Q?/font>iLenQ要发送的长度



Send(char * pSendData, unsigned int iLen);


      发送方可以直接q行如下调用发?/font>struct CommuPacket 的一?span onclick="tagshow(event)" class="t_tag">实例sendCommuPacketQ?/font>


Send( (char *)&sendCommuPacket , sizeof(CommuPacket) );



假设接收函数的原 形如下:



// pRecvData
Q发送字节流的首地址Q?/font>iLenQ要接收的长?/font>



//
q回|实际接收到的字节?/font>


unsigned int Recv(char * pRecvData, unsigned int iLen)Q?/font>


      接收方可以直接进行如下调用将接收到的数据保存?/font>struct CommuPacket 的一个实?/font>recvCommuPacket 中:


Recv( (char *)&recvCommuPacket , sizeof(CommuPacket) );


      接着判断报文cdq行相应处理Q?/font>


switch(recvCommuPacket. iPacketType)


{


case PACKET_A:



//A
cL文处?/font>


break;


case PACKET_B:



//B
cL文处?/font>


break;


case PACKET_C:



//C
cL文处?/font>


break;


}


以上E序中最值得注意的是


Send( (char *)&sendCommuPacket , sizeof(CommuPacket) );


Recv( (char *)&recvCommuPacket , sizeof(CommuPacket) );


中的强制cd转换Q?/font>(char *)&sendCommuPacket?/font>(char *)&recvCommuPacketQ? 先取地址Q再转化?/font>char 型指针,q样可以直接利用处理字节流的函数?/font>


      利用q种强制cd转化Q我们还可以方便E序的编写,例如? ?/font>sendCommuPacket 所?span onclick="tagshow(event)" class="t_tag">内存初始化ؓ0Q可以这栯用标准库函数memset()Q?/font>



memset((char *)&sendCommuPacket,0, sizeof(CommuPacket));


原文Q?http://www.arm16.com/viewthread.php?tid=397



qLv蓝梦 2010-11-29 14:31 发表评论
]]>
#ifdef #define 条g~译http://m.tkk7.com/jasmine214--love/archive/2010/11/29/339310.htmlqLv蓝梦qLv蓝梦Mon, 29 Nov 2010 06:11:00 GMThttp://m.tkk7.com/jasmine214--love/archive/2010/11/29/339310.htmlhttp://m.tkk7.com/jasmine214--love/comments/339310.htmlhttp://m.tkk7.com/jasmine214--love/archive/2010/11/29/339310.html#Feedback0http://m.tkk7.com/jasmine214--love/comments/commentRss/339310.htmlhttp://m.tkk7.com/jasmine214--love/services/trackbacks/339310.html#ifndef、(或?ifndef)?def?endif{宏q几个宏是ؓ了进行条件编译。一般情况下Q源E序? 所有的行都参加~译。但是有时希望对其中一部分内容只在满一定条件才q行~译Q也是对一部分内容指定~译的条Ӟq就?#8220;条g~译”。有Ӟ希望当满 x条g时对一l语句进行编译,而当条g不满x则编译另一l语句?br />   条g~译命o最常见的Ş式ؓQ?br />   #ifdef 标识W?br />   E序D?
  #else
  E序D?
  #endif
 
  它的作用是:当标识符已经被定义过(一般是?define命o定义)Q则对程序段1q行~译Q否则编译程序段2?br />   其中#else部分也可以没有,卻I
  #ifdef
  E序D?
  #denif
 
  q里?#8220;E序D?#8221;可以是语句组Q也可以是命令行。这U条件编译可以提高C源程序的通用性。如果一个C源程序在不同计算机系l上pȝ上运行,而不同的计算? 又有一定的差异。例如,我们有一个数据类型,在Windowsq_中,应该使用longcd表示Q而在其他q_应该使用float表示Q这样往往需要对? E序作必要的修改Q这降低了E序的通用性。可以用以下的条件编译:
  #ifdef WINDOWS
  #define MYTYPE long
  #else
  #define MYTYPE float
  #endif
 
  如果在Windows上编译程序,则可以在E序的开始加?br />   #define WINDOWS
 
  q样则编译下面的命o行:
  #define MYTYPE long
 
  如果在这l条件编译命令之前曾出现以下命o行:
  #define WINDOWS 0
 
  则预~译后程序中的MYTYPE都用float代替。这P源程序可以不必作M修改可以用于不同类型的计算机系l。当然以上介l的只是一U简单的? 况,可以Ҏ此思\设计出其它的条g~译?br />   例如Q在调试E序Ӟ常常希望输出一些所需的信息,而在调试完成后不再输些信息。可以在源程序中插入以下的条件编译段Q?br />   #ifdef DEBUG
  print ("device_open(%p)\n", file);
  #endif
 
  如果在它的前面有以下命o行:
  #define DEBUG
 
  则在E序q行时输出file指针的|以便调试分析。调试完成后只需这个define命o行删除即可。有人可能觉得不用条件编译也可达此目的,卛_调试 时加一批printf语句Q调试后一一printf语句删除厅R的,q是可以的。但是,当调试时加的printf语句比较多时Q修改的工作量是很大 的。用条g~译Q则不必一一删改printf语句Q只需删除前面的一?#8220;#define DEBUG”命o卛_Q这时所有的用DEBUG作标识符的条件编译段都其中的printf语句不v作用Q即L一控制的作用,如同一?#8220;开?#8221;一栗?br />   有时也采用下面的形式Q?br />   #ifndef 标识W?br />   E序D?
  #else
  E序D?
  #endif
 
  只是W一行与W一UŞ式不同:?#8220;ifdef”改ؓ“ifndef”。它的作用是Q若标识W未被定义则~译E序D?Q否则编译程序段2。这UŞ式与W一U? 形式的作用相反?br />   以上两种形式用法差不多,Ҏ需要Q选一U,视方便而定?br />   q有一UŞ式,是#if后面的是一个表辑ּQ而不是一个简单的标识W:
  #if 表达?br />   E序D?
  #else
  E序D?
  #endif
 
  它的作用是:当指定的表达式gؓ真(非零Q时q译程序段1Q否则编译程序段2。可以事先给定一定条Ӟ使程序在不同的条件下执行不同的功能?br />   例如Q输入一行字母字W,Ҏ需要设|条件编译,使之能将字母全改为大写输出,或全改ؓ写字母输出?br />   #define LETTER 1
  main()
  {
  char str[20]="C Language",c;
  int i=0;
  while((c=str[i])!='\0'){
  i++;
  #if LETTER
  if(c>='a'&&c<='z') c=c-32;
  #else
  if(c>='A'&&c<='Z') c=c+32;
  #endif
  printf("%c",c);
  }
  }
 
  q行l果为:C LANGUAGE
  现在先定义LETTER?Q这样在预处理条件编译命令时Q由于LETTER为真Q非ӞQ则对第一个if语句q行~译Q运行时使小写字母变大写。如果将 E序W一行改为:
  #define LETTER 0
 
  则在预处理时Q对W二个if语句q行~译处理Q大写字母变成写字母Q大写字母与相应的小写字母的ASCII代码?2Q。此时运行情况ؓQ?br />   c language
  有h会问Q不用条件编译命令而直接用if语句也能辑ֈ要求Q用条g~译命o有什么好处呢Q的,此问题完全可以不用条件编译处理,但那样做目标E序长(? 为所有语句都~译Q,而采用条件编译,可以减少被编译的语句Q从而减目标的长度。当条g~译D|较多Ӟ目标E序长度可以大大减少?br /> 原文Q?http://blog.csdn.net/sunshuai03/archive/2005/11/17/531596.aspx


qLv蓝梦 2010-11-29 14:11 发表评论
]]>typedef cd重命??define 宏定?http://m.tkk7.com/jasmine214--love/archive/2010/11/29/339307.htmlqLv蓝梦qLv蓝梦Mon, 29 Nov 2010 05:59:00 GMThttp://m.tkk7.com/jasmine214--love/archive/2010/11/29/339307.htmlhttp://m.tkk7.com/jasmine214--love/comments/339307.htmlhttp://m.tkk7.com/jasmine214--love/archive/2010/11/29/339307.html#Feedback0http://m.tkk7.com/jasmine214--love/comments/commentRss/339307.htmlhttp://m.tkk7.com/jasmine214--love/services/trackbacks/339307.html typedef的语法描q?br /> typedef cd名称 cd标识W?
typedef为系l保留字Q?#8220;cd名称”为已知数据类型名Uͼ包括基本数据cd和用戯定义数据cdQ?#8220;cd标识W?#8221; 为新的类型名U。例?
typedef double LENGTH;
typedef unsigned int COUNT;
? 义新的类型名UC后,可像基本数据cd那样定义变量。例如:
typedef unsigned int COUNT;
unsigned int b;
COUNT c;
typedef 的主要应用有如下的几UŞ式:
1) 为基本数据类型定义新的类型名。例如:
typedef unsigned int COUNT;
typedef double AREA;
此种应用的主要目的,首先是丰富数据类型中包含的属 性信息,其次是ؓ了系l移植的需要,E后详细描述?br /> 2) 定义数据cdQ结构体、公用体和枚丄型)定义z的cd名称。例如:
struct Point
{
double x;
double y;
double z;
};
struct Point oPoint1={100Q?00Q?};
struct Point oPoint2;
其中l构体struct Point为新的数据类型,在定义变量的时候均要有保留字structQ而不能像int和double那样直接使用Point来定义变量。如果经q如下的 修改Q?br /> typedef struct tagPoint
{
double x;
double y;
double z;
} Point;
定义变量的方法可以简化ؓ
Point oPoint;
׃定义l构体类型有多种形式Q因此可以修? 如下Q?br /> typedef struct
{
double x;
double y;
double z;
} Point;
3) 为数l定义简z的cd名称。例如,定义三个长度?的整型数l,
int a[10]Qb[10]Qc[10]Qd[10];
在C语言中,可以长度ؓ10的整型数l看作ؓ一个新的数据类型,再利用typedef为其? 定义一个新的名Uͼ可以更加zŞ式定义此U类型的变量Q具体的处理方式如下:
typedef int INT_ARRAY_10[10];
typedef int INT_ARRAY_20[20];
INT_ARRAY_10 aQbQcQd;
INT_ARRAY_20 e;
其中 INT_ARRAY_10和INT_ARRAY_20为新的类型名Q?0 ?0 为数l的长度。aQbQcQd均是长度?0的整型数l,e是长度ؓ20的整型数l?br /> 4) 为指针定义简z的名称。首先ؓ数据指针定义新的名称Q例?br /> typedef char * STRING;
STRING csName={“Jhon”};
其次Q可以ؓ函数指针定义新的名称Q例?br /> typedef int (*MyFUN)(int aQint b);
其中MyFUN代表 int *XFunction(int aQintb)cd指针的新名称。例?br /> typedef int (*MyFUN)(int aQint b);
int Max(int aQint b);
MyFUN *pMyFun;
pMyFun= Max;
在用typedefӞ应当注意如下的问题:
1) typedef的目的是为已知数据类型增加一个新的名U。因此ƈ没有引入新的数据cd?br /> 2) typedef 只适于cd名称定义Q不适合变量的定义?br /> 3) typedef ?defineh怼的之处,但是实质不同?br /> 提示 #define AREA double ?typedef double AREA 可以辑ֈ相同的效果。但是其实质不同Q? #define为预~译处理命oQ主要定义常量,此常量可以ؓM的字W及其组合,在编译之前,此帔R出现的所有位|,用其代表的字W或字符l合无条? 的替换,然后q行~译。typedef是ؓ已知数据cd增加一个新名称Q其原理与用int double{保留字一致?br /> 原文Q?http://blog.chinaunix.net/u2/75045/showart_1120891.html


qLv蓝梦 2010-11-29 13:59 发表评论
]]>
վ֩ģ壺 13СϴƵվ| ޶Ʒav| ѲvƬ߹ۿ| 99þƷƵ77| ӰƬһѹۿ| ĻƵ| һƬѿ| һƵ| һëƬѲһ| ҹƵ| һaƬþëƬѿ| һɫaƬþëƬ| ˸徫Ʒѹۿ| ëƬڵ| Ļѿ| jŮjڲվ| պƷѹۿ| 18ëƬѹۿ| AVһ֤| Ƶ| ůůձ| ƷŮٸaѾþ| ߹ۿվڵ | Ʒ޹AVƬý| ƵѲ| sssۺþþþ| ޾Ʒٸ30P| ޳߹ۿ| ޻ҳ߹ۿ| Ʒ޳A߹ۿ| ޾ƷƵѹۿ| ëƬ߲ѹۿ| 999ƵƷѲŹۿ| ѹۿavëƬվ| ޾ƷƵ߹ۿ㶮| 㽶þۺӰ| ޾Ʒվ߹ۿ㶮| ŷ޾Ʒ˾þԻ| jizzѲ| AëƬA| Ʒ鶹Ѱ|