﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-唐吉诃德-文章分类-C/C++</title><link>http://www.cppblog.com/tdweng/category/14699.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 26 Jun 2013 14:40:43 GMT</lastBuildDate><pubDate>Wed, 26 Jun 2013 14:40:43 GMT</pubDate><ttl>60</ttl><item><title>Datatype misalignment </title><link>http://www.cppblog.com/tdweng/articles/145076.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Tue, 26 Apr 2011 11:26:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/145076.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/145076.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/145076.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/145076.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/145076.html</trackback:ping><description><![CDATA[<p><a href="http://blog.csdn.net/lqk1985/archive/2008/10/23/3129976.aspx">http://blog.csdn.net/lqk1985/archive/2008/10/23/3129976.aspx</a></p>
<p>&nbsp;</p>
<p>对于读取数据流时（如网络或文件）要特别注意。</p>
<p>比如</p>
<p>PBYTE pData;</p>
<p>//指向接收到的数据流</p>
<p>int * pi = pData + 这次接收到数据流的大小 - 4；</p>
<p>//指向接收到数据流的最后4位,可能客户端发过来的这个数据流最后4位是int，那样就是对齐好的了。也有可能不是int。</p>
<p>if *pi = 4561321&nbsp; endparse data;//判断作为数据流的结束标志，最后4位的前面可能是全是char的。</p>
<p>&nbsp;</p>
<p>由于这最后4位可能不是int，那样就有可能不对齐，这里就会出现Datatype misalignment错误。但是我们还是必须通过最后4位作为结束标志，而只有知道什么时候结束才能用int指针指向最后4位才不会出现对齐错误。这样形成了一个死循环，难道没办法解决了么？</p>
<p>&nbsp;</p>
<p>PBYTE pData;</p>
<p>PBYTE * pi = pData + 这次接收到数据流的大小 - 4；</p>
<p>int i;</p>
<p>memcpy(&amp;i, pi, 4);</p>
<p>if i = 4561321&nbsp; endparse data;</p>
<p>&nbsp;</p>
<p>这样就可以解决用int* pi指向未对齐的int错误了。</p>
<p>这一招对所有碰到Datatype misalignment的数据的访问应该都有效，就是把Datatype misalignment的数据用memcpy拷贝到对齐的内存来访问。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>1，解析数据流时应该时刻注意。如果需要把一个数据流（BUFFER）转化成结构进行取值，就应该把这个结构定义为按字节存取.考虑如下结构：</p>
<p>struct a{</p>
<p>char a;<br>short b;<br>long c;<br>};<br>如果某个数据流中包含这样的结构，而且我们要直接将数据流的指针转化成该结构的指针，然后直接取结构成员的值，我们就应该将这个结构定义成按字节访问，即将其夹在语句<br>#pragma pack(push,1)//设为1字节对齐<br>...</p>
<p>#pragma pack(pop)//还原为原来的字节对齐方式<br>之中。如果我们不这样做，编译器会将成员b的地址对齐到short指针的地址，即在a之后加上一个char即8位的成员，将C对齐到LONG，即在B之后再加一个char成员。如此一来，成员B和成员C就得不到正确的值了。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>pragma pack 只作用于结构的定义，而不是分配内存空间。把一个结构定义为pack1后，这个结构在程序中就一直是1了。</p>
<p>上面这个例子是客户端发送3个连续的数据不是发送结构体，服务端接收结构体。</p>
<p>&nbsp;</p>
<p>如果客户端也发送结构体，服务端也接收结构体就不需要这样了。但是前提是双方的对齐方式一致。所以在客户端发送前也要用#pragma pack()一下，服务端也要#pragma pack()一下。</p>
<p>&nbsp;</p>
<p>最好还是客户端也单个数据发送，服务端也单个数据接收。</p>
<p>&nbsp;</p>
<p>如果我们定义一个普通的结构用来存放一些数据，则不用定义成按字节存取，编译器会加上一些占位成员，但并不会影响程序的运行。从这个意义上讲，在ARM中，将结构成员定义成CHAR和SHORT来节约内存是没有意义的。</p>
<p>一个典型的例子就文件系统的驱动程序，文件是以一些已经定义好的结构存放在存储介质上的，它们被读取到一个BUFFER中，而具体取某个文件、目录结构时，我们会将地址转化成结构而读取其中的值。</p>
<p><br>2，访问外设时。<br>例如，磁盘驱动通常以16BIT的方式存取数据，即每次存取两个字节，这样就要求传给它的BUFFER是双字节对齐的，驱动程序应该至上层传来的指针做出正确的处理以保证数据的正确性。</p>
<p><br>3.有时，我们没有将数据流指针转化为结构指针取值，但如果我们读取的是双字节或者是四字节的数据，同样需要注意对齐的问题，例如，如果从一个BUFFER的偏移10处读取一个四字节值，则实际得到的值是偏移8处的<br>地址上的DWORD值。</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/lqk1985/archive/2008/10/23/3129842.aspx">http://blog.csdn.net/lqk1985/archive/2008/10/23/3129842.aspx</a></p>
<img src ="http://www.cppblog.com/tdweng/aggbug/145076.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2011-04-26 19:26 <a href="http://www.cppblog.com/tdweng/articles/145076.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++关键字：mutable、volatile、explicit以及__based </title><link>http://www.cppblog.com/tdweng/articles/140928.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Tue, 01 Mar 2011 09:32:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/140928.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/140928.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/140928.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/140928.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/140928.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: mutable关键字&nbsp;&nbsp;&nbsp; 关键字mutable是C＋＋中一个不常用的关键字,他只能用于类的非静态和非常量数据成员我们知道一个对象的状态由该对象的非静态数据成员决定,所以随着数据成员的改变,对像的状态也会随之发生变化!如果一个类的成员函数被声明为const类型,表示该函数不会改变对象的状态,也就是该函数不会修改类的非静态数据成员.但是有些时候需要在该类函数中对...&nbsp;&nbsp;<a href='http://www.cppblog.com/tdweng/articles/140928.html'>阅读全文</a><img src ="http://www.cppblog.com/tdweng/aggbug/140928.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2011-03-01 17:32 <a href="http://www.cppblog.com/tdweng/articles/140928.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>移位操作</title><link>http://www.cppblog.com/tdweng/articles/139160.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Sun, 23 Jan 2011 06:53:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/139160.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/139160.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/139160.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/139160.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/139160.html</trackback:ping><description><![CDATA[<div style="TEXT-INDENT: 2em">
<p>最近笔者一直在做JPEG的解码工作，发现用完全使用哈夫曼树进行解码比较费时，而使用表结构存储编码和值的对应关系比较快捷，但是也存在比较难处理的地方，比如解码工作通常是以位为单位的操作，这里必然会涉及到移位操作，而笔者之前对位的操作很少，经验很欠缺，经过这次历练终于发现了一个自己曾经忽视的东西，那就是C/C++中的移位操作容易出错的情况。</p>
<p><span style="COLOR: red"><strong>1、什么样的数据类型可以直接移位</strong></span></p>
<p>char、short、int、long、unsigned char、unsigned short、unsigned int、unsigned long都可以进行移位操作，而double、float、bool、long double则不可以进行移位操作。</p>
<p><span style="COLOR: red"><strong>2、有符号数据类型的移位操作</strong></span></p>
<p>对于char、short、int、long这些有符号的数据类型：</p>
<ul>
    <li>对负数进行左移：符号位始终为1，其他位左移
    <li>对正数进行左移：所有位左移，即 &lt;&lt;，可能会变成负数
    <li>对负数进行右移：取绝对值，然后右移，再取相反数
    <li>对正数进行右移：所有位右移，即 &gt;&gt; </li>
</ul>
<p><span style="COLOR: red"><strong>3、无符号数据类型的移位操作</strong></span></p>
<p>对于unsigned char、unsigned short、unsigned int、unsigned long这些无符号数据类型：</p>
<p>没有特殊要说明的，使用&lt;&lt; 和 &gt;&gt; 操作符就OK了</p>
<p>结束语</p>
<p>8086 中存在逻辑移位、算术移位，而C\C++中的移位似乎既不是逻辑移位，也不是算术移位。</p>
<p>比如-1，我们若对它右移1位，C的结果仍旧是-1，事实上无论右移多少位始终是-1，逻辑移位得到的结果（8位表示）应该是-128，所以这点要注意<br><br>例子：<br><span style="COLOR: red"><strong>1.将 13800138000&nbsp; 转为&nbsp; 91 68 31 08 10 83 00 F0&nbsp; //91为+ 68国家号 不够位长以F补</strong></span><br><br></p>
unsigned char *tt = new unsigned char[12];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcpy((char*)tt,"13800138000");<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tt[11] = 0xFF;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned char *ss = new unsigned char[6];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; (tt[11]&lt;&lt;4) &lt;&lt; endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memset(ss,0xFF,6);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int k=0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0; i&lt;12; i=i+2)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ss[k++] = (tt[i+1]&lt;&lt;4)+(tt[i]&amp;0x0F);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;}<br><span style="COLOR: red"><strong>2. 将 整形 转为 3位字节型16进制，如将 整型 888 转为 16进制&nbsp; 00 03 78<em>(Debug下有效，Release下无效)</em></strong></span><br>&nbsp;&nbsp; char param[4] = {0};<br>&nbsp;&nbsp; &nbsp;int iParamLen = 888;<br>&nbsp;&nbsp;&nbsp; param[0] = iParamLen &gt;&gt; 16;<br>&nbsp;&nbsp;&nbsp; param[1] = ((iParamLen &gt;&gt; 8) &lt;&lt; 32) &gt;&gt; 32;<br>&nbsp;&nbsp;&nbsp; param[2] = (iParamLen &lt;&lt; 32) &gt;&gt; 32;<br><br><span style="COLOR: red"><strong>反之<br></strong></span><br>&nbsp;&nbsp;&nbsp; char param[4] = {0x00,0x03,0x78};<br>&nbsp;&nbsp;&nbsp; int ii1 = 0;<br>&nbsp;&nbsp;&nbsp; ii1 = param[0];<br>&nbsp;&nbsp;&nbsp; ii1 =ii1 &lt;&lt; 8;<br>&nbsp;&nbsp;&nbsp; ii1 = ii1 | param[1];<br>&nbsp;&nbsp;&nbsp; ii1 =ii1 &lt;&lt; 8;<br>&nbsp;&nbsp;&nbsp;&nbsp;ii1 = ii1 | param[2];<br></div>
<img src ="http://www.cppblog.com/tdweng/aggbug/139160.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2011-01-23 14:53 <a href="http://www.cppblog.com/tdweng/articles/139160.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>BCD码、十六进制与十进制互转</title><link>http://www.cppblog.com/tdweng/articles/139022.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Fri, 21 Jan 2011 06:04:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/139022.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/139022.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/139022.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/139022.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/139022.html</trackback:ping><description><![CDATA[<p><span onmouseup=NewHighlight(event) class=wenzhang_con id=articlecontent style="WIDTH: 740px">
<div>在<font style="BACKGROUND-COLOR: #ffff00">做嵌入式软件的设计中，经常会遇到十六进制、BCD码与十进制之间的转换，最近做M1卡的应用中，涉及了大量的十六进制、BCD码与十进制之间的转换。笔者通过对BCD码、十六进制 权的理解，轻松的实现了他们之间的互换。</font></div>
<div><font style="BACKGROUND-COLOR: #ffff00">#include &lt;stdio.h&gt; <br>#include &lt;string.h</font>&gt; </div>
<div>///////////////////////////////////////////////////// <br>// <br>//功能：二进制取反 <br>// <br>//输入：const unsigned char *src&nbsp; 二进制数据 <br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 待转换的二进制数据长度 <br>// <br>//输出：unsigned char *dst&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 取反后的二进制数据 <br>// <br>//返回：0&nbsp;&nbsp;&nbsp; success <br>// <br>////////////////////////////////////////////////////// <br>int convert(unsigned char *dst, const unsigned char *src, int length) <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i; </div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(i=0; i&lt;length; i++) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dst[i] = src[i]^0xFF; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0; <br>} </div>
<div>////////////////////////////////////////////////////////// <br>// <br>//功能：十六进制转为十进制 <br>// <br>//输入：const unsigned char *hex&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 待转换的十六进制数据 <br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 十六进制数据长度 <br>// <br>//输出： <br>// <br>//返回：int&nbsp; rslt&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 转换后的十进制数据 <br>// <br>//思路：十六进制每个字符位所表示的十进制数的范围是0 ~255，进制为256 <br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 左移8位(&lt;&lt;8)等价乘以256 <br>// <br>///////////////////////////////////////////////////////// <br>unsigned long HextoDec(const unsigned char *hex, int length) <br>{ <br>&nbsp;&nbsp;&nbsp; int i; <br>&nbsp;&nbsp;&nbsp; unsigned long rslt = 0; </div>
<div>&nbsp;&nbsp;&nbsp; for(i=0; i&lt;length; i++) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rslt += (unsigned long)(hex[i])&lt;&lt;(8*(length-1-i)); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; } </div>
<div>&nbsp;&nbsp;&nbsp; return rslt; <br>} </div>
<div><br>///////////////////////////////////////////////////////// <br>// <br>//功能：十进制转十六进制 <br>// <br>//输入：int dec&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 待转换的十进制数据 <br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 转换后的十六进制数据长度 <br>// <br>//输出：unsigned char *hex&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 转换后的十六进制数据 <br>// <br>//返回：0&nbsp;&nbsp;&nbsp; success <br>// <br>//思路：原理同十六进制转十进制 <br>////////////////////////////////////////////////////////// <br>int DectoHex(int dec, unsigned char *hex, int length) <br>{ <br>&nbsp;&nbsp;&nbsp; int i; </div>
<div>&nbsp;&nbsp;&nbsp; for(i=length-1; i&gt;=0; i--) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hex[i] = (dec%256)&amp;0xFF; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dec /= 256; <br>&nbsp;&nbsp;&nbsp; } </div>
<div>&nbsp;&nbsp;&nbsp; return 0; <br>} </div>
<div>///////////////////////////////////////////////////////// <br>// <br>//功能：求权 <br>// <br>//输入：int base&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 进制基数 <br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int times&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 权级数 <br>// <br>//输出： <br>// <br>//返回：unsigned long&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当前数据位的权 <br>// <br>////////////////////////////////////////////////////////// <br>unsigned long power(int base, int times) <br>{ <br>&nbsp;&nbsp;&nbsp; int i; <br>&nbsp;&nbsp;&nbsp; unsigned long rslt = 1; </div>
<div>&nbsp;&nbsp;&nbsp; for(i=0; i&lt;times; i++) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rslt *= base; </div>
<div>&nbsp;&nbsp;&nbsp; return rslt; <br>} </div>
<div>///////////////////////////////////////////////////////// <br>// <br>//功能：BCD转10进制 <br>// <br>//输入：const unsigned char *bcd&nbsp;&nbsp;&nbsp;&nbsp; 待转换的BCD码 <br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BCD码数据长度 <br>// <br>//输出： <br>// <br>//返回：unsigned long&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当前数据位的权 <br>// <br>//思路：压缩BCD码一个字符所表示的十进制数据范围为0 ~ 99,进制为100 <br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 先求每个字符所表示的十进制值，然后乘以权 <br>////////////////////////////////////////////////////////// <br>unsigned long&nbsp; BCDtoDec(const unsigned char *bcd, int length) <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp; int i, tmp; <br>&nbsp;&nbsp;&nbsp;&nbsp; unsigned long dec = 0; </div>
<div>&nbsp;&nbsp;&nbsp;&nbsp; for(i=0; i&lt;length; i++) <br>&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp = ((bcd[i]&gt;&gt;4)&amp;0x0F)*10 + (bcd[i]&amp;0x0F);&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dec += tmp * power(100, length-1-i);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp; } </div>
<div>&nbsp;&nbsp;&nbsp;&nbsp; return dec; <br>} </div>
<div>///////////////////////////////////////////////////////// <br>// <br>//功能：十进制转BCD码 <br>// <br>//输入：int Dec&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 待转换的十进制数据 <br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BCD码数据长度 <br>// <br>//输出：unsigned char *Bcd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 转换后的BCD码 <br>// <br>//返回：0&nbsp; success <br>// <br>//思路：原理同BCD码转十进制 <br>// <br>////////////////////////////////////////////////////////// <br>int DectoBCD(int Dec, unsigned char *Bcd, int length) <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp; int i; <br>&nbsp;&nbsp;&nbsp;&nbsp; int temp; </div>
<div>&nbsp;&nbsp;&nbsp;&nbsp; for(i=length-1; i&gt;=0; i--) <br>&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temp = Dec%100; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bcd[i] = ((temp/10)&lt;&lt;4) + ((temp%10) &amp; 0x0F); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dec /= 100; <br>&nbsp;&nbsp;&nbsp;&nbsp; } </div>
<div>&nbsp;&nbsp;&nbsp;&nbsp; return 0; <br>} </div>
<div>int main() <br>{ <br>&nbsp;&nbsp;&nbsp; register int i; <br>&nbsp;&nbsp;&nbsp; unsigned char tmp_bff[12] = ""; </div>
<div>&nbsp;&nbsp;&nbsp; //十六进制转十进制 <br>&nbsp;&nbsp;&nbsp; unsigned char HEX[4] = {0x34, 0xFE, 0x3E, 0xFF}; <br>&nbsp;&nbsp;&nbsp; unsigned long dec_hex = 0; </div>
<div>&nbsp;&nbsp;&nbsp; dec_hex = HextoDec(HEX, 4); <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; printf("dec_hex = %d\n", dec_hex); </div>
<div>&nbsp;&nbsp;&nbsp; //十进制转十六进制 <br>&nbsp;&nbsp;&nbsp; DectoHex(dec_hex, tmp_bff, 4); <br>&nbsp;&nbsp;&nbsp; for(i=0; i&lt;5; i++) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("tmp_bff[%d] = 0x%02X\n",i, tmp_bff[i]); <br>&nbsp;&nbsp;&nbsp; } </div>
<div>&nbsp;&nbsp;&nbsp; //BCD码转十进制 <br>&nbsp;&nbsp;&nbsp; unsigned long dec_bcd = 0; <br>&nbsp;&nbsp;&nbsp; unsigned char BCD[4] = {0x98, 0x23, 0x45, 0x78}; </div>
<div>&nbsp;&nbsp;&nbsp; dec_bcd = BCDtoDec(BCD, 4); <br>&nbsp;&nbsp;&nbsp; printf("dec_bcd = %d\n", dec_bcd); </div>
<div>&nbsp;&nbsp;&nbsp; //十进制转BCD码 <br>&nbsp;&nbsp;&nbsp; DectoBCD(dec_bcd, tmp_bff, 4); <br>&nbsp;&nbsp;&nbsp; for(i=0; i&lt;5; i++) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("tmp_bff[%d] = 0x%02X\n", i, tmp_bff[i]); <br>&nbsp;&nbsp;&nbsp; } </div>
<div>&nbsp;&nbsp;&nbsp; getchar(); <br>} </div>
</span><br>BCD
<p>&#160;</p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;BCDToChar(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">src,unsigned&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;srcLen,&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">dest)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;temp[</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;{</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">};<br>&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;temp2[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;{</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">};<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">srcLen;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp2[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;src[i];<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;src[i]</span><span style="COLOR: #000000">&gt;&gt;</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;temp[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">0x0F</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;temp[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">0x30</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;temp2[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">0x0F</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;temp[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">0x30</span><span style="COLOR: #000000">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dest[i</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;temp[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dest[i</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;temp[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">];<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}</span></div>
<img src ="http://www.cppblog.com/tdweng/aggbug/139022.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2011-01-21 14:04 <a href="http://www.cppblog.com/tdweng/articles/139022.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Visual C++编程命名规则 </title><link>http://www.cppblog.com/tdweng/articles/138643.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Mon, 17 Jan 2011 02:51:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/138643.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/138643.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/138643.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/138643.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/138643.html</trackback:ping><description><![CDATA[<strong><font size=5>一、程序风格：</font></strong>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;<strong> 1、严格采用阶梯层次组织程序代码：</strong>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 各层次缩进的分格采用VC的缺省风格，即每层次缩进为4格，括号位于下一行。要求相匹配的大括号在同一列，对继行则要求再缩进4格。例如：&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;<strong>&nbsp; 2、提示信息字符串的位置</strong>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 在程序中需要给出的提示字符串，为了支持多种语言的开发，除了一些给调试用的临时信息外，其他所有的提示信息必须定义在资源中。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <strong>3、对变量的定义，尽量位于函数的开始位置。</strong>&nbsp;&nbsp;&nbsp;&nbsp;
<p><span style="FONT-SIZE: 14pt"><strong>二、命名规则：</strong></span>&nbsp;&nbsp;&nbsp;&nbsp; <br><strong>&nbsp;&nbsp;&nbsp; 1、变量名的命名规则</strong>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ①、变量的命名规则要求用&#8220;匈牙利法则&#8221;。即开头字母用变量的类型，其余部分用变量的英文意思或其英文意思的缩写,尽量避免用中文的拼音,要求单词的第一个字母应大写。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 即：&nbsp;&nbsp;&nbsp;&nbsp; 变量名=变量类型+变量的英文意思（或缩写）&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 对非通用的变量，在定义时加入注释说明，变量定义尽量可能放在函数的开始处。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 见下表：&nbsp;&nbsp;&nbsp;&nbsp; <br><span style="COLOR: #008000">&nbsp;&nbsp;&nbsp; bool(BOOL)&nbsp;&nbsp;&nbsp;&nbsp; 用b开头&nbsp;&nbsp;&nbsp;&nbsp; bIsParent&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; byte(BYTE)&nbsp;&nbsp;&nbsp;&nbsp; 用by开头&nbsp;&nbsp;&nbsp;&nbsp; byFlag&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; short(int)&nbsp;&nbsp;&nbsp;&nbsp; 用n开头&nbsp;&nbsp;&nbsp;&nbsp; nStepCount&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; long(LONG)&nbsp;&nbsp;&nbsp;&nbsp; 用l开头&nbsp;&nbsp;&nbsp;&nbsp; lSum&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; char(CHAR)&nbsp;&nbsp;&nbsp;&nbsp; 用c开头&nbsp;&nbsp;&nbsp;&nbsp; cCount&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; float(FLOAT)&nbsp;&nbsp;&nbsp;&nbsp; 用f开头&nbsp;&nbsp;&nbsp;&nbsp; fAvg&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; double(DOUBLE)&nbsp;&nbsp;&nbsp;&nbsp; 用d开头&nbsp;&nbsp;&nbsp;&nbsp; dDeta&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; void(VOID)&nbsp;&nbsp;&nbsp;&nbsp; 用v开头&nbsp;&nbsp;&nbsp;&nbsp; vVariant&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; unsigned&nbsp;&nbsp;&nbsp;&nbsp; int（WORD）&nbsp;&nbsp;&nbsp;&nbsp; 用w开头&nbsp;&nbsp;&nbsp;&nbsp; wCount&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; unsigned&nbsp;&nbsp;&nbsp;&nbsp; long(DWORD)&nbsp;&nbsp;&nbsp;&nbsp; 用dw开头&nbsp;&nbsp;&nbsp;&nbsp; dwBroad&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; HANDLE（HINSTANCE）&nbsp;&nbsp;&nbsp;&nbsp; 用h开头&nbsp;&nbsp;&nbsp;&nbsp; hHandle&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; DWORD&nbsp;&nbsp;&nbsp;&nbsp; 用dw开头&nbsp;&nbsp;&nbsp;&nbsp; dwWord&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; LPCSTR(LPCTSTR)&nbsp;&nbsp;&nbsp;&nbsp; 用str开头&nbsp;&nbsp;&nbsp;&nbsp; strString&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 用0结尾的字符串&nbsp;&nbsp;&nbsp;&nbsp; 用sz开头&nbsp;&nbsp;&nbsp;&nbsp; szFileName</span>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 对未给出的变量类型要求提出并给出命名建议给技术委员会。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ②、指针变量命名的基本原则为：&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 对一重指针变量的基本原则为：&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &#8220;p&#8221;+变量类型前缀+命名&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 如一个float*型应该表示为<span style="COLOR: #008000">pfStat&nbsp;&nbsp;&nbsp;</span>&nbsp; <br>&nbsp;&nbsp;&nbsp; 对多重指针变量的基本规则为：&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 二重指针：&nbsp;&nbsp;&nbsp;&nbsp; &#8220;pp&#8221;+变量类型前缀+命名&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 三重指针：&nbsp;&nbsp;&nbsp;&nbsp; &#8220;ppp&#8221;+变量类型前缀+命名&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ......&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ③、全局变量用g_开头,如一个全局的长型变量定义为<span style="COLOR: #008000">g_lFailCount</span>,即：变量名=g_+变量类型+变量的英文意思（或缩写）&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ④、静态变量用s_开头,如一个静态的指针变量定义为<span style="COLOR: #008000">s_plPerv_Inst</span>,即：&nbsp;&nbsp;&nbsp;&nbsp; 变量名=s_+变量类型+变量的英文意思（或缩写）&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ⑤、成员变量用m_开头,如一个长型成员变量定义为<span style="COLOR: #008000">m_lCount</span>;即：变量名=m_+变量类型+变量的英文意思（或缩写）&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ⑥、对枚举类型（enum）中的变量，要求用枚举变量或其缩写做前缀。并且要求用大写。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 如：<span style="COLOR: #008000">enum&nbsp;&nbsp;&nbsp;&nbsp; cmEMDAYS&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; EMDAYS_MONDAY;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; EMDAYS_TUESDAY;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &#8230;&#8230;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; };</span>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ⑦、对struct、union、class变量的命名要求定义的类型用大写。并要加上前缀，其内部变量的命名规则与变量命名规则一致。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 结构一般用S开头&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 如：<span style="COLOR: #008000">struct&nbsp;&nbsp;&nbsp;&nbsp; ScmNPoint&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp; nX;//点的X位置&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp; nY;&nbsp;&nbsp;&nbsp;&nbsp; //点的Y位置&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; };</span>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 联合体一般用U开头&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 如:&nbsp;&nbsp;&nbsp;<span style="COLOR: #008000">&nbsp; union&nbsp;&nbsp;&nbsp;&nbsp; UcmLPoint&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp;&nbsp; lX;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp;&nbsp; lY;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;</span>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 类一般用C开头&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 如：&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;<span style="COLOR: #008000">&nbsp; class&nbsp;&nbsp;&nbsp;&nbsp; CcmFPoint&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public:&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; float&nbsp;&nbsp;&nbsp;&nbsp; fPoint;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; };&nbsp;&nbsp;&nbsp;&nbsp; <br></span>&nbsp;&nbsp;&nbsp; 对一般的结构应该定义为类模板，为以后的扩展性考虑&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 如：&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;<span style="COLOR: #008000">&nbsp; template&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; class&nbsp;&nbsp;&nbsp;&nbsp; CcmTVector3d&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public:&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; TYPE&nbsp;&nbsp;&nbsp;&nbsp; x,y,z;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; };&nbsp;&nbsp;&nbsp;&nbsp; <br></span>&nbsp;&nbsp;&nbsp; ⑧、对常量（包括错误的编码）命名，要求常量名用大写，常量名用英文表达其意思。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 如<span style="COLOR: #008000">：#define&nbsp;&nbsp;&nbsp;&nbsp; CM_FILE_NOT_FOUND&nbsp;&nbsp;&nbsp;&nbsp; CMMAKEHR(0X20B)</span>&nbsp;&nbsp;&nbsp;&nbsp; 其中CM表示类别。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ⑨、对const&nbsp;&nbsp;&nbsp;&nbsp; 的变量要求在变量的命名规则前加入c_,即：c_+变量命名规则；例如：&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;<span style="COLOR: #008000"> const&nbsp;&nbsp;&nbsp;&nbsp; char*&nbsp;&nbsp;&nbsp;&nbsp; c_szFileName;</span>&nbsp;&nbsp;&nbsp;&nbsp; <br><strong>&nbsp;&nbsp;&nbsp; 2、&nbsp;&nbsp;&nbsp;&nbsp; 函数的命名规范：</strong>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 函数的命名应该尽量用英文表达出函数完成的功能。遵循动宾结构的命名法则，函数名中动词在前,并在命名前加入函数的前缀，函数名的长度不得少于8个字母。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 例如：&nbsp;&nbsp;&nbsp;&nbsp; <br><span style="COLOR: #008000">&nbsp;&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp;&nbsp; cmGetDeviceCount(&#8230;&#8230;);</span>&nbsp;&nbsp;&nbsp;&nbsp; <br><strong>&nbsp;&nbsp;&nbsp; 3、函数参数规范：<span style="FONT-SIZE: 12pt">&nbsp;&nbsp;&nbsp;</span>&nbsp; <br></strong>&nbsp;&nbsp;&nbsp; ①、&nbsp;&nbsp;&nbsp;&nbsp; 参数名称的命名参照变量命名规范。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ②、&nbsp;&nbsp;&nbsp;&nbsp; 为了提高程序的运行效率，减少参数占用的堆栈，传递大结构的参数，一律采用指针或引用方式传递。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ③、&nbsp;&nbsp;&nbsp;&nbsp; 为了便于其他程序员识别某个指针参数是入口参数还是出口参数，同时便于编译器检查错误，应该在入口参数前加入const标志。如：&nbsp;&nbsp;&nbsp;&nbsp; <br><span style="COLOR: #008000">&nbsp;&nbsp;&nbsp; &#8230;&#8230;cmCopyString(const&nbsp;&nbsp;&nbsp;&nbsp; char&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; c_szSource,&nbsp;&nbsp;&nbsp;&nbsp; char&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; szDest)</span>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 4、引出函数规范：&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 对于从动态库引出作为二次开发函数公开的函数，为了能与其他函数以及Windows的函数区分，采用类别前缀+基本命名规则的方法命名。例如：在对动态库中引出的一个图象编辑的函数定义为&nbsp;&nbsp;&nbsp;&nbsp; imgFunctionname(其中img为image缩写)。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 现给出三种库的命名前缀：&nbsp;&nbsp;&nbsp;&nbsp; <br><span style="COLOR: #008000">&nbsp;&nbsp;&nbsp; ①、&nbsp;&nbsp;&nbsp;&nbsp; 对通用函数库，采用cm为前缀。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ②、&nbsp;&nbsp;&nbsp;&nbsp; 对三维函数库，采用vr为前缀。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ③、&nbsp;&nbsp;&nbsp;&nbsp; 对图象函数库，采用img为前缀。</span>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 对宏定义，结果代码用同样的前缀。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;<strong>&nbsp; 5、文件名(包括动态库、组件、控件、工程文件等)的命名规范：</strong>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 文件名的命名要求表达出文件的内容，要求文件名的长度不得少于5个字母，严禁使用象file1,myfile之类的文件名。&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p><span style="FONT-SIZE: 14pt"><strong>三、注释规范：</strong></span>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;<strong> 1、函数头的注释</strong>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 对于函数，应该从&#8220;功能&#8221;，&#8220;参数&#8221;，&#8220;返回值&#8221;、&#8220;主要思路&#8221;、&#8220;调用方法&#8221;、&#8220;日期&#8221;六个方面用如下格式注释：&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //程序说明开始&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //================================================================//&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 功能：&nbsp;&nbsp;&nbsp;&nbsp; 从一个String&nbsp;&nbsp;&nbsp;&nbsp; 中删除另一个String。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 参数：&nbsp;&nbsp;&nbsp;&nbsp; strByDelete,strToDelete&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; （入口）&nbsp;&nbsp;&nbsp;&nbsp; strByDelete:&nbsp;&nbsp;&nbsp;&nbsp; 被删除的字符串（原来的字符串）&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; （出口）&nbsp;&nbsp;&nbsp;&nbsp; strToDelete:&nbsp;&nbsp;&nbsp;&nbsp; 要从上个字符串中删除的字符串。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 返回：&nbsp;&nbsp;&nbsp;&nbsp; 找到并删除返回1，否则返回0。（对返回值有错误编码的要//&nbsp;&nbsp;&nbsp;&nbsp; 求列出错误编码）。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 主要思路：本算法主要采用循环比较的方法来从strByDelete中找到&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 与strToDelete相匹配的字符串，对多匹配strByDelete&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 中有多个strToDelete子串）的情况没有处理。请参阅：&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 书名......&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 调用方法：......&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 日期：起始日期，如：2000/8/21.9:40--2000/8/23.21:45&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //================================================================//&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 函数名(&#8230;&#8230;)&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //程序说明结束&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ①、&nbsp;&nbsp;&nbsp;&nbsp; 对于某些函数，其部分参数为传入值，而部分参数为传出值，所以对参数要详细说明该参数是入口参数，还是出口参数，对于某些意义不明确的参数还要做详细说明（例如：以角度作为参数时，要说明该角度参数是以弧度（PI）,还是以度为单位）,对既是入口又是出口的变量应该在入口和出口处同时标明。等等。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ②、&nbsp;&nbsp;&nbsp;&nbsp; 函数的注释应该放置在函数的头文件中，在实现文件中的该函数的实现部分应该同时放置该注释。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ③、&nbsp;&nbsp;&nbsp;&nbsp; 在注释中应该详细说明函数的主要实现思路、特别要注明自己的一些想法，如果有必要则应该写明对想法产生的来由。对一些模仿的函数应该注释上函数的出处。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ④、&nbsp;&nbsp;&nbsp;&nbsp; 在注释中详细注明函数的适当调用方法，对于返回值的处理方法等。在注释中要强调调用时的危险方面，可能出错的地方。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ⑤、&nbsp;&nbsp;&nbsp;&nbsp; 对日期的注释要求记录从开始写函数到结束函数的测试之间的日期。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ⑥、&nbsp;&nbsp;&nbsp;&nbsp; 对函数注释开始到函数命名之间应该有一组用来标识的特殊字符串。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 如果算法比较复杂，或算法中的变量定义与位置有关，则要求对变量的定义进行图解。对难以理解的算法能图解尽量图解。&nbsp;&nbsp;&nbsp;&nbsp; <br><strong>&nbsp;&nbsp;&nbsp; 2、变量的注释：</strong>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 对于变量的注释紧跟在变量的后面说明变量的作用。原则上对于每个变量应该注释，但对于意义非常明显的变量，如：i,j等循环变量可以不注释。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 例如：&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #008000"> long&nbsp;&nbsp;&nbsp;&nbsp; lLineCount</span>&nbsp;&nbsp;&nbsp;&nbsp; //线的根数。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;<strong>&nbsp;&nbsp; 　3、文件的注释：</strong>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 文件应该在文件开头加入以下注释：&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /////////////////////////////////////////////////////////////////////&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 工程:&nbsp;&nbsp;&nbsp;&nbsp; 文件所在的项目名。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 作者：**，修改者：**&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 描述:说明文件的功能。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 主要函数：&#8230;&#8230;&#8230;&#8230;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 版本:&nbsp;&nbsp;&nbsp;&nbsp; 说明文件的版本，完成日期。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 修改:&nbsp;&nbsp;&nbsp;&nbsp; 说明对文件的修改内容、修改原因以及修改日期。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 参考文献：&nbsp;&nbsp;&nbsp;&nbsp; ......&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /////////////////////////////////////////////////////////////////////&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 为了头文件被重复包含要求对头文件进行定义如下:&nbsp;&nbsp;&nbsp;&nbsp; <br><span style="COLOR: #008000">&nbsp;&nbsp;&nbsp; #ifndef&nbsp;&nbsp;&nbsp;&nbsp; __FILENAME_H__&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; #define&nbsp;&nbsp;&nbsp;&nbsp; __FILENAME_H__</span>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 其中FILENAME为头文件的名字。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 　<strong>　　4、其他注释：</strong>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 在函数内我们不需要注释每一行语句。但必须在各功能模块的每一主要部分之前添加块注释，注释每一组语句，在循环、流程的各分支等，尽可能多加以注释。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 其中的循环、条件、选择等位置必须注释。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 对于前后顺序不能颠倒的情况，建议在注释中增加序号。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 例如：&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 在其他顺序执行的程序中，每隔3—5行语句，必须加一个注释，注明这一段语句所组成的小模块的作用。对于自己的一些比较独特的思想要求在注释中标明。&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p><strong><span style="FONT-SIZE: 14pt">四、程序健壮性：</span>&nbsp;&nbsp;</strong>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;<strong> 1、函数的返回值规范：</strong>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 对于函数的返回位置，尽量保持单一性，即一个函数尽量做到只有一个返回位置。(单入口单出口)。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 要求大家统一函数的返回值，所有的函数的返回值都将以编码的方式返回。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 例如编码定义如下：&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;<span style="COLOR: #008000"> #define&nbsp;&nbsp;&nbsp;&nbsp; CM_POINT_IS_NULL&nbsp;&nbsp;&nbsp;&nbsp; CMMAKEHR(0X200)&nbsp;&nbsp;&nbsp;&nbsp; <br></span>&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 建议函数实现如下：&nbsp;&nbsp;&nbsp;&nbsp; <br><span style="COLOR: #008000">&nbsp;&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp;&nbsp; 函数名(参数,&#8230;&#8230;)&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp;&nbsp; lResult;&nbsp;&nbsp;&nbsp;&nbsp;<span> //保持错误号&nbsp;&nbsp;&nbsp;&nbsp; <br></span>&nbsp;&nbsp;&nbsp; lResult=CM_OK;</span>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //如果参数有错误则返回错误号&nbsp;&nbsp;&nbsp;&nbsp; <br><span style="COLOR: #008000">&nbsp;&nbsp;&nbsp; if(参数==NULL)&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; lResult=CM_POINT_IS_NULL;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; goto&nbsp;&nbsp;&nbsp;&nbsp; END;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &#8230;&#8230;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; END:&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp;&nbsp;&nbsp; lResult;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }</span>&nbsp;&nbsp;&nbsp;&nbsp; <br><strong>&nbsp;&nbsp;&nbsp; 2、关于goto的应用：</strong>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 对goto语句的应用，我们要求尽量少用goto语句。对一定要用的地方要求只能向后转移。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 3、资源变量的处理（资源变量是指消耗系统资源的变量）：&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 对资源变量一定赋初值。分配的资源在用完后必须马上释放，并重新赋值。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 4、对复杂的条件判断，为了程序的可读性，应该尽量使用括号。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 例：<span style="COLOR: #008000">if(((szFileName!=NULL)&amp;&amp;(lCount&gt;=0)))||(bIsRead==TRUE))&nbsp;&nbsp;&nbsp;&nbsp; <br></span>&nbsp; <br><strong><span style="FONT-SIZE: 14pt">五、可移植性：</span></strong>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 1、高质量的代码要求能够跨平台，所以我们的代码应该考虑到对不同的平台的支持，特别是对windows98和windowsnt的支持。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 2、由于C语言的移植性比较好，所以对算法函数要求用C代码，不能用C++代码。&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 3、对不同的硬件与软件的函数要做不同的处理 <br>匈牙利命名法 <br><br><br>MFC、句柄、控件及结构的命名规范 &nbsp; Windows类型 &nbsp; 样本变量 &nbsp; MFC类 &nbsp; 样本变量 &nbsp; <br>HWND &nbsp; hWnd； &nbsp; CWnd* &nbsp; pWnd； &nbsp; <br>HDLG &nbsp; hDlg； &nbsp; CDialog* &nbsp; pDlg； &nbsp; <br>HDC &nbsp; hDC； &nbsp; CDC* &nbsp; pDC； &nbsp; <br>HGDIOBJ &nbsp; hGdiObj； &nbsp; CGdiObject* &nbsp; pGdiObj； &nbsp; <br>HPEN &nbsp; hPen； &nbsp; CPen* &nbsp; pPen； &nbsp; <br>HBRUSH &nbsp; hBrush； &nbsp; CBrush* &nbsp; pBrush； &nbsp; <br>HFONT &nbsp; &nbsp; hFont； &nbsp; &nbsp; CFont* &nbsp; pFont； &nbsp; <br>HBITMAP &nbsp; &nbsp; hBitmap； &nbsp; CBitmap* &nbsp; pBitmap； &nbsp; <br>HPALETTE &nbsp; &nbsp; hPaltte； &nbsp; CPalette* &nbsp; pPalette； &nbsp; <br>HRGN &nbsp; &nbsp; hRgn； &nbsp; CRgn* &nbsp; pRgn； &nbsp; <br>HMENU &nbsp; &nbsp; hMenu； &nbsp; CMenu* &nbsp; pMenu； &nbsp; <br>HWND &nbsp; &nbsp; hCtl； &nbsp; CState* &nbsp; &nbsp; pState； &nbsp; <br>HWND &nbsp; &nbsp; hCtl； &nbsp; CButton* &nbsp; pButton； &nbsp; <br>HWND &nbsp; &nbsp; hCtl； &nbsp; CEdit* &nbsp; pEdit； &nbsp; <br>HWND &nbsp; &nbsp; hCtl； &nbsp; CListBox* &nbsp; pListBox； &nbsp; <br>HWND &nbsp; &nbsp; hCtl； &nbsp; CComboBox* &nbsp; pComboBox； &nbsp; <br>HWND &nbsp; &nbsp; hCtl； &nbsp; CScrollBar* &nbsp; pScrollBar； &nbsp; <br>HSZ &nbsp; &nbsp; hszStr； &nbsp; CString &nbsp; &nbsp; pStr； &nbsp; <br>POINT &nbsp; &nbsp; pt； &nbsp; CPoint &nbsp; &nbsp; pt； &nbsp; <br>SIZE &nbsp; &nbsp; size； &nbsp; CSize &nbsp; &nbsp; size； &nbsp; <br>RECT &nbsp; &nbsp; rect； &nbsp; CRect &nbsp; &nbsp; rect； &nbsp; <br><br><br>一般前缀命名规范 &nbsp; 前缀 &nbsp; 类型 &nbsp; 实例 &nbsp; <br>C &nbsp; 类或结构 &nbsp; CDocument，CPrintInfo &nbsp; <br>m_ &nbsp; 成员变量 &nbsp; m_pDoc，m_nCustomers &nbsp; <br><br><br>变量命名规范 &nbsp; 前缀 &nbsp; 类型 &nbsp; 描述 &nbsp; 实例 &nbsp; <br>ch &nbsp; char &nbsp; 8位字符 &nbsp; chGrade &nbsp; <br>ch &nbsp; &nbsp; TCHAR &nbsp; 如果_UNICODE定义，则为16位字符 &nbsp; chName &nbsp; <br>b &nbsp; BOOL &nbsp; 布尔值 &nbsp; bEnable &nbsp; <br>n &nbsp; &nbsp; int &nbsp; 整型（其大小依赖于操作系统） &nbsp; nLength &nbsp; <br>n &nbsp; &nbsp; UINT &nbsp; &nbsp; 无符号值（其大小依赖于操作系统） &nbsp; nHeight &nbsp; <br>w &nbsp; &nbsp; WORD &nbsp; &nbsp; 16位无符号值 &nbsp; wPos &nbsp; <br>l &nbsp; &nbsp; LONG &nbsp; &nbsp; 32位有符号整型 &nbsp; lOffset &nbsp; <br>dw &nbsp; &nbsp; DWORD &nbsp; &nbsp; 32位无符号整型 &nbsp; &nbsp; dwRange &nbsp; <br>p &nbsp; &nbsp; * &nbsp; &nbsp; 指针 &nbsp; pDoc &nbsp; <br>lp &nbsp; &nbsp; FAR* &nbsp; &nbsp; 远指针 &nbsp; &nbsp; lpszName &nbsp; <br>lpsz &nbsp; &nbsp; LPSTR &nbsp; &nbsp; 32位字符串指针 &nbsp; lpszName &nbsp; <br>lpsz &nbsp; &nbsp; LPCSTR &nbsp; &nbsp; 32位常量字符串指针 &nbsp; lpszName &nbsp; <br>lpsz &nbsp; &nbsp; LPCTSTR &nbsp; &nbsp; 如果_UNICODE定义，则为32位常量字符串指针 &nbsp; lpszName &nbsp; <br>h &nbsp; &nbsp; handle &nbsp; &nbsp; Windows对象句柄 &nbsp; hWnd &nbsp; <br>lpfn &nbsp; &nbsp; callback &nbsp; 指向CALLBACK函数的远指针 &nbsp; &nbsp; &nbsp; <br><br><br>应用程序符号命名规范 &nbsp; 前缀 &nbsp; 符号类型 &nbsp; 实例 &nbsp; 范围 &nbsp; <br>IDR_ &nbsp; &nbsp; 不同类型的多个资源共享标识 &nbsp; IDR_MAIINFRAME &nbsp; 1～0x6FFF &nbsp; <br>IDD_ &nbsp; 对话框资源 &nbsp; IDD_SPELL_CHECK &nbsp; &nbsp; 1～0x6FFF &nbsp; <br>HIDD_ &nbsp; 对话框资源的Help上下文 &nbsp; HIDD_SPELL_CHECK &nbsp; &nbsp; 0x20001～0x26FF &nbsp; <br>IDB_ &nbsp; &nbsp; 位图资源 &nbsp; IDB_COMPANY_LOGO &nbsp; &nbsp; 1～0x6FFF &nbsp; <br>IDC_ &nbsp; 光标资源 &nbsp; IDC_PENCIL &nbsp; &nbsp; 1～0x6FFF &nbsp; <br>IDI_ &nbsp; 图标资源 &nbsp; IDI_NOTEPAD &nbsp; &nbsp; 1～0x6FFF &nbsp; <br>ID_ &nbsp; 来自菜单项或工具栏的命令 &nbsp; ID_TOOLS_SPELLING &nbsp; &nbsp; 0x8000～0xDFFF &nbsp; <br>HID_ &nbsp; 命令Help上下文 &nbsp; HID_TOOLS_SPELLING &nbsp; &nbsp; 0x18000～0x1DFFF &nbsp; <br>IDP_ &nbsp; 消息框提示 &nbsp; IDP_INVALID_PARTNO &nbsp; &nbsp; 8～0xDEEF &nbsp; <br>HIDP_ &nbsp; 消息框Help上下文 &nbsp; HIDP_INVALID_PARTNO &nbsp; &nbsp; 0x30008～0x3DEFF &nbsp; <br>IDS_ &nbsp; 串资源 &nbsp; IDS_COPYRIGHT &nbsp; &nbsp; 1～0x7EEF &nbsp; <br>IDC_ &nbsp; 对话框内的控件 &nbsp; IDC_RECALC &nbsp; &nbsp; 8～0xDEEF &nbsp; <br><br><br>Microsoft &nbsp; MFC宏命名规范 &nbsp; 名称 &nbsp; 类型 &nbsp; <br>_AFXDLL &nbsp; 唯一的动态连接库（Dynamic &nbsp; Link &nbsp; Library，DLL）版本 &nbsp; <br>_ALPHA &nbsp; 仅编译DEC &nbsp; Alpha处理器 &nbsp; <br>_DEBUG &nbsp; 包括诊断的调试版本 &nbsp; <br>_MBCS &nbsp; 编译多字节字符集 &nbsp; <br>_UNICODE &nbsp; 在一个应用程序中打开Unicode &nbsp; <br>AFXAPI &nbsp; &nbsp; MFC提供的函数 &nbsp; <br>CALLBACK &nbsp; 通过指针回调的函数 &nbsp; &nbsp; <br><br><br>库标识符命名法 &nbsp; 标识符 &nbsp; 值和含义 &nbsp; <br>u &nbsp; &nbsp; ANSI（N）或Unicode（U） &nbsp; <br>d &nbsp; &nbsp; 调试或发行：D &nbsp; = &nbsp; 调试；忽略标识符为发行。 &nbsp; <br><br><br>静态库版本命名规范 &nbsp; 库 &nbsp; 描述 &nbsp; <br>NAFXCWD.LIB &nbsp; 调试版本：MFC静态连接库 &nbsp; <br>NAFXCW.LIB &nbsp; 发行版本：MFC静态连接库 &nbsp; <br>UAFXCWD.LIB &nbsp; 调试版本：具有Unicode支持的MFC静态连接库 <br>&nbsp; <br>UAFXCW.LIB &nbsp; 发行版本：具有Unicode支持的MFC静态连接库 &nbsp; <br><br><br>动态连接库命名规范 &nbsp; 名称 &nbsp; 类型 &nbsp; <br>_AFXDLL &nbsp; 唯一的动态连接库（DLL）版本 <br>&nbsp; <br>WINAPI &nbsp; &nbsp; Windows所提供的函数 &nbsp; <br><br><br>Windows.h中新的命名规范 &nbsp; 类型 &nbsp; 定义描述 &nbsp; <br>WINAPI &nbsp; 使用在API声明中的FAR &nbsp; PASCAL位置，如果正在编写一个具有导出API人口点的DLL，则可以在自己的API中使用该类型 &nbsp; <br>CALLBACK &nbsp; 使用在应用程序回叫例程，如窗口和对话框过程中的FAR &nbsp; PASCAL的位置 &nbsp; <br>LPCSTR &nbsp; 与LPSTR相同，只是LPCSTR用于只读串指针，其定义类似（const &nbsp; char &nbsp; FAR*） &nbsp; <br>UINT &nbsp; 可移植的无符号整型类型，其大小由主机环境决定（对于Windows &nbsp; NT和Windows &nbsp; 9x为32位）；它是unsigned &nbsp; int的同义词 &nbsp; <br>LRESULT &nbsp; 窗口程序返回值的类型 &nbsp; <br>LPARAM &nbsp; 声明lParam所使用的类型，lParam是窗口程序的第四个参数 &nbsp; <br>WPARAM &nbsp; 声明wParam所使用的类型，wParam是窗口程序的第三个参数 &nbsp; <br>LPVOID &nbsp; 一般指针类型，与（void &nbsp; *）相同，可以用来代替LPSTR&nbsp;&nbsp;&nbsp;&nbsp;</p>
<img src ="http://www.cppblog.com/tdweng/aggbug/138643.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2011-01-17 10:51 <a href="http://www.cppblog.com/tdweng/articles/138643.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>#ifdef __cplusplus 学习 </title><link>http://www.cppblog.com/tdweng/articles/137094.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Tue, 21 Dec 2010 01:48:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/137094.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/137094.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/137094.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/137094.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/137094.html</trackback:ping><description><![CDATA[<div class=postText><span class=Apple-style-span style="WORD-SPACING: 0px; FONT: medium Simsun; TEXT-TRANSFORM: none; COLOR: #000000; TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2"><span class=Apple-style-span style="FONT-SIZE: 14px; COLOR: #333333; FONT-FAMILY: 宋体,Arial,Helvetica,sans-serif">
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">时常在cpp的代码之中看到这样的代码:</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">#ifdef __cplusplus</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">extern "C" {</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">#endif</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">//一段代码</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">#ifdef __cplusplus</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">}</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">#endif</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">　　这样的代码到底是什么意思呢？首先，__cplusplus是cpp中的自定义宏，那么定义了这个宏的话表示这是一段cpp的代码，也就是说，上面的代码的含义是:<span style="BACKGROUND-COLOR: #ccffcc">如果这是一段cpp的代码，那么加入extern "C"{和}处理其中的代码</span>。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">　　要明白为何使用extern "C"，还得从cpp中对函数的重载处理开始说起。在c++中，为了支持重载机制，在编译生成的汇编码中，要对函数的名字进行一些处理，加入比如函数的返回类型等等.而在C中，只是简单的函数名字而已，不会加入其他的信息.也就是说:C++和C对产生的函数名字的处理是不一样的.</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">　　比如下面的一段简单的函数，我们看看加入和不加入extern "C"产生的汇编代码都有哪些变化:</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">int f(void)</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">{</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">return 1;</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">}</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">　　在加入extern "C"的时候产生的汇编代码是:</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">.file "test.cxx"</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">.text</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">.align 2</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">.globl _f</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">.def _f; .scl 2; .type 32; .endef</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">_f:</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">pushl %ebp</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">movl %esp， %ebp</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">movl $1， %eax</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">popl %ebp</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">ret</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">　　但是不加入了extern "C"之后</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">.file "test.cxx"</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">.text</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">.align 2</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">.globl __Z1fv</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">.def __Z1fv; .scl 2; .type 32; .endef</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">__Z1fv:</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">pushl %ebp</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">movl %esp， %ebp</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">movl $1， %eax</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">popl %ebp</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">ret</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">　　两段汇编代码同样都是使用gcc -S命令产生的，所有的地方都是一样的，唯独是产生的函数名，一个是_f，一个是__Z1fv。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">　　明白了加入与不加入extern "C"之后对函数名称产生的影响，我们继续我们的讨论:为什么需要使用extern "C"呢？C++之父在设计C++之时，考虑到当时已经存在了大量的C代码，为了支持原来的C代码和已经写好C库，需要在C++中尽可能的支持C，而extern "C"就是其中的一个策略。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">　　试想这样的情况:一个库文件已经用C写好了而且运行得很良好，这个时候我们需要使用这个库文件，但是我们需要使用C++来写这个新的代码。如果这个代码使用的是C++的方式链接这个C库文件的话，那么就会出现链接错误.我们来看一段代码:首先，我们使用C的处理方式来写一个函数，也就是说假设这个函数当时是用C写成的:</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">//f1.c</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">extern "C"</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">{</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">void f1()</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">{</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">return;</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">}</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">}</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">　　编译命令是:gcc -c f1.c -o f1.o 产生了一个叫f1.o的库文件。再写一段代码调用这个f1函数:</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">// test.cxx</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">//这个extern表示f1函数在别的地方定义，这样可以通过</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">//编译，但是链接的时候还是需要</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">//链接上原来的库文件.</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">extern void f1();</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">int main()</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">{</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">f1();</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">return 0;</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">}</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">　　通过gcc -c test.cxx -o test.o 产生一个叫test.o的文件。然后，我们使用gcc test.o f1.o来链接两个文件，可是出错了，错误的提示是:</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">test.o(.text + 0x1f):test.cxx: undefine reference to 'f1()'</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">　　也就是说，在编译test.cxx的时候编译器是使用C++的方式来处理f1()函数的，但是实际上链接的库文件却是用C的方式来处理函数的，所以就会出现链接过不去的错误:因为链接器找不到函数。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">　　因此，<span style="COLOR: #ff0000">为了在C++代码中调用用C写成的库文件，就需要用extern "C"来告诉编译器:这是一个用C写成的库文件，请用C的方式来链接它们。</span></p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">　　比如，现在我们有了一个C库文件，它的头文件是f.h，产生的lib文件是f.lib，那么我们如果要在C++中使用这个库文件，我们需要这样写:</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">extern "C"</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">{</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">#include "f.h"</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">}</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">　　回到上面的问题，如果要改正链接错误，我们需要这样子改写test.cxx:</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">extern "C"</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">{</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">extern void f1();</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">}</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">int main()</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">{</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">f1();</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">return 0;</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">}</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">　　重新编译并且链接就可以过去了.</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">总结</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">C和C++对函数的处理方式是不同的.<span style="BACKGROUND-COLOR: #ccffcc">extern "C"是使C++能够调用C写作的库文件的一个手段，如果要对编译器提示使用C的方式来处理函数的话，那么就要使用extern "C"来说明</span>。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">1.引言</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">C++语言的创建初衷是&#8220;a better C&#8221;，但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同。作为一种欲与C兼容的语言，C++保留了一部分过程 式语言的特点（被世人称为&#8220;不彻底地面向对象&#8221;），因而它可以定义不属于任何类的全局变量和函数。但是，C++毕竟是一种面向对象的程序设计语言，为了支持函数的重载，C++对全局函数的处理方式与C有明显的不同。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">2.从标准头文件说起</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">某企业曾经给出如下的一道面试题：</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">面试题</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">为什么标准头文件都有类似以下的结构？</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp; #ifndef __INCvxWorksh</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp; #define __INCvxWorksh</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp; #ifdef __cplusplus</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp; extern "C" {</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp; #endif</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp; /*...*/</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp; #ifdef __cplusplus</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp; }</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp; #endif</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp; #endif /* __INCvxWorksh */</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">分析</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">显然，头文件中的编译宏&#8220;#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif&#8221; 的作用是<span style="COLOR: #ff0000">防止该头文件被重复引用</span>。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">那么</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp; #ifdef __cplusplus</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp; extern "C" {</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp; #endif</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp; #ifdef __cplusplus</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp; }</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp; #endif</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">的作用又是什么呢？我们将在下文一一道来。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">3.深层揭密extern "C"</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">extern "C" 包含双重含义，从字面上即可得到：首先，被它修饰的目标是&#8220;extern&#8221;的；其次，被它修饰的目标是&#8220;C&#8221;的。让我们来详细解读这两重含义。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">（1）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #ff0000"><span class=Apple-converted-space>&nbsp;</span>被extern "C"限定的函数或变量是extern类型的</span>；</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">extern是C/C++语言中表明函数和全局变量作用范围（可见性）的关键字，该关键字告诉编译器，其声明的函数和变量可以在本模块或其它模块中使用。记住，下列语句：</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">extern int a;</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">仅仅是一个变量的声明，其并不是在定义变量a，并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被定义一次，否则会出现连接错误。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">通常，在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如，如果模块B欲引用该模块A中定义的全局变量和 函数时只需包含模块A的头文件即可。这样，模块B中调用模块A中的函数时，在编译阶段，模块B虽然找不到该函数，但是并不会报错；它会在连接阶段中从模块 A编译生成的目标代码中找到此函数。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">与extern对应的关键字是static，被它修饰的全局变量和函数只能在本模块中使用。因此，一个函数或变量只可能被本模块使用时，其不可能被extern &#8220;C&#8221;修饰。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">（2）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: #ff0000">被extern "C"修饰的变量和函数是按照C语言方式编译和连接的</span>；</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">未加extern &#8220;C&#8221;声明时的编译方式</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">首先看看C++中对类似C的函数是怎样编译的。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">作为一种面向对象的语言，C++支持函数重载，而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如，假设某个函数的原型为：</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">void foo( int x, int y );</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">该函数被<span style="COLOR: #008000">C</span>编译器编译后在符号库中的名字为<span style="COLOR: #008000">_foo</span>，而<span style="COLOR: #008000">C++</span>编译器则会产生像_<span style="COLOR: #008000">foo_int_int</span>之类的名字（不同的编译器可能生成的名字不同，但是都采用了相同的机制，生成的新名字称为&#8220;mangled name&#8221;）。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息，C++就是靠这种机制来实现函数重载的。例如，在C++中，函 数void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的，后者为_foo_int_float。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">同样地，C++中的变量除支持局部变量外，还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名，我们以"."来区分。而本 质上，编译器在进行编译时，与函数的处理相似，也为类中的变量取了一个独一无二的名字，这个名字与用户程序中同名的全局变量名字不同。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em"><span style="COLOR: #3366ff">未加extern "C"声明时的连接方式：</span></p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">假设在C++中，模块A的头文件如下：</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">// 模块A头文件　moduleA.h</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">#ifndef MODULE_A_H</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #define MODULE_A_H</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp;&nbsp; int foo( int x, int y );</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">#endif</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">在模块B中引用该函数：</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">// 模块B实现文件　moduleB.cpp</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">＃i nclude "moduleA.h"</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">foo(2,3);</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">实际上，在连接阶段，连接器会从模块A生成的目标文件moduleA.obj中寻找_foo_int_int这样的符号！</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em"><span style="COLOR: #3366ff">加extern "C"声明后的编译和连接方式：</span></p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">加extern "C"声明后，模块A的头文件变为：</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">// 模块A头文件　moduleA.h</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">#ifndef MODULE_A_H</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #define MODULE_A_H</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp;&nbsp; extern "C" int foo( int x, int y );</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">#endif</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">在模块B的实现文件中仍然调用foo( 2,3 )，其结果是：</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">（1）模块A编译生成foo的目标代码时，没有对其名字进行特殊处理，采用了C语言的方式；</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">（2）连接器在为模块B的目标代码寻找foo(2,3)调用时，寻找的是未经修改的符号名_foo。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">如果在模块A中函数声明了foo为extern "C"类型，而模块B中包含的是extern int foo( int x, int y ) ，则模块B找不到模块A中的函数；反之亦然。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">所以，可以用一句话概括extern &#8220;C&#8221;这个声明的真实目的（任何语言中的任何语法特性的诞生都不是随意而为的，来源于真实世界的需求驱动。我们在思考问题时，不能只停留在这个语言是怎么做的，还要问一问它为什么要这么做，动机是什么，这样我们可以更深入地理解许多问题）：</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">实现C++与C及其它语言的混合编程。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">明白了C++中extern "C"的设立动机，我们下面来具体分析extern "C"通常的使用技巧。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">4.extern "C"的惯用法</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">（1）在C++中引用C语言中的函数和变量，在包含C语言头文件（假设为cExample.h）时，需进行下列处理：</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">extern "C"</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">{</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">＃i nclude "cExample.h"</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">}</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">而在C语言的头文件中，对其外部函数只能指定为extern类型，C语言中不支持extern "C"声明，在.c文件中包含了extern "C"时会出现编译语法错误。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">笔者编写的C++引用C函数例子工程中包含的三个文件的源代码如下：</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">/* c语言头文件：cExample.h */</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">#ifndef C_EXAMPLE_H</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">#define C_EXAMPLE_H</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">extern int add(int x,int y);</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">#endif</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">/* c语言实现文件：cExample.c */</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">＃i nclude "cExample.h"</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">int add( int x, int y )</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">{</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return x + y;</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">}</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">// c++实现文件，调用add：cppFile.cpp</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">extern "C"</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">{</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">＃i nclude "cExample.h"</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">}</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">int main(int argc, char* argv[])</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">{</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; add(2,3);</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">}</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">如果C++调用一个C语言编写的.DLL时，当包括.DLL的头文件或声明接口函数时，应加extern "C" {　}。</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">（2）在C中引用C++语言中的函数和变量时，C++的头文件需添加extern "C"，但是在C语言中不能直接引用声明了extern "C"的该头文件，应该仅将C文件中将C++中定义的extern "C"函数声明为extern类型。<span class=Apple-style-span style="WORD-SPACING: 0px; FONT: medium Simsun; TEXT-TRANSFORM: none; COLOR: #000000; TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2"><span class=Apple-style-span style="FONT-SIZE: 14px; COLOR: #333333; FONT-FAMILY: 宋体,Arial,Helvetica,sans-serif">
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">笔者编写的C引用C++函数例子工程中包含的三个文件的源代码如下：</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">//C++头文件 cppExample.h</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">#ifndef CPP_EXAMPLE_H</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">#define CPP_EXAMPLE_H</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">extern "C" int add( int x, int y );</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">#endif</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">//C++实现文件 cppExample.cpp</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">＃i nclude "cppExample.h"</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">int add( int x, int y )</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">{</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return x + y;</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">}</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">/* C实现文件 cFile.c</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">/* 这样会编译出错：＃i nclude "cExample.h" */</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">extern int add( int x, int y );</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">int main( int argc, char* argv[] )</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">{</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; add( 2, 3 );&nbsp;&nbsp;&nbsp;</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;</p>
<p style="MARGIN-TOP: 10px; FONT-SIZE: 14px; MARGIN-BOTTOM: 10px; TEXT-INDENT: 2em; LINE-HEIGHT: 1.8em">}</p>
</span></span>
<p>&#160;</p>
</span></span></div>
<img src ="http://www.cppblog.com/tdweng/aggbug/137094.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-12-21 09:48 <a href="http://www.cppblog.com/tdweng/articles/137094.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】 深入分析C++中char * 和char []的区别</title><link>http://www.cppblog.com/tdweng/articles/136732.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Fri, 17 Dec 2010 05:59:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/136732.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/136732.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/136732.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/136732.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/136732.html</trackback:ping><description><![CDATA[<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS"><span class=Title><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">问题引入：<br></span></span>在实习过程中发现了一个以前一直默认的错误，同样char *c = "abc"和char c[]="abc",前者改变其内</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">容程序是会崩溃的，而后者完全正确。<br>程序演示：<br>测试环境Devc++<br>代码<br></span><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">运行结果<br>2293628 4199056 abc<br>2293624 2293624 abc<br>2293620 4199056 abc</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">#include &lt;iostream&gt;<br>using namespace std;</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">main()<br>{<br>char *c1 = "abc";<br>char c2[] = "abc";<br>char *c3 = ( char* )malloc(3);<br>c3 = "abc";<br>printf("%d %d %s\n",&amp;c1,c1,c1);<br>printf("%d %d %s\n",&amp;c2,c2,c2);<br>printf("%d %d %s\n",&amp;c3,c3,c3);<br>getchar();<br>}<br></span></p>
<br>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">参考资料：<br>首先要搞清楚编译程序占用的内存的分区形式：<br>一、预备知识-程序的内存分配<br>一个由c/C++编译的程序占用的内存分为以下几个部分<br>1、栈区（stack）-由编译器自动分配释放，存放函数的参数值，局部变量的值等。其操作方式类似于</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">数据结构中的栈。<br>2、堆区（heap）-一般由程序员分配释放，若程序员不释放，程序结束时可能由OS回收。注意它与数据</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">结构中的堆是两回事，分配方式倒是类似于链表，呵呵。<br>3、全局区（静态区）（static）-全局变量和静态变量的存储是放在一块的，初始化的全局变量和静态</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">变量在一块区域，未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">释放。<br>4、文字常量区-常量字符串就是放在这里的。程序结束后由系统释放。<br>5、程序代码区<br>这是一个前辈写的，非常详细<br><span class=Code><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">//main.cpp<br>int a=0; //全局初始化区<br>char *p1; //全局未初始化区<br>main()<br>{<br>int b;栈<br>char s[]="abc"; //栈<br>char *p2; //栈<br>char *p3="123456"; //123456\0在常量区，p3在栈上。<br>static int c=0； //全局（静态）初始化区<br>p1 = (char*)malloc(10);<br>p2 = (char*)malloc(20); //分配得来得10和20字节的区域就在堆区。<br>strcpy(p1,"123456"); //123456\0放在常量区，编译器可能会将它与p3所向"123456"优化成一个</span></span></span><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">地方。<br>}<br>二、堆和栈的理论知识<br>2.1申请方式<br>stack:<br>由系统自动分配。例如，声明在函数中一个局部变量int b;系统自动在栈中为b开辟空间<br>heap:<br>需要程序员自己申请，并指明大小，在c中malloc函数<br>如p1=(char*)malloc(10);<br>在C++中用new运算符<br>如p2=(char*)malloc(10);<br>但是注意p1、p2本身是在栈中的。<br>2.2<br>申请后系统的响应<br>栈：只要栈的剩余空间大于所申请空间，系统将为程序提供内存，否则将报异常提示栈溢出。<br>堆：首先应该知道操作系统有一个记录空闲内存地址的链表，当系统收到程序的申请时，<br>会遍历该链表，寻找第一个空间大于所申请空间的堆结点，然后将该结点从空闲结点链表中删除，并将</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">该结点的空间分配给程序，另外，对于大多数系统，会在这块内存空间中的首地址处记录本次分配的大</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">小，这样，代码中的delete语句才能正确的释放本内存空间。另外，由于找到的堆结点的大小不一定正</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">好等于申请的大小，系统会自动的将多余的那部分重新放入空闲链表中。<br>2.3申请大小的限制<br>栈：在Windows下,栈是向低地址扩展的数据结构，是一块连续的内存的区域。这句话的意思是栈顶的地</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">址和栈的最大容量是系统预先规定好的，在WINDOWS下，栈的大小是2M（也有的说是1M，总之是一个编译</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">时就确定的常数），如果申请的空间超过栈的剩余空间时，将提示overflow。因此，能从栈获得的空间</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">较小。<br>堆：堆是向高地址扩展的数据结构，是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">址的，自然是不连续的，而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">虚拟内存。由此可见，堆获得的空间比较灵活，也比较大。<br>2.4申请效率的比较：<br>栈:由系统自动分配，速度较快。但程序员是无法控制的。<br>堆:是由new分配的内存，一般速度比较慢，而且容易产生内存碎片,不过用起来最方便.<br>另外，在WINDOWS下，最好的方式是用Virtual Alloc分配内存，他不是在堆，也不是在栈,而是直接在进</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">程的地址空间中保留一块内存，虽然用起来最不方便。但是速度快，也最灵活。<br>2.5堆和栈中的存储内容<br>栈：在函数调用时，第一个进栈的是主函数中后的下一条指令（函数调用语句的下一条可执行语句）的</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">地址，然后是函数的各个参数，在大多数的C编译器中，参数是由右往左入栈的，然后是函数中的局部变</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">量。注意静态变量是不入栈的。<br>当本次函数调用结束后，局部变量先出栈，然后是参数，最后栈顶指针指向最开始存的地址，也就是主</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">函数中的下一条指令，程序由该点继续运行。<br>堆：一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容由程序员安排。<br>2.6存取效率的比较<br>char s1[]="aaaaaaaaaaaaaaa";<br>char *s2="bbbbbbbbbbbbbbbbb";<br>aaaaaaaaaaa是在运行时刻赋值的；<br>而bbbbbbbbbbb是在编译时就确定的；<br>但是，在以后的存取中，在栈上的数组比指针所指向的字符串(例如堆)快。<br>比如：<br><span class=Code>#include<br>voidmain()<br>{<br>char a=1;<br>char c[]="1234567890";<br>char *p="1234567890";<br>a = c[1];<br>a = p[1];<br>return;<br>}<br></span>对应的汇编代码<br>10:a=c[1];<br>004010678A4DF1movcl,byteptr[ebp-0Fh]<br>0040106A884DFCmovbyteptr[ebp-4],cl<br>11:a=p[1];<br>0040106D8B55ECmovedx,dwordptr[ebp-14h]<br>004010708A4201moval,byteptr[edx+1]<br>004010738845FCmovbyteptr[ebp-4],al<br>第一种在读取时直接就把字符串中的元素读到寄存器cl中，而第二种则要先把指针值读到edx中，在根据</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">edx读取字符，显然慢了。<br>2.7小结：<br>堆和栈的区别可以用如下的比喻来看出：<br>使用栈就象我们去饭馆里吃饭，只管点菜（发出申请）、付钱、和吃（使用），吃饱了就走，不必理会</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作，他的好处是快捷，但是自由度小。<br>使用堆就象是自己动手做喜欢吃的菜肴，比较麻烦，但是比较符合自己的口味，而且自由度大。</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">自我总结：<br>char *c1 = "abc";实际上先是在文字常量区分配了一块内存放"abc",然后在栈上分配一地址给c1并指向</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">这块地址，然后改变常量"abc"自然会崩溃</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">然而char c2[] = "abc",实际上abc分配内存的地方和上者并不一样，可以从<br>4199056<br>2293624 看出，完全是两块地方，推断4199056处于常量区，而2293624处于栈区</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">2293628<br>2293624<br>2293620 这段输出看出三个指针分配的区域为栈区，而且是从高地址到低地址</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">2293620 4199056 abc 看出编译器将c3优化指向常量区的"abc"</span></p>
<p><br><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">继续思考：<br>代码：<br></span><br><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">输出：<br>2293628 4199056 abc<br>2293624 2293624 abc<br>2293620 4012976 gbc<br>写成注释那样，后面改动就会崩溃<br>可见strcpy(c3,"abc");abc是另一块地方分配的，而且可以改变，和上面的参考文档说法有些不一定，</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">#include &lt;iostream&gt;<br>using namespace std;</span></p>
<p><span style="FONT-SIZE: 1em; COLOR: #003366; FONT-FAMILY: Comic Sans MS">main()<br>{<br>char *c1 = "abc";<br>char c2[] = "abc";<br>char *c3 = ( char* )malloc(3);<br>// *c3 = "abc" //error<br>strcpy(c3,"abc");<br>c3[0] = 'g';<br>printf("%d %d %s\n",&amp;c1,c1,c1);<br>printf("%d %d %s\n",&amp;c2,c2,c2);<br>printf("%d %d %s\n",&amp;c3,c3,c3);<br>getchar();<br>}</span></p>
<img src ="http://www.cppblog.com/tdweng/aggbug/136732.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-12-17 13:59 <a href="http://www.cppblog.com/tdweng/articles/136732.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EVC移植到VC总结</title><link>http://www.cppblog.com/tdweng/articles/134141.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Sat, 20 Nov 2010 02:42:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/134141.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/134141.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/134141.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/134141.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/134141.html</trackback:ping><description><![CDATA[1.Unicode问题,在Project Settings里,C/C++卡片,里面有Preprocessor definitions里面添,_UNICODE,UNICODE<br>2.link --&gt;output Entry-point symbol:wWinMainCRTStartup (支持双字节)<br>3.资源可以直接拷过来 用VC打开eVC的资源文件(rc),然后eVC的资源就会出现VC<br>在右侧,用鼠标拖到VC的资源中就可以. <br>4.其他就是一些细节问题了.可以用宏判断,是不是eVC的程序,如果是怎么处理,不是的话,就用VC的处理方式<br>#ifdef _WIN32_WCE<br>#endif<br>
<img src ="http://www.cppblog.com/tdweng/aggbug/134141.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-11-20 10:42 <a href="http://www.cppblog.com/tdweng/articles/134141.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基本数据类型：字符型（上） </title><link>http://www.cppblog.com/tdweng/articles/133122.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Tue, 09 Nov 2010 13:23:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/133122.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/133122.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/133122.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/133122.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/133122.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1. 字符型（char）简介&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字符型（char）用于储存字符（character），如英文字母或标点。严格来说，char 其实也是整数类型（integer type），因为 char 类型储存的实际上是整数，而不是字符。计算机使用特定的整数编码来表示特定的字符。美国普遍使用的编码是 ASCII（...&nbsp;&nbsp;<a href='http://www.cppblog.com/tdweng/articles/133122.html'>阅读全文</a><img src ="http://www.cppblog.com/tdweng/aggbug/133122.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-11-09 21:23 <a href="http://www.cppblog.com/tdweng/articles/133122.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>_cdecl,_fastcall和_stdcall的区别 </title><link>http://www.cppblog.com/tdweng/articles/130207.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Sun, 17 Oct 2010 11:37:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/130207.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/130207.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/130207.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/130207.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/130207.html</trackback:ping><description><![CDATA[&nbsp;
<p><strong><span>C++ Calling Convention</span></strong><strong><span>调用约定：</span></strong><span><br>__cdecl __fastcall</span><span>与</span><span> __stdcall</span><span>，三者都是调用约定</span><span>(Calling convention)</span><span>，它决定以下内容：</span></p>
<p><span>1)</span><span>函数参数的压栈顺序，</span><span>2)</span><span>由调用者还是被调用者把参数弹出栈，</span><span>3)</span><span>以及产生函数修饰名的方法。</span></p>
<p><span>1</span><span>、</span><span>__stdcall</span><span>调用约定：函数的参数自右向左通过栈传递，被调用的函数在返回前清理传送参数的内存栈，</span></p>
<p><span>2</span><span>、</span><span>_cdecl</span><span>是</span><span>C</span><span>和</span><span>C</span><span>＋＋程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码，所以产生的可执行文件大小会比调用</span><span>_stdcall</span><span>函数的大。函数采用从右到左的压栈方式。注意：对于可变参数的成员函数，始终使用</span><span>__cdecl</span><span>的转换方式。</span></p>
<p><span>3</span><span>、</span><span>__fastcall</span><span>调用约定：它是通过寄存器来传送参数的（实际上，它用</span><span>ECX</span><span>和</span><span>EDX</span><span>传送前两个双字（</span><span>DWORD</span><span>）或更小的参数，剩下的参数仍旧自右向左压栈传送，被调用的函数在返回前清理传送参数的内存栈）。</span></p>
<p><span>4</span><span>、</span><span>thiscall</span><span>仅仅应用于</span><span>"C++"</span><span>成员函数。</span><span>this</span><span>指针存放于</span><span>CX</span><span>寄存器，参数从右到左压。</span><span>thiscall</span><span>不是关键词，因此不能被程序员指定。</span></p>
<p><span>5</span><span>、</span><span>naked call</span><span>采用</span><span>1-4</span><span>的调用约定时，如果必要的话，进入函数时编译器会产生代码来保存</span><span>ESI</span><span>，</span><span>EDI</span><span>，</span><span>EBX</span><span>，</span><span>EBP</span><span>寄存器，退出函数时则产生代码恢复这些寄存器的内容。</span><span>naked call</span><span>不产生这样的代码。</span><span>naked call</span><span>不是类型修饰符，故必须和</span><span>_declspec</span><span>共同使用。</span></p>
<p><span>调用约定可以通过工程设置：</span><span>Setting...\C/C++ \Code Generation</span><span>项进行选择，缺省状态为</span><span>__cdecl</span><span>。</span></p>
<p><strong><span>名字修饰约定：</span></strong></p>
<p><span>1</span><span>、修饰名</span><span>(Decoration name)</span><span>：</span><span>"C"</span><span>或者</span><span>"C++"</span><span>函数在内部（编译和链接）通过修饰名识别</span><span><br>2</span><span>、</span><span>C</span><span>编译时函数名修饰约定规则：</span><span><br>__stdcall</span><span>调用约定在输出函数名前加上一个下划线前缀，后面加上一个</span><span>"@"</span><span>符号和其参数的字节数，格式为</span><span><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#95;&#102;&#117;&#110;&#99;&#116;&#105;&#111;&#110;&#110;&#97;&#109;&#101;&#64;&#110;&#117;&#109;&#98;&#101;&#114;"><span>_functionname@number</span></a></span><span>,</span><span>例如：</span><span>function(int a, int b)</span><span>，其修饰名为：</span><span><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#95;&#102;&#117;&#110;&#99;&#116;&#105;&#111;&#110;&#64;&#56;"><span>_function@8</span></a><br></span><span>__cdecl</span><span>调用约定仅在输出函数名前加上一个下划线前缀，格式为</span><span>_functionname</span><span>。</span><span><br>__fastcall</span><span>调用约定在输出函数名前加上一个</span><span>"@"</span><span>符号，后面也是一个</span><span>"@"</span><span>符号和其参数的字节数，格式为</span><span>@functionname@number</span><span>。</span></p>
<p><span>3</span><span>、</span><span>C++</span><span>编译时函数名修饰约定规则：</span><span><br>__stdcall</span><span>调用约定：</span><span><br>1)</span><span>、以</span><span>"?"</span><span>标识函数名的开始，后跟函数名；</span><span><br>2)</span><span>、函数名后面以</span><span>"@@YG"</span><span>标识参数表的开始，后跟参数表；</span><span><br>3)</span><span>、参数表以代号表示：</span><span><br>X--void </span><span>，</span><span><br>D--char</span><span>，</span><span><br>E--unsigned char</span><span>，</span><span><br>F--short</span><span>，</span><span><br>H--int</span><span>，</span><span><br>I--unsigned int</span><span>，</span><span><br>J--long</span><span>，</span><span><br>K--unsigned long</span><span>，</span><span><br>M--float</span><span>，</span><span><br>N--double</span><span>，</span><span><br>_N--bool</span><span>，</span><span><br>PA--</span><span>表示指针，后面的代号表明指针类型，如果相同类型的指针连续出现，以</span><span>"0"</span><span>代替，一个</span><span>"0"</span><span>代表一次重复；</span><span><br>4)</span><span>、参数表的第一项为该函数的返回值类型，其后依次为参数的数据类型</span><span>,</span><span>指针标识在其所指数据类型前；</span><span><br>5)</span><span>、参数表后以</span><span>"@Z"</span><span>标识整个名字的结束，如果该函数无参数，则以</span><span>"Z"</span><span>标识结束。</span><span><br></span><span>其格式为</span><span>"</span><span><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#102;&#117;&#110;&#99;&#116;&#105;&#111;&#110;&#110;&#97;&#109;&#101;&#64;&#64;&#89;&#71;&#42;&#42;&#42;&#42;&#42;&#64;&#90;"><span>?functionname@@YG*****@Z</span></a></span><span>"</span><span>或</span><span>"</span><span><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#102;&#117;&#110;&#99;&#116;&#105;&#111;&#110;&#110;&#97;&#109;&#101;&#64;&#64;&#89;&#71;&#42;&#88;&#90;"><span>?functionname@@YG*XZ</span></a></span><span>"</span><span>，例如</span><span><br>&nbsp;&nbsp;int Test1(char *var1,unsigned long)----"?Test1@@YGHPADK@Z"</span></p>
<p><span>&nbsp; void Test2()</span><span><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#45;&#45;&#45;&#45;&#45;&#37;&#67;&#50;&#37;&#65;&#49;&#37;&#67;&#50;&#37;&#66;&#48;&#63;&#84;&#101;&#115;&#116;&#50;&#64;&#64;&#89;&#71;&#88;&#88;&#90;"><span>-----&#8220;?Test2@@YGXXZ</span></a></span><span>&#8221;</span></p>
<p><span>__cdecl</span><span>调用约定：</span><span><br></span><span>规则同上面的</span><span>_stdcall</span><span>调用约定，只是参数表的开始标识由上面的</span><span>"@@YG"</span><span>变为</span><span>"@@YA"</span><span>。</span><span><br>__fastcall</span><span>调用约定：</span><span><br></span><span>规则同上面的</span><span>_stdcall</span><span>调用约定，只是参数表的开始标识由上面的</span><span>"@@YG"</span><span>变为</span><span>"@@YI"</span><span>。</span><span><br>VC++</span><span>对函数的省缺声明是</span><span>"__cedcl",</span><span>将只能被</span><span>C/C++</span><span>调用</span><span>.</span></p>
<p><span><br></span><strong><span>注意：</span></strong><span><br>1</span><span>、</span><span>_beginthread</span><span>需要</span><span>__cdecl</span><span>的线程函数地址，</span><span>_beginthreadex</span><span>和</span><span>CreateThread</span><span>需要</span><span>__stdcall</span><span>的线程函数地址。</span></p>
<p><span>2</span><span>、一般</span><span>WIN32</span><span>的函数都是</span><span>__stdcall</span><span>。而且在</span><span>Windef.h</span><span>中有如下的定义：</span><span><br>&nbsp;#define CALLBACK __stdcall<br>&nbsp;#define WINAPI</span><span>　</span><span> __stdcall</span></p>
<p><span>3</span><span>、</span><span>extern "C" _declspec(dllexport) int __cdecl Add(int a, int b);<br>&nbsp;&nbsp; typedef int (__cdecl*FunPointer)(int a, int b);<br>&nbsp;&nbsp; </span><span>修饰符的书写顺序如上。</span></p>
<p><span>4</span><span>、</span><span>extern "C"</span><span>的作用：如果</span><span>Add(int a, int b)</span><span>是在</span><span>c</span><span>语言编译器编译，而在</span><span>c++</span><span>文件使用，则需要在</span><span>c++</span><span>文件中声明：</span><span>extern "C" Add(int a, int b)</span><span>，因为</span><span>c</span><span>编译器和</span><span>c++</span><span>编译器对函数名的解释不一样（</span><span>c++</span><span>编译器解释函数名的时候要考虑函数参数，这样是了方便函数重载，而在</span><span>c</span><span>语言中不存在函数重载的问题），使用</span><span>extern "C"</span><span>，实质就是告诉</span><span>c++</span><span>编译器，该函数是</span><span>c</span><span>库里面的函数。如果不使用</span><span>extern "C"</span><span>则会出现链接错误。</span><span><br></span><span>一般象如下使用：</span><span><br>#ifdef _cplusplus<br>#define EXTERN_C extern "C"<br>#else<br>#define EXTERN_C extern<br>#endif</span></p>
<p><span>#ifdef _cplusplus<br>extern "C"{<br>#endif<br>&nbsp;EXTERN_C int func(int a, int b);<br>#ifdef _cplusplus<br>}<br>#endif</span></p>
<p><span>5</span><span>、</span><span>MFC</span><span>提供了一些宏，可以使用</span><span>AFX_EXT_CLASS</span><span>来代替</span><span>__declspec(DLLexport)</span><span>，并修饰类名，从而导出类，</span><span>AFX_API_EXPORT</span><span>来修饰函数，</span><span>AFX_DATA_EXPORT</span><span>来修饰变量</span><span><br>AFX_CLASS_IMPORT</span><span>：</span><span>__declspec(DLLexport)<br>AFX_API_IMPORT</span><span>：</span><span>__declspec(DLLexport)<br>AFX_DATA_IMPORT</span><span>：</span><span>__declspec(DLLexport)<br>AFX_CLASS_EXPORT</span><span>：</span><span>__declspec(DLLexport)<br>AFX_API_EXPORT</span><span>：</span><span>__declspec(DLLexport)<br>AFX_DATA_EXPORT</span><span>：</span><span>__declspec(DLLexport)<br>AFX_EXT_CLASS</span><span>：</span><span>#ifdef _AFXEXT<br>&nbsp;&nbsp;&nbsp;AFX_CLASS_EXPORT<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #else<br>&nbsp;&nbsp;&nbsp;AFX_CLASS_IMPORT</span></p>
<p><span>6</span><span>、</span><span>DLLMain</span><span>负责初始化</span><span>(Initialization)</span><span>和结束</span><span>(Termination)</span><span>工作，每当一个新的进程或者该进程的新的线程访问</span><span>DLL</span><span>时，或者访问</span><span>DLL</span><span>的每一个进程或者线程不再使用</span><span>DLL</span><span>或者结束时，都会调用</span><span>DLLMain</span><span>。但是，使用</span><span>TerminateProcess</span><span>或</span><span>TerminateThread</span><span>结束进程或者线程，不会调用</span><span>DLLMain</span><span>。</span></p>
<p><span>7</span><span>、一个</span><span>DLL</span><span>在内存中只有一个实例</span><span><br>DLL</span><span>程序和调用其输出函数的程序的关系：</span><span><br>1)</span><span>、</span><span>DLL</span><span>与进程、线程之间的关系</span><span><br>DLL</span><span>模块被映射到调用它的进程的虚拟地址空间。</span><span><br>DLL</span><span>使用的内存从调用进程的虚拟地址空间分配，只能被该进程的线程所访问。</span><span><br>DLL</span><span>的句柄可以被调用进程使用；调用进程的句柄可以被</span><span>DLL</span><span>使用。</span><span><br>DLLDLL</span><span>可以有自己的数据段，但没有自己的堆栈，使用调用进程的栈，与调用它的应用程序相同的堆栈模式。</span></p>
<p><span>2)</span><span>、关于共享数据段</span><span><br>DLL</span><span>定义的全局变量可以被调用进程访问；</span><span>DLL</span><span>可以访问调用进程的全局数据。使用同一</span><span>DLL</span><span>的每一个进程都有自己的</span><span>DLL</span><span>全局变量实例。如果多个线程并发访问同一变量，则需要使用同步机制；对一个</span><span>DLL</span><span>的变量，如果希望每个使用</span><span>DLL</span><span>的线程都有自己的值，则应该使用线程局部存储</span><span>(TLS</span><span>，</span><span>Thread Local Strorage)</span><span>。</span></p>
<p>&nbsp;<span>Visual</span>&nbsp;<span>C++</span>&nbsp;<span>Compiler</span>&nbsp;<span>Options</span><span>可以指定的<span>Calling</span></span>&nbsp;<span>Convention</span><span>有</span>&nbsp;<span>3</span><span>种：<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>/Gd</span>&nbsp;<span>/Gr</span>&nbsp;<span>/Gz<br><br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>这三个参数决定了：<span><br><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>1.</span><span>函数参数以何种顺序入栈，右到左还是左到右。<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>2.</span><span>在函数运行完后，是调用函数还是被调用函数清理入栈的参数。<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>3.</span><span>在编译时函数名字是如何转换的。<span><br><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>下面我们分别详细介绍：<span><br><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>1./Gd<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>这是编译器默认的转换模式，对一般函数使用</span>&nbsp;<span>C</span><span>的函数调用转换方式<span>__cdecl</span>，<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>但是对于<span>C++</span></span>&nbsp;<span>成员函数和前面修饰了<span>__stdcall</span></span>&nbsp;<span>__fastcall</span><span>的函数除外。<span><br><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>2./Gr<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>对于一般函数使用<span>__fastcall</span>函数调用转换方式，所有使用<span>__fastcall</span>的函数<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>必须要有函数原形。但对于<span>C++</span></span>&nbsp;<span>成员函数和前面修饰了<span>__cdecl</span></span>&nbsp;<span>__stdcall</span>&nbsp;<span>的函数除外。<span><br><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>3./Gz<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>对于所有</span>&nbsp;<span>C</span><span>函数使用<span>__stdcall</span>函数调用转换方式，但对于可变参数的</span>&nbsp;<span>C</span><span>函数以<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>及用<span>__cdecl</span></span>&nbsp;<span>__fastcall</span><span>修饰过的函数和<span>C++</span></span>&nbsp;<span>成员函数除外。所有用<span>__stdcall<br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>修饰的函数必须有函数原形。<span><br><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>事实上，对于<span>x86</span>系统，<span>C++</span></span>&nbsp;<span>成员函数的调用方式有点特别，将成员函数的<span>this<br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>指针放入<span>ECX</span>，所有函数参数从右向左入栈，被调用的成员函数负责清理入栈的<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>参数。对于可变参数的成员函数，始终使用<span>__cdecl</span>的转换方式。<span><br><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>下面该进入主题，分别讲一下这三种函数调用转换方式有什么区别：<span><br><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>1.__cdecl<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>这是编译器默认的函数调用转换方式，它可以处理可变参数的函数调用。参数<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>的入栈顺序是从右向左。在函数运行结束后，由调用函数负责清理入栈的参数。<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>在编译时，在每个函数前面加上下划线<span>(_)</span>，没有函数名大小写的转换。即<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>　　<span>_functionname<br><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>2.__fastcall<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>有一些函数调用的参数被放入<span>ECX</span>，<span>EDX</span>中，而其它参数从右向左入栈。被调用<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>函数在它将要返回时负责清理入栈的参数。在内嵌汇编语言的时候，需要注意<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>寄存器的使用，以免与编译器使用的产生冲突。函数名字的转换是：<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>　　<span>@functionname@number<br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>没有函数名大小写的转换，<span>number</span>表示函数参数的字节数。由于有一些参数不<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>需要入栈，所以这种转换方式会在一定程度上提高函数调用的速度。<span><br><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>3.__stdcall<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>　　函数参数从右向左入栈，被调用函数负责入栈参数的清理工作。函数名转换格<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>　　式如下：<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>　　　　</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>_functionname@number<br><br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>下面我们亲自写一个程序，看看各种不同的调用在编译后有什么区别，我们的被调<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>用函数如下：<span><br><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>int</span>&nbsp;<span>function(int</span>&nbsp;<span>a,</span>&nbsp;<span>int</span>&nbsp;<span>b)<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>{<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>return</span>&nbsp;<span>a</span>&nbsp;<span>+</span>&nbsp;<span>b;<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>}<br><br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>void</span>&nbsp;<span>main()<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>{<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>function(10,</span>&nbsp;<span>20);<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>}<br><br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>1.__cdecl<br><br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>_function<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>push</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>mov</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp,</span>&nbsp;<span>esp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>mov</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>eax,</span>&nbsp;<span>[ebp+8]</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>参数<span>1<br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>add</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>eax,</span>&nbsp;<span>[ebp+C]</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>加上参数<span>2<br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>pop</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>retn<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>_main<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>push</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>mov</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp,</span>&nbsp;<span>esp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>push</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>14h</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>参数</span>&nbsp;<span>2</span><span>入栈<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>push</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>0Ah</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>参数</span>&nbsp;<span>1</span><span>入栈<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>call</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>_function</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>调用函数<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>add</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>esp,</span>&nbsp;<span>8</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>修正栈<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>xor</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>eax,</span>&nbsp;<span>eax<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>pop</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>retn<br><br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>2.__fastcall<br><br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>@function@8<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>push</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>mov</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp,</span>&nbsp;<span>esp</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>保存栈指针<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>sub</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>esp,</span>&nbsp;<span>8</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>多了两个局部变量<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>mov</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>[ebp-8],</span>&nbsp;<span>edx</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>保存参数</span>&nbsp;<span>2<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>mov</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>[ebp-4],</span>&nbsp;<span>ecx</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>保存参数</span>&nbsp;<span>1<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>mov</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>eax,</span>&nbsp;<span>[ebp-4]</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>参数</span>&nbsp;<span>1<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>add</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>eax,</span>&nbsp;<span>[ebp-8]</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>加上参数</span>&nbsp;<span>2<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>mov</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>esp,</span>&nbsp;<span>ebp</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>修正栈<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>pop</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>retn<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>_main<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>push</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>mov</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp,</span>&nbsp;<span>esp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>mov</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>edx,</span>&nbsp;<span>14h</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>参数</span>&nbsp;<span>2</span><span>给<span>EDX<br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>mov</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ecx,</span>&nbsp;<span>0Ah</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>参数</span>&nbsp;<span>1</span><span>给<span>ECX<br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>call</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>@function@8</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>调用函数<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>xor</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>eax,</span>&nbsp;<span>eax<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>pop</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>retn<br><br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>3.__stdcall<br><br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>_function@8<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>push</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>mov</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp,</span>&nbsp;<span>esp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>mov</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>eax,</span>&nbsp;<span>[ebp]</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>参数</span>&nbsp;<span>1<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>add</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>eax,</span>&nbsp;<span>[ebp+C]</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>加上参数</span>&nbsp;<span>2<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>pop</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>retn</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>8</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>修复栈<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>_main<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>push</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>mov</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp,</span>&nbsp;<span>esp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>push</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>14h</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>参数</span>&nbsp;<span>2</span><span>入栈<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>push</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>0Ah</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>;</span><span>参数</span>&nbsp;<span>1</span><span>入栈<span><br></span>　</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>call</span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>_function@8</span><span>　　　　<span>;</span>函数调用<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>xor</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>eax,</span>&nbsp;<span>eax<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>pop</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>ebp<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>retn<br><br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>可见上述三种方法各有各的特点，而且<span>_main</span>必须是<span>__cdecl</span>，一般<span>WIN32</span>的函数都是<span><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>__stdcall</span><span>。而且在<span>Windef.h</span>中有如下的定义：<span><br><br></span></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>#define</span>&nbsp;<span>CALLBACK</span>&nbsp;<span>__stdcall<br></span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>#define</span>&nbsp;<span>WINAPI</span><span>　</span>&nbsp;<span>__stdcall</span></p>
<img src ="http://www.cppblog.com/tdweng/aggbug/130207.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-10-17 19:37 <a href="http://www.cppblog.com/tdweng/articles/130207.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【分享】C数组与指针学习笔记 </title><link>http://www.cppblog.com/tdweng/articles/129721.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Wed, 13 Oct 2010 01:58:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/129721.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/129721.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/129721.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/129721.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/129721.html</trackback:ping><description><![CDATA[<font size=4>文章标题】:&nbsp;c数组与指针学习笔记<br>【文章作者】:&nbsp;evilkis<br>--------------------------------------------------------------------------------------------------------<br>1.数组的定义<br>int&nbsp;a[5];定义了一个数组a,它可以存放5个整型数据，注意：在定义了一个数组时，编译系统会按照数组类型和数组元素个数来分配一段连续的存储空间来存储数组元素。则数组存放数组a的空间大小为5*sizeof(int)=&nbsp;20字节。<br><br>2&nbsp;数组的引用<br>当我们引用数组元素时下标从0开始，小于元素的个数，且只能逐个引用数组元素，而不能直接引用整个数组。如：int&nbsp;a[2]={1,2};int&nbsp;b[2]=a;这句就是错误的！原因是引用了整个数组。<br><br>3数组在内存中的存放<br>数组在内存中式按照下标的顺序来一次存放的可以理解为线性存放，多维数组也是按照这个顺序存放<br>4&nbsp;数组的初始化<br>数组的初始化可以在定义的时候用{}全部赋值&nbsp;如int&nbsp;a[2]={1,2};如果把定义和赋值分开那就错了如：int&nbsp;a[2];a[2]={1,2};其中第二句本意是把1,2赋值给数组a,但是此时a[2]的意义变了，他不在代表一个数组，而是下标引用数组元素，即数组a的第1个元素。所以数组初始化的赋值方式只能在数组定义时使用，定义之后在赋值，只能一个元素一个元素的赋值<br><br>5&nbsp;多维数组<br>多维数组简单的如二维数组，他其实可以看成一个特殊的一位数组，他的元素是一个一维数组，例如：int&nbsp;a[2][3]可以看做由2个一维数组a[0]和a[1]组成。<br>好了简单的了解了下数组的基本知识，现在我么开始讨论一些常见的问题<br><br>数组名是什么？等价于指针？<br>数组名是一个地址，而且是一个不可被修改的常量。这一点类似于符号常量，数组名这个符号代表了容纳数组的那块内存的首地址，注意：不是数组名的值是那块内存的首地址，数组名本身没有地址，只是代表了那块地址，他是一个右值，而指针是一个左值，所以数组名与指针不同。例如：int&nbsp;a[3];虽然数组名a没有地址，但是对其取地址&amp;a,得到的依然是数组首地址。把数组名想象成一个符号常量即可，即数组名没有地址，只是代表了这个数组的首地址。又因为数组名是个地址常量所以不能修改它的值，即a++，a--是错误的！只有两种情况数组名不表示地址常量<br>即sizeof（a）和&amp;a，前者表示数组的整个长度，后者是数组地址，但并不意味着a有地址,数组名是数组元素的首地址，不是数组的首地址<br><br>一维数组的寻址公式<br>如int&nbsp;a[6];<br>则a[n]的地址为(int)a+sizeof(int)*n(当然n&lt;=6),其原理即：首地址+偏移地址其中a一定要做强制类型转换因为a是有类型的，必须把其转换成整数，sizeof(int)即是一个元素的大小<br>推而广之<br>对于TYPE&nbsp;array[m];<br>则array[n]的地址为:(int)array+sizeof(TYPE)*n(n&lt;=m)//做逆向的时候很有用<br>二维数组的寻址公式<br>如:int&nbsp;a[4][5]<br>则a[2][3]的地址为:(int)a+sizeof(int[5])*2+sizeof(int)*3<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;数组首地址&nbsp;&nbsp;&nbsp;&nbsp;行偏移&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;列偏移<br>即：先算确定在第几行，在确定在第几列最后加上首地址<br>或者第二种方式：<br>a[2][3]的地址为:(int)a+sizeof(int)*(2*5+3)&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;直接定位元素看跨越了多少个元素然后乘以他们的数据类型大小<br>因为数组a每一行有5个元素故2*5,3是目标行的元素偏移<br>故推而光之<br>对于TYPE&nbsp;array[x][y]二维数组<br>则array[m][n]的地址为:(int)a+sizeof(int[y])*m+sizeof(TYPE)*n<br>或array[m][n]的地址为:(int)a+sizeof(TYPE)*(m*y+n)<br>这些寻址公式在逆向过程中很有用，至少看到这样的寻址方式我们应该能想到是个数组，其实把数组在内存中的存放想成线性的就很好理解这些寻址方法。<br><br>实践一下：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;a[5]={0,1,2,3,4};<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;b;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b=*((int)a+sizeof(int)*2);<br>&nbsp;&nbsp;&nbsp;问b是否能取到a[2]的值?<br>如果你说不能，恭喜你，你很理解地址与数值的概念，如果你说能，也不能怪你，下面我们就分析一下地址和数值的关系，由上面的讲述我们知道((int)a+sizeof(int)*2)这里得到的确确实实是a[2]的地址，然后对地址取内容理所当然取的是a[2]的值啊，呵呵，初学者可能都会这么想，但是那都是我们一厢情愿所造成的，其实((int)a+sizeof(int)*2)只是一个整数，不是地址的含义，没有任何指向意义，也就是a[2]的地址值等于((int)a+sizeof(int)*2)，但是并不意味着((int)a+sizeof(int)*2)是地址，实际上地址本来就是一个基本数据类型，也就是说地址是有指向意义有类型这是地址和地址值的区别，如果没有类型，操作系统从这首地址取值根本不知道要取多少字节，<br>所以我们要加上强制类型转换，使他有类型有指向意义即若改成*(int*)((int)a+sizeof(int)*2)即可取到a[2]的值<br><br><br>4&nbsp;数组名作函数参数<br>当数组名作函数参数时，传递的是数组首地址的一份拷贝，虽然数组名不可以自加，但是形参可以这里注意，因为形参是变量，存放的只是数组首地址的一份拷贝。<br><br>6指针<br>指针的定义：<br>通俗的讲：指针就是一个变量，他存放另一个变量的地址；特殊就特殊在它存放的是地址。<br>弄清关于指针的4个方面的内容：指针的类型&nbsp;指针所指向的类型&nbsp;指针的值&nbsp;指针本身所占的内存区<br>如：<br>1指针的类型<br>把指针的名字去掉剩下的就是指针的类型：<br>int&nbsp;*p&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//指针的类型为&nbsp;int*<br>char&nbsp;**p&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//指针的类型为char**<br>int&nbsp;(*p)[5]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//指针得到类型为int(*)[5]<br>在32位平台下里所有指针类型的大小均为4字节<br>2&nbsp;指针所指向的类型<br>当我们通过指针来访问指针所指向的内存区时，指针的所指向的类型决定了编译器将那块内存里的内容当做什么来看待<br>把指针的名字和指针声明符*去掉，剩下的即指针所指向的类型<br>int&nbsp;*p&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//指针所指向的类型为int<br>char&nbsp;**p&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//指针所指向的类型为int*即p指向一个指针<br>int&nbsp;(*p)[5]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//指针所指向的类型为int()[5]<br>3指针的值<br>指针的值指针变量存放的地址值，他指向首地址为他的一片内存区，大小为sizeof(指针所指向的类型)<br>4&nbsp;指针本身所占的内存区<br>因为指针也是一个变量，所以指针本身也占内存，在32平台下大小为4字节<br>运算符&amp;和*<br>&amp;a的结果是产生了一个指针，*p的结果是p所指向的东西<br><br>指针的运算<br>指针加减一个整型数据得到的还是一个指针，指针加减一个指针得到的是一个整型数据。<br><br>关于复杂的指针声明<br>指针数组:如&nbsp;int&nbsp;*ptr[10],首先它是一个含有是个元素的数组，其次元素类型为int*,即元素为指针，<br>数组指针：int&nbsp;(*p)[10]，首先他是一个指针，其次他指向一个int[10]的数组<br>如果实在弄混的话就想想牛奶和奶牛的区别，牛奶是奶，而奶牛是牛,即中国人说话主语都在后面，说堆栈，其实说的是栈.<br>函数指针:<br>int&nbsp;(*p)&nbsp;(int&nbsp;x,int&nbsp;y)因为指针指向函数而函数名的类型为int(int&nbsp;x,int&nbsp;y)；所以定义的时候相当于&nbsp;int&nbsp;(int&nbsp;x,int&nbsp;y)&nbsp;(*p)<br>如果把*p两边的括号去掉则int&nbsp;*p(int&nbsp;x,int&nbsp;y)表示函数p返回值是个指针<br>9&nbsp;二维数组与指针<br><br>int&nbsp;ptr[2][3]={1,2,3,4,5,6};<br>关于二维数组主要就是要搞清楚&nbsp;数组的指针&nbsp;某一行的指针&nbsp;某一行某一列的指针之间的区别<br>单纯的数组名ptr则是数组第0行的指针&nbsp;她指向第0行，同理ptr+1指向第1行，这两个均为行指针，问题来了&nbsp;*(ptr+1)可能有很多人认为它的值为4，即ptr[1][0]的值，因为ptr+1是第1行的首地址，所以对其取内容应该为ptr[1][0]的值，实际上是错的因为&nbsp;ptr+1是一个行指针&nbsp;而我们要取元素的话要使用列指针，所以要做个强制类型转换&nbsp;即*(ptr+1)为列指针其值与ptr+1的值相等但意义不同如果不理解请接着看<br>例如：int&nbsp;a[i]<br>这样数组名加下标的形式，被编译器理解为<br>*(a+i)<br>同理，a[i][j]被理解为：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*(a[i]&nbsp;+&nbsp;j)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;＝&nbsp;*(*(a&nbsp;+&nbsp;i)&nbsp;+&nbsp;j)&nbsp;&nbsp;<br>a+1表示a[1]的地址，a[1]表示a[1][0]的地址,尽管他们的值是一样的！<br><br>其实数组与指针并不难，只要平时多练习多用久而久之就会了。笔记就到这里了写的比较乱，希望对初学者有所帮助，有不对的地方请指正</font> <!-- google_ad_section_end  -->
<img src ="http://www.cppblog.com/tdweng/aggbug/129721.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-10-13 09:58 <a href="http://www.cppblog.com/tdweng/articles/129721.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>函数成员变量</title><link>http://www.cppblog.com/tdweng/articles/129094.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Fri, 08 Oct 2010 14:20:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/129094.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/129094.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/129094.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/129094.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/129094.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">base</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_11_165_Open_Image onclick="this.style.display='none'; Codehighlighter1_11_165_Open_Text.style.display='none'; Codehighlighter1_11_165_Closed_Image.style.display='inline'; Codehighlighter1_11_165_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_11_165_Closed_Image onclick="this.style.display='none'; Codehighlighter1_11_165_Closed_Text.style.display='none'; Codehighlighter1_11_165_Open_Image.style.display='inline'; Codehighlighter1_11_165_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_11_165_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_11_165_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;</span><span style="COLOR: #0000ff">base</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i):m_j(i),m_i(m_j)<br><img id=Codehighlighter1_51_57_Open_Image onclick="this.style.display='none'; Codehighlighter1_51_57_Open_Text.style.display='none'; Codehighlighter1_51_57_Closed_Image.style.display='inline'; Codehighlighter1_51_57_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_51_57_Closed_Image onclick="this.style.display='none'; Codehighlighter1_51_57_Closed_Text.style.display='none'; Codehighlighter1_51_57_Open_Image.style.display='inline'; Codehighlighter1_51_57_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_51_57_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_51_57_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">&nbsp;}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;get_i()<br><img id=Codehighlighter1_73_90_Open_Image onclick="this.style.display='none'; Codehighlighter1_73_90_Open_Text.style.display='none'; Codehighlighter1_73_90_Closed_Image.style.display='inline'; Codehighlighter1_73_90_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_73_90_Closed_Image onclick="this.style.display='none'; Codehighlighter1_73_90_Closed_Text.style.display='none'; Codehighlighter1_73_90_Open_Image.style.display='inline'; Codehighlighter1_73_90_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_73_90_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_73_90_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;m_i;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">&nbsp;}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;get_j()<br><img id=Codehighlighter1_106_123_Open_Image onclick="this.style.display='none'; Codehighlighter1_106_123_Open_Text.style.display='none'; Codehighlighter1_106_123_Closed_Image.style.display='inline'; Codehighlighter1_106_123_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_106_123_Closed_Image onclick="this.style.display='none'; Codehighlighter1_106_123_Closed_Text.style.display='none'; Codehighlighter1_106_123_Open_Image.style.display='inline'; Codehighlighter1_106_123_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_106_123_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_106_123_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;m_j;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">&nbsp;}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">:<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;m_i;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;m_j;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;argv[])<br><img id=Codehighlighter1_202_285_Open_Image onclick="this.style.display='none'; Codehighlighter1_202_285_Open_Text.style.display='none'; Codehighlighter1_202_285_Closed_Image.style.display='inline'; Codehighlighter1_202_285_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_202_285_Closed_Image onclick="this.style.display='none'; Codehighlighter1_202_285_Closed_Text.style.display='none'; Codehighlighter1_202_285_Open_Image.style.display='inline'; Codehighlighter1_202_285_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_202_285_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_202_285_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;</span><span style="COLOR: #0000ff">base</span><span style="COLOR: #000000">&nbsp;obj(</span><span style="COLOR: #000000">98</span><span style="COLOR: #000000">);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;obj.get_i()&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;obj.get_j()&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span></div>
<p><br>在带参数的构造函数中，初始化列表的初始化变量顺序是根据成员变量的声明顺序来执行的，因此m_i会被<br>赋予一个随机值，输出是<br>-858993460<br>98<br>如果在声明变量为<br>&nbsp;int m_j;</p>
int m_i;<br>就会输出正常值 <br>98<br>98<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;A<br><img id=Codehighlighter1_8_33_Open_Image onclick="this.style.display='none'; Codehighlighter1_8_33_Open_Text.style.display='none'; Codehighlighter1_8_33_Closed_Image.style.display='inline'; Codehighlighter1_8_33_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_8_33_Closed_Image onclick="this.style.display='none'; Codehighlighter1_8_33_Closed_Text.style.display='none'; Codehighlighter1_8_33_Open_Image.style.display='inline'; Codehighlighter1_8_33_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_8_33_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_8_33_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Size&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span></div>
<br>是错误的，常量必须在构造函数的初始化列表里面初始化<br>如<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;A<br><img id=Codehighlighter1_8_46_Open_Image onclick="this.style.display='none'; Codehighlighter1_8_46_Open_Text.style.display='none'; Codehighlighter1_8_46_Closed_Image.style.display='inline'; Codehighlighter1_8_46_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_8_46_Closed_Image onclick="this.style.display='none'; Codehighlighter1_8_46_Closed_Text.style.display='none'; Codehighlighter1_8_46_Open_Image.style.display='inline'; Codehighlighter1_8_46_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_8_46_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_8_46_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;A()<br><img id=Codehighlighter1_19_44_Open_Image onclick="this.style.display='none'; Codehighlighter1_19_44_Open_Text.style.display='none'; Codehighlighter1_19_44_Closed_Image.style.display='inline'; Codehighlighter1_19_44_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_19_44_Closed_Image onclick="this.style.display='none'; Codehighlighter1_19_44_Closed_Text.style.display='none'; Codehighlighter1_19_44_Open_Image.style.display='inline'; Codehighlighter1_19_44_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_19_44_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_19_44_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Size&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000">;&nbsp;</span></div>
<img src ="http://www.cppblog.com/tdweng/aggbug/129094.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-10-08 22:20 <a href="http://www.cppblog.com/tdweng/articles/129094.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>static用法总结</title><link>http://www.cppblog.com/tdweng/articles/124767.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Thu, 26 Aug 2010 01:07:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/124767.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/124767.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/124767.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/124767.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/124767.html</trackback:ping><description><![CDATA[<p>用static声明的函数和变量小结<o:p></o:p></p>
<p>&nbsp;static 声明的变量在C语言中有两方面的特征：<br>　　1)、变量会被放在程序的全局存储区中，这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与堆栈变量和堆变量的区别。<br>　　2)、变量用static告知编译器，自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。<br>Tips:<br>　　A.若全局变量仅在单个C文件中访问，则可以将这个变量修改为静态全局变量，以降低模块间的耦合度；<br>　　B.若全局变量仅由单个函数访问，则可以将这个变量改为该函数的静态局部变量，以降低模块间的耦合度；<br>　　C.设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时，需要考虑重入问题；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D.如果我们需要一个可重入的函数，那么，我们一定要避免函数中使用static变量(这样的函数被称为：带&#8220;内部存储器&#8221;功能的的函数)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; E.函数中必须要使用static变量情况:比如当某函数的返回值为指针类型时，则必须是static的局部变量的地址作为返回值，若为auto类型，则返回为错指针。<o:p></o:p></p>
<p>函数前加static使得函数成为静态函数。但此处&#8220;static&#8221;的含义不是指存储方式，而是指对函数的作用域仅局限于本文件(所以又称内部函数)。使用内部函数的好处是：不同的人编写不同的函数时，不用担心自己定义的函数，是否会与其它文件中的函数同名。<o:p></o:p></p>
<p>扩展分析:术语static有着不寻常的历史.起初，在C中引入关键字static是为了表示退出一个块后仍然存在的局部变量。随后，static在C中有了第二种含义：用来表示不能被其它文件访问的全局变量和函数。为了避免引入新的关键字，所以仍使用static关键字来表示这第二种含义。最后，C++重用了这个关键字，并赋予它与前面不同的第三种含义：表示属于一个类而不是属于此类的任何特定对象的变量和函数(与Java中此关键字的含义相同)。<o:p></o:p></p>
<p>全局变量、静态全局变量、静态局部变量和局部变量的区别<o:p></o:p></p>
<p>变量可以分为：全局变量、静态全局变量、静态局部变量和局部变量。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 按存储区域分，全局变量、静态全局变量和静态局部变量都存放在内存的静态存储区域，局部变量存放在内存的栈区。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 按作用域分，全局变量在整个工程文件内都有效；静态全局变量只在定义它的文件内有效；静态局部变量只在定义它的函数内有效，只是程序仅分配一次内存，函数返回后，该变量不会消失；局部变量在定义它的函数内有效，但是函数返回后失效。<o:p></o:p></p>
<p>全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式， 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序， 当一个源程序由多个源文件组成时，非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域， 即只在定义该变量的源文件内有效， 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内，只能为该源文件内的函数公用， 因此可以避免在其它源文件中引起错误。 <o:p></o:p></p>
<p>　　从以上分析可以看出， 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域， 限制了它的使用范围。<o:p></o:p></p>
<p>　　static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static)，内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数，应该在一个头文件中说明，要使用这些函数的源文件要包含这个头文件<o:p></o:p></p>
<p>　　static全局变量与普通的全局变量有什么区别：static全局变量只初始化一次，防止在其他文件单元中被引用;<br>　　static局部变量和普通局部变量有什么区别：static局部变量只被初始化一次，下一次依据上一次结果值；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static函数与普通函数有什么区别：static函数在内存中只有一份，普通函数在每个被调用中维持一份拷贝<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;全局变量和静态变量如果没有手工初始化，则由编译器初始化为0。局部变量的值不可知。<o:p></o:p></p>
<p><o:p>&nbsp;</o:p></p>
<p><o:p>&nbsp;</o:p></p>
.先来介绍它的第一条也是最重要的一条：隐藏。
<p>当我们同时编译多个文件时，所有未加static前缀的全局变量和函数都具有全局可见性。为理解这句话，我举例来说明。我们要同时编译两个源文件，一个是a.c，另一个是main.c.</p>
<p>下面是a.c的内容：</p>
<table border=1 cellSpacing=0 borderColorLight=#999999 borderColorDark=#ffffff cellPadding=2 width=400 align=center>
    <tbody>
        <tr>
            <td bgColor=#e6e6e6>
            <pre> char a = 'A'; // global variable
            void msg()
            {
            printf("Hello\n");
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<p>下面是main.c的内容：</p>
<table border=1 cellSpacing=0 borderColorLight=#999999 borderColorDark=#ffffff cellPadding=2 width=400 align=center>
    <tbody>
        <tr>
            <td bgColor=#e6e6e6>
            <pre> int main(void)
            {
            extern char a; // extern variable must be declared before use
            printf("%c ", a);
            (void)msg();
            return 0;
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<p>程序的运行结果是：</p>
<p>A Hello</p>
<p>你可能会问：为什么在a.c中定义的全局变量a和函数msg能在main.c中使用？前面说过，所有未加static前缀的全局变量和函数都具有全局可见性，其它的源文件也能访问。此例中，a是全局变量，msg是函数，并且都没有加static前缀，因此对于另外的源文件main.c是可见的。</p>
<p>如果加了static，就会对其它源文件隐藏。例如在a和msg的定义前加上static，main.c就看不到它们了。利用这一特性可以在不同的文件中定义同名函数和同名变量，而不必担心命名冲突。Static可以用作函数和变量的前缀，对于函数来讲，static的作用仅限于隐藏，而对于变量，static还有下面两个作用。</p>
<p>2.static的第二个作用是保持变量内容的持久。</p>
<p>存储在静态数据区的变量会在程序刚开始运行时就完成初始化，也是唯一的一次初始化。共有两种变量存储在静态存储区：全局变量和static变量，只不过和全局变量比起来，static可以控制变量的可见范围，说到底static还是用来隐藏的。虽然这种用法不常见，但我还是举一个例子。</p>
<table border=1 cellSpacing=0 borderColorLight=#999999 borderColorDark=#ffffff cellPadding=2 width=400 align=center>
    <tbody>
        <tr>
            <td bgColor=#e6e6e6>
            <pre> #include ＜stdio.h＞
            int fun(void){
            static int count = 10; // 事实上此赋值语句从来没有执行过
            return count--;
            }
            int count = 1;
            int main(void)
            {
            printf("global\t\tlocal static\n");
            for(; count ＜= 10; ++count)
            printf("%d\t\t%d\n", count, fun());
            return 0;
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
<p>程序的运行结果是：<br></p>
<p align=center>global local static<br>1&nbsp; 10<br>2&nbsp;&nbsp; 9<br>3&nbsp;&nbsp; 8<br>4&nbsp;&nbsp; 7<br>5&nbsp;&nbsp; 6<br>6&nbsp;&nbsp; 5<br>7&nbsp;&nbsp; 4<br>8&nbsp;&nbsp; 3<br>9&nbsp;&nbsp; 2<br>10&nbsp;&nbsp;1</p>
<p>3.static的第三个作用是默认初始化为0.其实全局变量也具备这一属性，因为全局变量也存储在静态数据区。</p>
<p>在静态数据区，内存中所有的字节默认值都是0x00，某些时候这一特点可以减少程序员的工作量。比如初始化一个稀疏矩阵，我们可以一个一个地把所有元素都置0，然后把不是0的几个元素赋值。如果定义成静态的，就省去了一开始置0的操作。再比如要把一个字符数组当字符串来用，但又觉得每次在字符数组末尾加&#8216;\0&#8217;太麻烦。如果把字符串定义成静态的，就省去了这个麻烦，因为那里本来就是&#8216;\0&#8217;。不妨做个小实验验证一下。</p>
<table border=1 cellSpacing=0 borderColorLight=#999999 borderColorDark=#ffffff cellPadding=2 width=400 align=center>
    <tbody>
        <tr>
            <td bgColor=#e6e6e6>
            <pre>#include ＜stdio.h＞
            int a;
            int main(void)
            {
            int i;
            static char str[10];
            printf("integer: %d; string: (begin)%s(end)", a, str);
            return 0;
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<p>程序的运行结果如下integer： 0； string： （begin）（end）</p>
<p>最后对static的三条作用做一句话总结。首先static的最主要功能是隐藏，其次因为static变量存放在静态存储区，所以它具备持久性和默认值0.</p>
<img src ="http://www.cppblog.com/tdweng/aggbug/124767.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-08-26 09:07 <a href="http://www.cppblog.com/tdweng/articles/124767.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>零值比较--BOOL，int，float，指针变量与零值比较的if语句</title><link>http://www.cppblog.com/tdweng/articles/124762.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Thu, 26 Aug 2010 00:36:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/124762.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/124762.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/124762.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/124762.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/124762.html</trackback:ping><description><![CDATA[<p style="COLOR: #000000">这是程序员面试的一道常见题，也是个C++基础问题。若只在大学里看过几本基础的编程入门书，看见这道题可能会觉得奇怪，不就是和0比较吗，直接拿出来比就是了，其实非也。下文引自google搜索结果，出处不详，高手可以无视，菜菜留下，记得做好笔记。<br>首先给个提示：题目中要求的是零值比较，而非与0进行比较，在C++里&#8220;零值&#8221;的范围可就大了，可以是0， 0.0 ， FALSE或者&#8220;空指针&#8221;。<br><span style="COLOR: #ff0000"><strong>int型变量 n 与&#8220;零值&#8221;比较的 if 语句就是：</strong></span><br><br>if ( n == 0 )<br><br>if ( n != 0 )<br><br>如下写法均属不良风格.。<br><br>if ( n )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 会让人误解 n 是布尔变量<br><br>if ( !n&nbsp;&nbsp; )<br><br><span style="COLOR: #ff0000"><strong>&nbsp;BOOL flag 与&#8220;零值&#8221;比较的 if 语句:</strong></span><br><br>根 据布尔类型的语义，零值为&#8220;假&#8221;（记为FALSE），任何非零值都是&#8220;真&#8221;（记为TRUE）。TRUE 的值究竟是什么并没有统一的标准。例如Visual C++ 将TRUE 定义为1，而Visual Basic 则将TRUE 定义为-1。所以我们不可以将布尔变量直接与TRUE、FALSE 或者1、0 进行比较。<br><br>标准答案：<br><br>if ( flag )<br><br>if ( !flag )<br><br>如下写法均属不良风格。<br><br>if (flag == TRUE) <br><br>if (flag == 1 ) <br><br>if (flag == FALSE) <br><br>if (flag == 0) <br><br><span style="COLOR: #ff0000"><strong>float x 与&#8220;零值&#8221;比较的 if 语句:</strong></span><br>千万要留意，无论是float 还是double 类型的变量，都有精度限制，都不可以用&#8220;==&#8221;或&#8220;！=&#8221;与任何数字比较，应该设法转化成&#8220;&gt;=&#8221;或&#8220;&lt;=&#8221;形式。(为什么？文章之后有详细的讨论，可参考)<br><br>假设浮点变量的名字为x，应当将<br><br>if (x == 0.0)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 隐含错误的比较<br><br>转化为<br><br>if ((x&gt;=-EPSINON) &amp;&amp; (x&lt;=EPSINON))<br><br>其中EPSINON 是允许的误差（即精度）。<br><br>标准答案示例：<br><br>const float EPSINON = 0.00001;<br><br>if ((x &gt;= - EPSINON) &amp;&amp; (x &lt;= EPSINON)<br><br>如下是错误的写法。<br><br>if (x == 0.0) <br><br>if (x != 0.0)&nbsp;<br><br><span style="COLOR: #ff0000"><strong>char *p 与&#8220;零值&#8221;比较的 if 语句:</strong></span><br><br>标准答案：<br><br>if (p == NULL)<br><br>if (p != NULL)<br><br>如下写法均属不良风格。<br><br>if (p == 0)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 容易让人误解p是整型变量<br><br>if (p != 0) <br><br>if (p)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 容易让人误解p是bool型变量<br><br>if (!p) <br><br>以 上的不良风格很多都能通过编译，但是语句并不能很好的表达与零值进行比较的逻辑依据。一般的，如果想用 if 语句判断一个变量的真假，应该直接使用if（var）、if（！var），表明此 if 语句的功能为&#8220;逻辑&#8221;判断；如果想用 if 语句判断一个数值型变量（short、int、long等），应该用if（var==0），表明此 if 语句是将变量与0进行&#8220;数值&#8221;上的比较；而检视指针是否为空则适宜用if（var==NULL），这是一种很好的编程习惯。<br><br>浮点型变量并不精确，所以不可将float变量用&#8220;==&#8221;或&#8220;！=&#8221;与数字比较，应该设法转化成&#8220;&gt;=&#8221;或&#8220;&lt;=&#8221;形式。如果写成if （x == 0.0），则判为错，得0分。以下给出详细原因：<br>浮点数在内存中的存贮机制和整型数不同，有舍入误差，在计算机中用以近似表示任意某个实数。具体的说，这个实数由一个整数或定点数（即尾数）乘以某个基数（计算机中通常是2）的整数次幂得到，这种表示方法类似于基数为10的科学记数法。 <br>所以浮点数在运算过成功运算通常伴随着因为无法精确表示而进行的近似或舍入。但是这种设计的好处是可以在固定的长度上存储更大范围的数。 <br>例如，一个指数范围为&#177;4的4位十进制浮点数可以用来表示43210，4.321或0.0004321，但是没有足够的精度来表示432.123和43212.3（必须近似为432.1和43210）。当然，实际使用的位数通常远大于4。 <br>所以浮点数不能够判断相等，像 if(x==0)的这样的编码是不总是正确的，我们在判断浮点数相等时，推荐用范围来确定，若x在某一范围内，我们就认为相等，至于范围怎么定义，要看实际情况而已了，float，和double 各有不同 <br>所以const float EPSINON = 0.00001; <br>if ((x &gt;= - EPSINON) &amp;&amp; (x &lt;= EPSINON) 这样判断是可取的 <br>至于为什么取0.00001，可以自己按实际情况定义<br><br>再看下面CSDN上的回答<br></p>
<div style="COLOR: #000000">
<div style="COLOR: #000000">引用</div>
<div style="COLOR: #000000">#define&nbsp;&nbsp; E&nbsp;&nbsp; 1.0E-6&nbsp;&nbsp; <br><br>float&nbsp;&nbsp; x&nbsp;&nbsp; 与&#8220;零值&#8221;比较的if&nbsp;&nbsp; <br>-----------------------&nbsp;&nbsp; <br><br>浮点数是不可以直接比较大小的，因为是非精确存储，只能设置一个精度，然后在允许误差内的就认为是相等的；对浮点型数比较的时候用==是不对的&nbsp;&nbsp; <br><br>#define&nbsp;&nbsp; E&nbsp;&nbsp; 0.000001&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><br>fabs((a+b)+c)&nbsp;&nbsp; -&nbsp;&nbsp; ((b+a)+c))</div>
</div>
<img src ="http://www.cppblog.com/tdweng/aggbug/124762.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-08-26 08:36 <a href="http://www.cppblog.com/tdweng/articles/124762.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++高效编程忠告 </title><link>http://www.cppblog.com/tdweng/articles/124633.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Wed, 25 Aug 2010 02:26:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/124633.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/124633.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/124633.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/124633.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/124633.html</trackback:ping><description><![CDATA[这是对C++高效编程的一个总结, 很有指导作用.<br><br><strong><span style="COLOR: red">一、#include &#8220;filename.h&#8221;和#include &lt;filename.h&gt;的区别</span></strong><br>#include &#8220;filename.h&#8221;是指编译器将从当前工作目录上开始查找此文件<br>#include &lt;filename.h&gt;是指编译器将从标准库目录中开始查找此文件<br><br><strong><span style="COLOR: red">二、头文件的作用</span></strong><br>加强安全检测<br>通过头文件可能方便地调用库功能，而不必关心其实现方式<br><br><strong><span style="COLOR: red">三、* , &amp;修饰符的位置<br></span></strong>int *i,j; // better for read<br>&nbsp;i = new int(0);<br>&nbsp;j = 0;<br>&nbsp;int *&amp;y = i; // pointer's reference<br>对于*和&amp;修饰符，为了避免误解，最好将修饰符紧靠变量名<br><strong><span style="COLOR: red">四、if语句</span><br></strong>不要将布尔变量与任何值进行比较，那会很容易出错的。<br>整形变量必须要有类型相同的值进行比较<br>浮点变量最好少比相等，可以通过求差与较小的数比较<br>指针变量要和NULL进行比较，不要和布尔型和整形比较<br><br><strong><span style="COLOR: red">五、const和#define的比较</span></strong><br>const有数据类型，#define没有数据类型<br>个别编译器中const可以进行调试，#define不可以进行调试<br>在类中定义常量有两种方式<br>1、 在类在声明常量，但不赋值，在构造函数初始化表中进行赋值；（常量和引用类型的成员变量必须通过初始化列表来初始化赋值）<br>2、 用枚举代替const常量。<br><br><strong><span style="COLOR: red">六、C++函数中值的传递方式</span></strong><br>有三种方式：值传递(Pass by value)、指针传递(Pass by pointer)、引用传递(Pass by reference)<br>void fun(char c) //pass by value<br>void fun(char *str) //pass by pointer<br>void fun(char &amp;str) //pass by reference<br>如果输入参数是以值传递的话，最好使用引用传递代替，因为引用传递省去了临时对象的构造和析构<br>函数的返回类型不能省略，就算没有也要加个void<br><span style="COLOR: red"><strong>七、函数体中的指针或引用常量不能被返回</strong></span>
<div class=code>Char *func(void)<br>{<br>&nbsp;char str[]=&#8221;Hello Word&#8221;;<br>&nbsp;//这个是不能被返回的，因为str是个指定变量，不是一般的值，函数结束后会被注销掉<br>//它是存放在栈中，函数结束后被注销掉<br>//可以改为 char *str = "HelloWorld",因为指针存放在全局作用域中，函数结束后不会被注销<br>&nbsp;return str; <br>}</div>
函数体内的指针变量并不会随着函数的消亡而自动释放<br><br><strong><span style="COLOR: red">八、一个内存拷贝函数的实现体</span></strong>
<div class=code>void *memcpy(void *pvTo,const void *pvFrom,size_t size)<br><br>{<br><br>&nbsp;assert((pvTo!=NULL)&amp;&amp;(pvFrom!=NULL));<br><br>&nbsp;byte *pbTo=(byte*)pvTo; //防止地址被改变<br><br>&nbsp;byte *pbFrom=(byte*)pvFrom;<br><br>&nbsp;while (size-- &gt;0)<br><br>&nbsp;pbTo++ = pbForm++;<br><br>&nbsp;return pvTo;<br><br>}</div>
<strong><span style="COLOR: red">九、内存的分配方式</span><br></strong>分配方式有三种，请记住，说不定那天去面试的时候就会有人问你这问题<br>1、 静态存储区，是在程序编译时就已经分配好的，在整个运行期间都存在，如全局变量、常量。（程序编译后运行时包含code和data两部分，其中data即为静态存储区分配，程序一开始运行便分配整个data的东东）<br>2、 栈上分配，函数内的局部变量就是从这分配的，但分配的内存容易有限。<br>3、 堆上分配，也称动态分配，如我们用new,malloc分配内存，用delete,free来释放的内存。<br><br><strong><span style="COLOR: red">十、内存分配的注意事项</span></strong><br>用new或malloc分配内存时，必须要对此指针赋初值。<br>用delete 或free释放内存后，必须要将指针指向NULL<br>不能修改指向常量的指针数据<br><span style="COLOR: red"><strong>十一、内容复制与比较</strong></span>
<div class=code>//数组&#8230;&#8230;<br>char a[]=&#8221;Hello Word!&#8221;;<br>char b[10];<br>strcpy(b,a);<br>if (strcmp(a,b)==0)<br>{}</div>
<div class=code>//指针&#8230;&#8230;<br>char a[]=&#8221;Hello Word!&#8221;;<br>char *p;<br>p=new char[strlen(a)+1];<br>strcpy(p,a);<br>if (strcmp(p,a)==0)<br>{}<br><br><strong><span style="COLOR: red">十二、sizeof的问题</span><br></strong>记住一点，C++无法知道指针所指对象的大小，指针的大小永远为4字节
<div class=code>char a[]=&#8221;Hello World!&#8221;<br>char *p=a;<br>count&lt;&lt;sizeof(a)&lt;&lt;end; //12字节<br>count&lt;&lt;sizeof(p)&lt;&lt;endl; //4字节</div>
而且，在函数中，数组参数退化为指针，所以下面的内容永远输出为4
<div class=code>void fun(char a[1000])<br>{<br>count&lt;&lt;sizeof(a)&lt;&lt;endl; //输出4而不是1000<br>}</div>
<br><strong><span style="COLOR: red">十三、关于指针</span></strong><br>1、 指针创建时必须被初始化<br>2、 指针在free 或delete后必须置为NULL<br>3、 指针的长度都为4字节<br>4、释放内存时，如果是数组指针，必须要释放掉所有的内存，如
<div class=code>char *p=new char[100];<br>strcpy(p,&#8221;Hello World&#8221;);<br>delete []p; //注意前面的［］号<br>p=NULL;</div>
5、数组指针的内容不能超过数组指针的最大容易。<br>如:
<div class=code>char *p=new char[5];<br>strcpy(p,&#8221;Hello World&#8221;); //报错 目标容易不够大<br>delete []p; //注意前面的［］号<br>p=NULL;</div>
<strong><span style="COLOR: red">十四、关于malloc/free 和new /delete</span><br></strong>malloc/free 是C/C+的内存分配符，new /delete是C++的内存分配符。<br>注意：malloc/free是库函数，new/delete是运算符<br>malloc/free不能执行构造函数与析构函数，而new/delete可以<br>new/delete不能在C上运行，所以malloc/free不能被淘汰<br>两者都必须要成对使用<br>C++中可以使用_set_new_hander函数来定义内存分配异常的处理<br><br><br><strong><span style="COLOR: red">十五、Ｃ++的特性</span></strong><br>Ｃ++新增加有重载(overload)，内联（inline），Const，Virtual四种机制<br>重载和内联：即可用于全局函数，也可用于类的成员函数；<br>Const和Virtual：只可用于类的成员函数；<br>重载：在同一类中，函数名相同的函数。由不同的参数决定调用那个函数。函数可要不可要Virtual关键字。和全局函数同名的函数不叫重载。如果在类中调用同名的全局函数，必须用全局引用符号::引用。<br>覆盖是指派生类函数覆盖基类函数：函数名相同；参数相同；基类函数必须有Virtual关键字；不同的范围(派生类和基类)。<br>隐藏是指派生类屏蔽了基类的同名函数相同<br>1、 函数名相同，但参数不同，此时不论基类有无Virtual关键字，基类函数将被隐藏。<br>2、 函数名相同，参数也相同，但基类无Virtual关键字(有就是覆盖)，基类函数将被隐藏。<br>内联：inline关键字必须与定义体放在一起，而不是单单放在声明中。<br>Const：const是constant的缩写，&#8220;恒定不变&#8221;的意思。被const修饰的东西都受到强制保护，可以预防意外的变动，能提高程序的健壮性。<br>1、 参数做输入用的指针型参数，加上const可防止被意外改动。<br>2、 按值引用的用户类型做输入参数时，最好将按值传递的改为引用传递，并加上const关键字，目的是为了提高效率。数据类型为内部类型的就没必要做这件事情；如：<br>将void Func(A a) 改为void Func(const A &amp;a)。<br>而void func(int a)就没必要改成void func(const int &amp;a);<br>3、 给返回值为指针类型的函数加上const，会使函数返回值不能被修改，赋给的变量也只能是const型变量。如：函数const char*GetString(void); char *str=GetString()将会出错。而const char *str=GetString()将是正确的。<br>4、 Const成员函数是指此函数体内只能调用Const成员变量，提高程序的键壮性。如声明函数 int GetCount(void) const;此函数体内就只能调用Const成员变量。<br>Virtual：虚函数：派生类可以覆盖掉的函数，纯虚函数：只是个空函数，没有函数实现体；<br><strong><span style="COLOR: red">十六、extern&#8220;C&#8221;有什么作用？</span><br></strong>Extern &#8220;C&#8221;是由Ｃ＋＋提供的一个连接交换指定符号，用于告诉Ｃ＋＋这段代码是Ｃ函数。这是因为C++编译后库中函数名会变得很长，与C生成的不一致，造成Ｃ＋＋不能直接调用C函数，加上extren &#8220;c&#8221;后，C++就能直接调用C函数了。<br>Extern &#8220;C&#8221;主要使用正规DLL函数的引用和导出 和 在C++包含C函数或C头文件时使用。使用时在前面加上extern &#8220;c&#8221; 关键字即可。<br><strong><span style="COLOR: red">十七、构造函数与析构函数</span><br></strong>派生类的构造函数应在初始化表里调用基类的构造函数；<br>派生类和基类的析构函数应加Virtual关键字。<br>不要小看构造函数和析构函数，其实编起来还是不容易。
<div class=code>#include &lt;iostream.h&gt;<br>class Base<br>{<br>public: <br>virtual ~Base() { cout&lt;&lt; "~Base" &lt;&lt; endl ; }<br>};<br><br>class Derived : public Base<br>{<br>public: <br>virtual ~Derived() { cout&lt;&lt; "~Derived" &lt;&lt; endl ; }<br>};<br><br>void main(void)<br>{<br>Base * pB = new Derived; // upcast<br>delete pB;<br>}</div>
输出结果为：<br>~Derived<br>~Base<br><br>如果析构函数不为虚，那么输出结果为<br>~Base<br><strong><span style="COLOR: red">十八、#IFNDEF/#DEFINE/#ENDIF有什么作用</span><br></strong>仿止该头文件被重复引用&nbsp;<br><span style="COLOR: red"><strong>十九、三维数组一次输出<br></strong></span>&nbsp;int b[2][3][4]={{{0,1,2,3,},{4,5,6,7},{8,9,10,11}},{{12,13,14,15},{16,17,18,19},{20,21,22,23}}};<br>&nbsp;&nbsp;&nbsp; int i,j;<br>&nbsp;&nbsp;&nbsp; for(i=0,j=1;i&lt;24;i++,j++)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("%3d",b[i/12][i%12/4][i%12%4]);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(j%4==0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("\n");<br>&nbsp;&nbsp;&nbsp; }<br></div>
<img src ="http://www.cppblog.com/tdweng/aggbug/124633.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-08-25 10:26 <a href="http://www.cppblog.com/tdweng/articles/124633.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC _T的用途</title><link>http://www.cppblog.com/tdweng/articles/124436.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Mon, 23 Aug 2010 08:46:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/124436.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/124436.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/124436.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/124436.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/124436.html</trackback:ping><description><![CDATA[<p>VC++里面定义字符串的时候，用_T来保证兼容性。VC++支持ascii和unicode两种字符类型，用_T可以保证从ascii编码类型转换到unicode编码类型的时候，程序不需要修改。</p>
<p>如果将来你不打算升级到unicode，那么也不需要_T。</p>
<p>_t("hello world")</p>
<p>在ansi的环境下，它是ansi的，如果在unicode下，那么它将自动解释为双字节字符串，既unicode编码。</p>
<p>这样做的好处，不管是ansi环境，还是unicode环境，都适用。</p>
<p>那么在VC++中，字符串_T("ABC")和一个普通的字符串"ABC"有什么区别呢？</p>
<p>_T("ABC")</p>
<p>如果定义了unicode，它将表示为L"ABC"，每个字符为16位，宽字符串。</p>
<p>如果没有定义unicode，它就是ascii的"ABC"，每个字符为8位。</p>
<p>相当于</p>
<p>#ifdef _UNICODE</p>
<p>#define _T("ABC") L"ABC"</p>
<p>#else</p>
<p>#define _T("ABC") "ABC"</p>
<p>#endif</p>
<p>_T("ABC")中的一个字符和汉字一样，占两个字节，而在"ABC"中，英文字符占一个字节，汉字占两个字节。</p>
<p>一、 在字符串前加一个L作用:</p>
<p>&nbsp;&nbsp; 如 L"我的字符串"&nbsp;&nbsp; 表示将ANSI字符串转换成unicode的字符串，就是每个字符占用两个字节。</p>
<p>strlen("asd") =&nbsp;&nbsp; 3;</p>
<p>strlen(L"asd") =&nbsp;&nbsp; 6;</p>
<p>&nbsp;&nbsp; 二、&nbsp;&nbsp; _T宏可以把一个引号引起来的字符串，根据你的环境设置，使得编译器会根据编译目标环境选择合适的（Unicode还是ANSI）字符处理方式</p>
<p>&nbsp;&nbsp; 如果你定义了UNICODE，那么_T宏会把字符串前面加一个L。这时 _T("ABCD") 相当于 L"ABCD" ，这是宽字符串。</p>
<p>&nbsp;&nbsp; 如果没有定义，那么_T宏不会在字符串前面加那个L，_T("ABCD") 就等价于 "ABCD"</p>
<p>三、TEXT,_TEXT 和_T 一样的</p>
<p>如下面三语句：</p>
<p>TCHAR szStr1[] = TEXT("str1");</p>
<p>char szStr2[] = "str2";</p>
<p>WCHAR szStr3[] = L("str3");</p>
<p>那么第一句话在定义了UNICODE时会解释为第三句话，没有定义时就等于第二句话。&nbsp;&nbsp;</p>
<p>但二句话无论是否定义了UNICODE都是生成一个ANSI字符串，而第三句话总是生成UNICODE字符串。</p>
<p>为了程序的可移植性，建议都用第一种表示方法。</p>
<p>但在某些情况下，某个字符必须为ANSI或UNICODE，那就用后两种方法<br><br></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char :单字节变量类型，最多表示256个字符</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wchar_t :宽字节变量类型，用于表示Unicode字符</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;它实际定义在&lt;string.h&gt;里：typedef unsigned short wchar_t。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;为了让编译器识别Unicode字符串，必须以在前面加一个&#8220;L&#8221;,定义宽字节类型方法如下：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; wchar_t c = `A' ;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wchar_t * p = L"Hello!" ;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wchar_t a[] = L"Hello!" ; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;其中，宽字节类型每个变量占用2个字节，故上述数组a的sizeof(a) = 14</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TCHAR / _T( ) :&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果在程序中既包括ANSI又包括Unicode编码，需要包括头文件tchar.h。TCHAR是定义在该头文件中的宏，它视你是否定义了&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp; NICODE宏而定义成： <br>定义了_UNICODE：&nbsp;&nbsp;&nbsp; typedef wchar_t TCHAR ; <br>没有定义_UNICODE： typedef char TCHAR ; </p>
<p>#ifdef UNICODE <br>typedef char TCHAR; <br>#else <br>typede wchar_t TCHAR; <br>#endif <br>_T( )也是定义在该头文件中的宏，视是否定义了_UNICODE宏而定义成： <br>定义了_UNICODE：&nbsp;&nbsp;&nbsp; #define _T(x) L##x <br>没有定义_UNICODE： #define _T(x) x <br>注意：如果在程序中使用了TCHAR，那么就不应该使用ANSI的strXXX函数或者Unicode的wcsXXX函数了，而必须使用tchar.h中定义的_tcsXXX函数。</p>
<p>以strcpy函数为例子，总结一下：<br>&nbsp;</p>
<div><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">//如果你想使用ANSI字符串，那么请使用这一套写法：&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">char&nbsp;szString[100];&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">strcpy(szString,"test");&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">//如果你想使用Unicode字符串，那么请使用这一套：&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">wchar_t&nbsp;szString[100];&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">wcscpy(szString,L"test");&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">//如果你想通过定义_UNICODE宏，而编译ANSI或者Unicode字符串代码：&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">TCHAR&nbsp;szString[100];&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">_tcscpy(szString,_TEXT("test"));</div>
<p>&nbsp;<br><font size=2>char是C语言标准数据类型，字符型，至于由几个字节组成通常由编译器决定，一般一个字节。Windows为了消除各 编译器的差别，重新定义了一些数据类型，你提到了另外几个类型都是这样。<br>CHAR为单字节字符。<br>还有个WCHAR为Unicode字符，即不论中英文，每 个字有两个字节组成。<br>如果当前编译方式为ANSI(默认)方式，TCHAR等价于CHAR，<br>如果为Unicode方式，TCHAR等价于WCHAR。<br>在当 前版本LPCSTR和LPSTR没区别，即以零结尾的字符串指针，相当于CHAR *。<br></font></p>
<p style="COLOR: red"><br></p>
<p>char :单字节变量类型，最多表示256个字符，</p>
<p>wchar_t :宽字节变量类型，用于表示Unicode字符，</p>
<p>它实际定义在&lt;string.h&gt;里：typedef unsigned short wchar_t。</p>
<p>为了让编译器识别Unicode字符串，必须以在前面加一个&#8220;L&#8221;,定义宽字节类型方法如下：</p>
<p>&nbsp;&nbsp;&nbsp; wchar_t c = `A' ; <br>wchar_t * p = L"Hello!" ; <br>wchar_t a[] = L"Hello!" ; </p>
<p>其中，宽字节类型每个变量占用2个字节，故上述数组a的sizeof(a) = 14</p>
<p>TCHAR / _T( ) : <br>如果在程序中既包括ANSI又包括Unicode编码，需要包括头文件tchar.h。TCHAR是定义在该头文件中的宏，它视你是否定义了_UNICODE宏而定义成： <br>定义了_UNICODE：&nbsp;&nbsp;&nbsp; typedef wchar_t TCHAR ; <br>没有定义_UNICODE： typedef char TCHAR ; </p>
<p>#ifdef UNICODE <br>typedef char TCHAR; <br>#else <br>typede wchar_t TCHAR; <br>#endif <br>_T( )也是定义在该头文件中的宏，视是否定义了_UNICODE宏而定义成： <br>定义了_UNICODE：&nbsp;&nbsp;&nbsp; #define _T(x) L##x <br>没有定义_UNICODE： #define _T(x) x <br>注意：如果在程序中使用了TCHAR，那么就不应该使用ANSI的strXXX函数或者Unicode的wcsXXX函数了，而必须使用tchar.h中定义的_tcsXXX函数。</p>
<p>以strcpy函数为例子，总结一下：<br>&nbsp;</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">如果你想使用ANSI字符串，那么请使用这一套写法：&nbsp;</span><span style="COLOR: #008000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;szString[</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">];&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">strcpy(szString,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">如果你想使用Unicode字符串，那么请使用这一套：&nbsp;</span><span style="COLOR: #008000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #000000">wchar_t&nbsp;szString[</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">];&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">wcscpy(szString,L</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">如果你想通过定义_UNICODE宏，而编译ANSI或者Unicode字符串代码：&nbsp;</span><span style="COLOR: #008000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #000000">TCHAR&nbsp;szString[</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">];&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">_tcscpy(szString,_TEXT(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">));</span></div>
<p>&nbsp;</p>
<p>CSDN:superarhow说： 不要再使用TCHAR和_T了！他分析了原因后总结：如 果您正开始一个新的项目，请无论如何也要顶住压力，直接使用UNICODE编码！切记！您只需要对您的组员进行10分钟的培训，记住strcpy用 wcscpy，sprintf用swprintf代替，常数前加L，就可以了！它不会花您很多时间的，带给您的是稳定和安全！相信偶，没错的！！</p>
<p>一、 在字符串前加一个L作用: <br>&nbsp;&nbsp; 如&nbsp; L"我的字符串"&nbsp;&nbsp;&nbsp; 表示将ANSI字符串转换成unicode的字符串，就是每个字符占用两个字节。 <br>&nbsp; strlen("asd")&nbsp;&nbsp; =&nbsp;&nbsp; 3;&nbsp;&nbsp; <br>&nbsp; strlen(L"asd")&nbsp;&nbsp; =&nbsp;&nbsp; 6; <br>&nbsp; 二、&nbsp; _T宏可以把一个引号引起来的字符串，根据你的环境设置，使得编译器会根据编译目标环境选择合适的（Unicode还是ANSI）字符处理方式 <br>&nbsp;&nbsp; 如果你定义了UNICODE，那么_T宏会把字符串前面加一个L。这时 _T("ABCD") 相当于 L"ABCD" ，这是宽字符串。 <br>&nbsp;&nbsp; 如果没有定义，那么_T宏不会在字符串前面加那个L，_T("ABCD") 就等价于 "ABCD" <br>三、TEXT,_TEXT 和_T 一样的 <br>如下面三语句：&nbsp;&nbsp; <br>&nbsp; TCHAR&nbsp;&nbsp; szStr1[]&nbsp;&nbsp; =&nbsp;&nbsp; TEXT("str1");&nbsp;&nbsp; <br>&nbsp; char&nbsp;&nbsp; szStr2[]&nbsp;&nbsp; =&nbsp;&nbsp; "str2";&nbsp;&nbsp; <br>&nbsp; WCHAR&nbsp;&nbsp; szStr3[]&nbsp;&nbsp; =&nbsp;&nbsp; L("str3");&nbsp;&nbsp; <br>&nbsp; 那么第一句话在定义了UNICODE时会解释为第三句话，没有定义时就等于第二句话。&nbsp;&nbsp; <br>&nbsp; 但二句话无论是否定义了UNICODE都是生成一个ANSI字符串，而第三句话总是生成UNICODE字符串。&nbsp;&nbsp; <br>&nbsp; 为了程序的可移植性，建议都用第一种表示方法。&nbsp;&nbsp; <br>&nbsp; 但在某些情况下，某个字符必须为ANSI或UNICODE，那就用后两种方法。</p>
<p style="COLOR: red">CSDN:superarhow说： 不要再使用TCHAR和_T了！他分析了原因后总结：如 果您正开始一个新的项目，请无论如何也要顶住压力，直接使用UNICODE编码！切记！您只需要对您的组员进行10分钟的培训，记住strcpy用 wcscpy，sprintf用swprintf代替，常数前加L，就可以了！它不会花您很多时间的，带给您的是稳定和安全！相信偶，没错的！！</p>
<img src ="http://www.cppblog.com/tdweng/aggbug/124436.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-08-23 16:46 <a href="http://www.cppblog.com/tdweng/articles/124436.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>#ifndef#define#endif的用法(整理) (转发)</title><link>http://www.cppblog.com/tdweng/articles/124387.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Mon, 23 Aug 2010 02:47:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/124387.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/124387.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/124387.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/124387.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/124387.html</trackback:ping><description><![CDATA[<div class=postText>
<div class=title>[转]&nbsp;#ifndef#define#endif的用法(整理)&nbsp;&nbsp;&nbsp; 原<span class=addtime>作者：icwk&nbsp; </div>
<div class=logtxt>
<p><span class=oblog_text>文件中的#ifndef
<p>头件的中的#ifndef，这是一个很关键的东西。比如你有两个C文件，这两个C文件都include了同一个头文件。而编译时，这两个C文件要一同编译成一个可运行文件，于是问题来了，大量的声明冲突。 </p>
<p>还是把头文件的内容都放在#ifndef和#endif中吧。不管你的头文件会不会被多个文件引用，你都要加上这个。一般格式是这样的： </p>
<p>#ifndef &lt;标识&gt; <br>#define &lt;标识&gt; </p>
<p>...... <br>...... </p>
<p>#endif </p>
<p>&lt;标识&gt;在理论上来说可以是自由命名的，但每个头文件的这个&#8220;标识&#8221;都应该是唯一的。标识的命名规则一般是头文件名全大写，前后加下划线，并把文件名中的&#8220;.&#8221;也变成下划线，如：stdio.h </p>
<p>#ifndef _STDIO_H_ <br>#define _STDIO_H_ </p>
<p>...... </p>
<p>#endif </p>
<p>2.在#ifndef中定义变量出现的问题（一般不定义在#ifndef中）。</p>
<p>#ifndef AAA<br>#define AAA<br>...<br>int i;<br>...<br>#endif<br>里面有一个变量定义<br>在vc中链接时就出现了i重复定义的错误，而在c中成功编译。</p>
<p>结论：</p>
<p>(1).当你第一个使用这个头的.cpp文件生成.obj的时候，int i 在里面定义了当另外一个使用这个的.cpp再次[单独]生成.obj的时候，int i 又被定义然后两个obj被另外一个.cpp也include 这个头的，连接在一起，就会出现重复定义.</p>
<p>(2).把源程序文件扩展名改成.c后，VC按照C语言的语法对源程序进行编译，而不是C++。在C语言中，若是遇到多个int i，则自动认为其中一个是定义，其他的是声明。</p>
<p>(3).C语言和C++语言连接结果不同，可能（猜测）时在进行编译的时候，C++语言将全局<br>变量默认为强符号，所以连接出错。C语言则依照是否初始化进行强弱的判断的。（参考）</p>
<p>解决方法：</p>
<p>(1).把源程序文件扩展名改成.c。</p>
<p>(2).推荐解决方案：<br>.h中只声明 extern int i;在.cpp中定义</p>
<p>&lt;x.h&gt;<br>#ifndef __X_H__<br>#define __X_H__<br>extern int i;<br>#endif //__X_H__<br>&lt;x.c&gt;<br>int i;</p>
<p>注意问题：</p>
<p>(1).变量一般不要定义在.h文件中。</p>
<p>&nbsp;</p>
<p>-------------------------------------------------------------------------------------------------------------------------------------------</p>
<p>一般情况下，源程序中所有的行都参加编译。但是有时希望对其中一部分内容只在满足一定条件才进行编译，也就是对一部分内容指定编译的条件，这就是&#8220;条件编译&#8221;。有时，希望当满足某条件时对一组语句进行编译，而当条件不满足时则编译另一组语句。 <br>条件编译命令最常见的形式为： <br>&nbsp;&nbsp;&nbsp; #ifdef 标识符 <br>&nbsp;&nbsp;&nbsp; 程序段1 <br>&nbsp;&nbsp;&nbsp; #else <br>&nbsp;&nbsp;&nbsp; 程序段2 <br>&nbsp;&nbsp;&nbsp; #endif <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 它的作用是：当标识符已经被定义过(一般是用#define命令定义)，则对程序段1进行编译，否则编译程序段2。 <br>&nbsp;&nbsp;&nbsp; 其中#else部分也可以没有，即： <br>&nbsp;&nbsp;&nbsp; #ifdef <br>&nbsp;&nbsp;&nbsp; 程序段1 <br>&nbsp;&nbsp;&nbsp; #denif <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 这里的&#8220;程序段&#8221;可以是语句组，也可以是命令行。这种条件编译可以提高C源程序的通用性。如果一个C源程序在不同计算机系统上系统上运行，而不同的计算机又有一定的差异。例如，我们有一个数据类型，在Windows平台中，应该使用long类型表示，而在其他平台应该使用float表示，这样往往需要对源程序作必要的修改，这就降低了程序的通用性。可以用以下的条件编译： <br>&nbsp;&nbsp;&nbsp; #ifdef WINDOWS <br>&nbsp;&nbsp;&nbsp; #define MYTYPE long <br>&nbsp;&nbsp;&nbsp; #else <br>&nbsp;&nbsp;&nbsp; #define MYTYPE float <br>&nbsp;&nbsp;&nbsp; #endif <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 如果在Windows上编译程序，则可以在程序的开始加上 <br>&nbsp;&nbsp;&nbsp; #define WINDOWS <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 这样则编译下面的命令行： <br>&nbsp;&nbsp;&nbsp; #define MYTYPE long <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 如果在这组条件编译命令之前曾出现以下命令行： <br>&nbsp;&nbsp;&nbsp; #define WINDOWS 0 <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 则预编译后程序中的MYTYPE都用float代替。这样，源程序可以不必作任何修改就可以用于不同类型的计算机系统。当然以上介绍的只是一种简单的情况，可以根据此思路设计出其它的条件编译。 <br>&nbsp;&nbsp;&nbsp; 例如，在调试程序时，常常希望输出一些所需的信息，而在调试完成后不再输出这些信息。可以在源程序中插入以下的条件编译段： <br>&nbsp;&nbsp;&nbsp; #ifdef DEBUG <br>&nbsp;&nbsp;&nbsp; print ("device_open(%p) ", file); <br>&nbsp;&nbsp;&nbsp; #endif <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 如果在它的前面有以下命令行： <br>&nbsp;&nbsp;&nbsp; #define DEBUG <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 则在程序运行时输出file指针的值，以便调试分析。调试完成后只需将这个define命令行删除即可。有人可能觉得不用条件编译也可达此目的，即在调试时加一批printf语句，调试后一一将printf语句删除去。的确，这是可以的。但是，当调试时加的printf语句比较多时，修改的工作量是很大的。用条件编译，则不必一一删改printf语句，只需删除前面的一条&#8220;#define DEBUG&#8221;命令即可，这时所有的用DEBUG作标识符的条件编译段都使其中的printf语句不起作用，即起统一控制的作用，如同一个&#8220;开关&#8221;一样。 <br>&nbsp;&nbsp;&nbsp; 有时也采用下面的形式： <br>&nbsp;&nbsp;&nbsp; #ifndef 标识符 <br>&nbsp;&nbsp;&nbsp; 程序段1 <br>&nbsp;&nbsp;&nbsp; #else <br>&nbsp;&nbsp;&nbsp; 程序段2 <br>&nbsp;&nbsp;&nbsp; #endif <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 只是第一行与第一种形式不同：将&#8220;ifdef&#8221;改为&#8220;ifndef&#8221;。它的作用是：若标识符未被定义则编译程序段1，否则编译程序段2。这种形式与第一种形式的作用相反。 <br>&nbsp;&nbsp;&nbsp; 以上两种形式用法差不多，根据需要任选一种，视方便而定。 <br>&nbsp;&nbsp;&nbsp; 还有一种形式，就是#if后面的是一个表达式，而不是一个简单的标识符： <br>&nbsp;&nbsp;&nbsp; #if 表达式 <br>&nbsp;&nbsp;&nbsp; 程序段1 <br>&nbsp;&nbsp;&nbsp; #else <br>&nbsp;&nbsp;&nbsp; 程序段2 <br>&nbsp;&nbsp;&nbsp; #endif <br>&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 它的作用是：当指定的表达式值为真（非零）时就编译程序段1，否则编译程序段2。可以事先给定一定条件，使程序在不同的条件下执行不同的功能。</p>
<p>---------------------------------------------------------------------------------------------------------------------------------------</p>
<p>作用范围就是当前文件啊。因为编译是以cpp或c文件位单位的嘛。还以这个为例：<br><br>//正常代码<br>#ifdef _DEBUG<br>&nbsp;&nbsp;&nbsp;&nbsp; TRACE("Some infomation");<br>#else<br>&nbsp;&nbsp;&nbsp;&nbsp; //Now is release version,so do nothing<br>#endif<br>//正常代码<br><br>编译时是先把所有的预编译处理展开（比如宏）再编译，所以Debug模式下，编译时的代码是：<br>//正常代码<br>TRACE("Some infomation");<br>//正常代码<br><br>Release模式下的代码是：<br>//正常代码<br>//正常代码<br></p>
为了避免同一个文件被include多次<br><br>1&nbsp;&nbsp; <span style="COLOR: #ff0000">#ifndef方式</span><br>2&nbsp;&nbsp;<span style="COLOR: #ff0000"> #pragma once方式<br></span><br>在能够支持这两种方式的编译器上，二者并没有太大的区别，但是两者仍然还是有一些细微的区别。<br>&nbsp;&nbsp;&nbsp; <span style="COLOR: #008000">方式一：</span>
<p>&nbsp;&nbsp;&nbsp; #ifndef __SOMEFILE_H__<br>&nbsp;&nbsp;&nbsp; #define __SOMEFILE_H__<br>&nbsp;&nbsp;&nbsp; ... ... // 一些声明语句<br>&nbsp;&nbsp;&nbsp; #endif</p>
<p>&nbsp;&nbsp;&nbsp; <span style="COLOR: #008000">方式二：</span></p>
<p>&nbsp;&nbsp;&nbsp; #pragma once<br>&nbsp;&nbsp;&nbsp; ... ... // 一些声明语句</p>
<p><br>&nbsp;&nbsp;&nbsp; #ifndef的方式依赖于宏名字不能冲突，这不光可以保证同一个文件不会被包含多次，也能保证内容完全相同的两个文件不会被不小心同时包含。当然，缺点就是如果不同头文件的宏名不小心&#8220;撞车&#8221;，可能就会导致头文件明明存在，编译器却硬说找不到声明的状况<br><br>&nbsp;&nbsp;&nbsp; #pragma once则由编译器提供保证：同一个文件不会被包含多次。注意这里所说的&#8220;同一个文件&#8221;是指物理上的一个文件，而不是指内容相同的两个文件。带来的好处是，你不必再费劲想个宏名了，当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝，本方法不能保证他们不被重复包含。当然，相比宏名碰撞引发的&#8220;找不到声明&#8221;的问题，重复包含更容易被发现并修正。<br><br>&nbsp;&nbsp; 方式一由语言支持所以移植性好，方式二 可以避免名字冲突</p>
</span></div>
</span></div>
<img src ="http://www.cppblog.com/tdweng/aggbug/124387.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-08-23 10:47 <a href="http://www.cppblog.com/tdweng/articles/124387.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++中const用法总结(转发)</title><link>http://www.cppblog.com/tdweng/articles/124385.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Mon, 23 Aug 2010 02:42:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/124385.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/124385.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/124385.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/124385.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/124385.html</trackback:ping><description><![CDATA[<p>作者JuKevin
<p>1. const修饰普通变量和指针</p>
<p>const修饰变量，一般有两种写法：
<p>const TYPE value;
<p>TYPE const value;
<p>这两种写法在本质上是一样的。它的含义是：const修饰的类型为TYPE的变量value是不可变的。
<p>对于一个非指针的类型TYPE，无论怎么写，都是一个含义，即value只不可变。
<p>例如：
<p>const int nValue； &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //nValue是const
<p align=left>int const nValue；&nbsp;&nbsp;&nbsp; // nValue是const
<p>但是对于指针类型的TYPE，不同的写法会有不同情况，例如：
<p>A. const char *pContent;
<p>B. char * const pContent;
<p>C. char const *pContent;
<p>D. const char* const pContent;
<p>&nbsp;
<p>对于前三种写法，我们可以换个方式，给其加上括号
<p>A. const (char) *pContent;
<p>B. (char*) const pContent;
<p>C. (char) const *pContent;
<p>这样就一目了然。根据对于const修饰非指针变量的规则，很明显，A=C.
<p>&nbsp;
<p>- 对于A,C, const修饰的类型为char的变量*pContent为常量，因此，pContent的内容为常量不可变.
<p>- 对于B, const修饰的类型为char*的变量pContent为常量，因此，pContent指针本身为常量不可变.
<p>- 对于D, 其实是A和B的混合体，表示指针本身和指针内容两者皆为常量不可变
<p>&nbsp;
<p>总结:
<p>(1)&nbsp; 指针本身是常量不可变
<p>(char*) const pContent;
<p>&nbsp;
<p>(2)&nbsp; 指针所指向的内容是常量不可变
<p>const (char) *pContent;
<p>(char) const *pContent;
<p>&nbsp;
<p>(3)&nbsp; 两者都不可变
<p>const char* const pContent;
<p>&nbsp;
<p>还有其中区别方法：
<p style="COLOR: red">沿着*号划一条线，
<p style="COLOR: red">如果const位于*的左侧，则const就是用来修饰指针所指向的内容变量，即指针指向为常量（物常量）；
<p><span style="COLOR: red">如果const位于*的右侧，const就是修饰指针本身，即指针本身是常量（指针常量）。</span> <br><br>小例子：<br>char ch[5] = "lisi";<br>const char* pStr = ch;<br>*pStr = 'w';&nbsp; //error，物常量，不可更改内容<br>pStr ="wangwu"; //OK，物常量，可更改指针<br><br>cha ch[5] = "lisi";<br>char * const pStr = "lisi";<br>pStr = "zhangsan"; //error，指针常量，不可更改指针<br>*pStr = "w"; //OK ，指针常量，可更改内容
<p>2. const修饰函数参数</p>
<p>const修饰函数参数是它最广泛的一种用途，它表示函数体中不能修改参数的值(包括参数本身的值或者参数其中包含的值)。它可以很好 <br>
<p>void function(const int Var); //传递过来的参数在函数内不可以改变(无意义，因为Var本身就是形参)
<p>void function(const char* Var); //参数指针所指内容为常量不可变
<p>void function(char* const Var); //参数指针本身为常量不可变(也无意义， 因为char* Var也是形参)
<p>&nbsp;
<p>参数为引用，为了增加效率同时防止修改。
<p>修饰引用参数时：
<p>void function(const Class&amp; Var);//引用参数在函数内不可以改变
<p>void function(const TYPE&amp; Var); //引用参数在函数内为常量不可变
<p>&nbsp;
<p>3. const 修饰函数返回值</p>
<p>const修饰函数返回值其实用的并不是很多，它的含义和const修饰普通变量以及指针的含义基本相同。
<p>(1) const int fun1() 这个其实无意义，因为参数返回本身就是赋值。
<p>(2) const int * fun2()
<p>调用时 const int *pValue = fun2();
<p>我们可以把fun2()看作成一个变量，那么就是我们上面所说的1.(1)的写法，即指针内容不可变。
<p>(3) int* const fun3()
<p>调用时 int * const pValue = fun2();
<p>我们可以把fun2()看作成一个变量，那么就是我们上面所说的1.(2)的写法，即指针本身不可变。
<p>4. const修饰类对象/对象指针/对象引用</p>
<p>const修饰类对象表示该对象为常量对象，其中的任何成员都不能被修改。对于对象指针和对象引用也是一样。
<p>const修饰的对象，该对象的任何非const成员函数都不能被调用，因为任何非const成员函数会有修改成员变量的企图。
<p>例如：
<p>class AAA
<p>{<br>&nbsp;&nbsp; void func1();
<p>void func2() const;
<p>}
<p>const AAA aObj;
<p>aObj.func1(); &#215;
<p>aObj.func2(); 正确
<p>&nbsp;
<p>const AAA* aObj = new AAA();
<p>aObj-&gt;func1(); &#215;
<p>aObj-&gt;func2(); 正确
<p>&nbsp;
<p>5. const修饰成员变量</p>
<p>const修饰类的成员函数，表示成员常量，不能被修改，同时它只能在初始化列表中赋值。
<p>&nbsp;
<p>class A
<p>{
<p>&nbsp;&nbsp; &#8230;
<p>&nbsp;&nbsp; const int nValue;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //成员常量不能被修改
<p>&nbsp;&nbsp; &#8230;
<p>&nbsp;&nbsp; A(int x): nValue(x) {}; //只能在初始化列表中赋值
<p>}
<p>&nbsp;
<p>6. const修饰成员函数</p>
<p>const修饰类的成员函数，则该成员函数不能修改类中任何非const成员函数。一般写在函数的最后来修饰。
<p>&nbsp;
<p>class A
<p>{
<p>&nbsp;&nbsp; &#8230;
<p>void function()const; //常成员函数, 它不改变对象的成员变量. 也不能调用类中任何非const成员函数。
<p>}
<p>对于const类对象/指针/引用，只能调用类的const成员函数，因此，const修饰成员函数的最重要作用就是限制对于const对象的使用。
<p>&nbsp;
<p>7. const常量与define宏定义的区别</p>
<p>(1) 编译器处理方式不同
<p>define宏是在预处理阶段展开。
<p>const常量是编译运行阶段使用。
<p>(2) 类型和安全检查不同
<p>define宏没有类型，不做任何类型检查，仅仅是展开。
<p>const常量有具体的类型，在编译阶段会执行类型检查。
<p>(3) 存储方式不同
<p>define宏仅仅是展开，有多少地方使用，就展开多少次，不会分配内存。
<p>const常量会在内存中分配(可以是堆中也可以是栈中)。</p>
<img src ="http://www.cppblog.com/tdweng/aggbug/124385.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-08-23 10:42 <a href="http://www.cppblog.com/tdweng/articles/124385.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ extern小例子</title><link>http://www.cppblog.com/tdweng/articles/124375.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Mon, 23 Aug 2010 02:17:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/124375.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/124375.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/124375.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/124375.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/124375.html</trackback:ping><description><![CDATA[<span style="COLOR: red">用例子给你示范 <br>// 1.cpp <br>int x = 10; <br>// 2.cpp 注意没有包含1.cpp <br>#include &lt;iostream&gt; <br>using namespace std; <br>extern int x;<br>int main () <br>{ cout &lt;&lt; x &lt;&lt; endl; } <br>//则输出10 <br>两个文件同在一个项目（project）中，你不包含某个文件（cpp）而可以用它内部定义的变量，(这里是.cpp不是.h, 因为在.h中定义的数据不能在.cpp中用除非这个.cpp包含这个.h文件）</span> <br>例： <br>// 1.h <br>#include &lt;iostream&gt; <br>void print() <br>{ <br>std::cout &lt;&lt; "hello!" &lt;&lt; std::endl; <br>} <br>// 2.cpp <br>#include &lt;iostream&gt; <br>using namespace std; <br>// 以上两句在这个例子中可以不要 <br>extern void print(); <br>int main () <br>{ <br>print(); <br>} <br>就会出错因为1.h中的void print()；在不包含它的文件中是不可调用的，即使在声明了extern 也于事无补，如果你将这个例子中的1.h名字换成1.cpp就对了！ <br><span style="COLOR: red">从这些可以看出来，extern在这里起的作用是告诉编译器，你这个print()已经在某个.cpp中已经定义了，这里只不过是声明一下有这个东西，然后拿来用一下。定义只能出现一次，声明却可出现多次，也就是说extern声明可在多个文件中用（包括.h) <br>还有，你还可以屏蔽extern声明，如第二个例子中的第二个.cpp文件可以改成 <br></span>#include &lt;iostream&gt; <br>using namespace std; <br>// 这里以上两句不能省略，因为，这里extern void print();函数已经不起作用了，在这里调用的而是本文件中定义的void print()函数，其中用到了cout,endl;他们来源于std::&lt;iostream&gt; <br>extern void print(); <br>void print() <br>{ <br>cout &lt;&lt; "world!" &lt;&lt; endl; <br>} <br><br>int main () <br>{ <br>print(); <br>} <br>// 输出结果为world! <br>还有一个extern "C"就不用说了，用这个可以允许C++程序中调用C的函数！ 
<img src ="http://www.cppblog.com/tdweng/aggbug/124375.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-08-23 10:17 <a href="http://www.cppblog.com/tdweng/articles/124375.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C/C++/VC随机数总结</title><link>http://www.cppblog.com/tdweng/articles/114159.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Sun, 02 May 2010 03:10:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/114159.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/114159.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/114159.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/114159.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/114159.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<p>大家都知道C语言中的随机函数random，可是random函数并不是ANSI C标准，所以说，random函数不能在gcc,vc等编译器下编<br>译通过。那么怎么实现VC语言中的随机函数呢？</p>
<p>其实，除了random函数，还有一个rand函数，这个函数也是一个随机函数，他可以产生从0到rand_max(32767)的随机数。</p>
<p>&nbsp;</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">#include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdlib.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_49_116_Open_Image onclick="this.style.display='none'; Codehighlighter1_49_116_Open_Text.style.display='none'; Codehighlighter1_49_116_Closed_Image.style.display='inline'; Codehighlighter1_49_116_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_49_116_Closed_Image onclick="this.style.display='none'; Codehighlighter1_49_116_Closed_Text.style.display='none'; Codehighlighter1_49_116_Open_Image.style.display='inline'; Codehighlighter1_49_116_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_49_116_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_49_116_Open_Text><span style="COLOR: #000000">{&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;k;&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;k&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;rand();<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%d\\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;k);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">main</span><span style="COLOR: #008000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span></div>
<p>大家可以把以上的代码编译运行一下，发现他的确产生随机数了，但是你会发现，每次运行程序产生的随机数都是一样的，不过你在程序里加上for循环，每次产生的数不一样，但是，如果再运行这个程序，它产生的数据却都是相同的。</p>
<p>那么如何写一个程序，让它每次运行时产生的随机数都不一样呢？ 请看下面的例子：<br></p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdlib.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">time.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_112_291_Open_Image onclick="this.style.display='none'; Codehighlighter1_112_291_Open_Text.style.display='none'; Codehighlighter1_112_291_Closed_Image.style.display='inline'; Codehighlighter1_112_291_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_112_291_Closed_Image onclick="this.style.display='none'; Codehighlighter1_112_291_Closed_Text.style.display='none'; Codehighlighter1_112_291_Open_Image.style.display='inline'; Codehighlighter1_112_291_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_112_291_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_112_291_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;time_t&nbsp;t;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;srand((unsigned)&nbsp;time(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">t));<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Ten&nbsp;random&nbsp;numbers&nbsp;from&nbsp;0&nbsp;to&nbsp;99\n\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">%d\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;rand()&nbsp;</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span></div>
<p>这时运行程序，会发现每次产生的随机数都不一样。</p>
<p>那么为什么第一个程序一样而第二个程序一样呢？</p>
<p>第二个程序用到了一个新的函数srand</p>
<p>这个函数是给随机数产生一个随机种子(seed)，函数原型是srand( (unsigned)time( NULL ) );</p>
<p><br>time的值每时每刻都不同。所以种子不同，所以，产生的随机数也不同。</p>
<p>所以说，要想产生不同的随机数，在使用rand之前需要先调用srand</p>
<p>srand和rand函数都包含在stdlib.h的头文件里。</p>
<p>由于rand产生的随机数是从0到rand_max的，而rand_max（32767）是一个很大的数，那么如何产生从X~Y的数呢？</p>
<p>从X到Y，有Y－X＋1个数，所以要产生从X到Y的数，只需要这样写：</p>
<p>k = rand() % (Y - X + 1) +X;</p>
<p>这样，就可以产生你想要的任何范围内的随机数了。 <br><span style="COLOR: red">问题：如何生成K个小于Ｎ并且互不重复的整数</span><br><br>一.首先对于c++的随机函数我们要有所了解，这里就不累赘了，请读者自行google之，<br>我们要用到的有<br>1.&nbsp;void srand(unsigned int_seed)函数产生一个以当前时间开始的随机种子<br>&nbsp;&nbsp;srand(unsigned(time(NULL))),必须放在生成随机数前<br>2.int rand()函数，随机产生一整数<br>&nbsp;&nbsp; rand()%MAX 产生[0,MAX)的整数<br>&nbsp;&nbsp; a+rand()%(b-a+1) 产生[a,b]之间的整数<br>3.需要头文件#include&lt;time.h&gt;<br></p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">#include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">time.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;N&nbsp;100</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;K&nbsp;20</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;x[N];<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;swap(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;j)<br><img id=Codehighlighter1_118_163_Open_Image onclick="this.style.display='none'; Codehighlighter1_118_163_Open_Text.style.display='none'; Codehighlighter1_118_163_Closed_Image.style.display='inline'; Codehighlighter1_118_163_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_118_163_Closed_Image onclick="this.style.display='none'; Codehighlighter1_118_163_Closed_Text.style.display='none'; Codehighlighter1_118_163_Open_Image.style.display='inline'; Codehighlighter1_118_163_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_118_163_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_118_163_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;temp</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">x[i];<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;x[i]</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">x[j];<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;x[j]</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">temp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_176_363_Open_Image onclick="this.style.display='none'; Codehighlighter1_176_363_Open_Text.style.display='none'; Codehighlighter1_176_363_Closed_Image.style.display='inline'; Codehighlighter1_176_363_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_176_363_Closed_Image onclick="this.style.display='none'; Codehighlighter1_176_363_Closed_Text.style.display='none'; Codehighlighter1_176_363_Open_Image.style.display='inline'; Codehighlighter1_176_363_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_176_363_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_176_363_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">N;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x[i]</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">i;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;srand(unsigned(time(NULL)));<br><img id=Codehighlighter1_279_342_Open_Image onclick="this.style.display='none'; Codehighlighter1_279_342_Open_Text.style.display='none'; Codehighlighter1_279_342_Closed_Image.style.display='inline'; Codehighlighter1_279_342_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_279_342_Closed_Image onclick="this.style.display='none'; Codehighlighter1_279_342_Closed_Text.style.display='none'; Codehighlighter1_279_342_Open_Image.style.display='inline'; Codehighlighter1_279_342_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">K;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_279_342_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_279_342_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;swap(i,i</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">rand()</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">(N</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">i));<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">x[i]</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span></div>
<p><br>二.考虑如何让数据不重复&nbsp;<br>&nbsp; 看代码吧。。学习下方法<br><font size=5>首先搞个一绝没有重复数据的数组，就是x[i]=i;<br>此时注意那个swap函数，每次生成的随机数作为数组下标去取数，然后交换，这就保证了x这个数组绝不会有重复的数出现。<br>绝了！！</font><br></p>
<img src ="http://www.cppblog.com/tdweng/aggbug/114159.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-05-02 11:10 <a href="http://www.cppblog.com/tdweng/articles/114159.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C语言全总字符串函数 </title><link>http://www.cppblog.com/tdweng/articles/113484.html</link><dc:creator>心羽</dc:creator><author>心羽</author><pubDate>Sat, 24 Apr 2010 18:07:00 GMT</pubDate><guid>http://www.cppblog.com/tdweng/articles/113484.html</guid><wfw:comment>http://www.cppblog.com/tdweng/comments/113484.html</wfw:comment><comments>http://www.cppblog.com/tdweng/articles/113484.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tdweng/comments/commentRss/113484.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tdweng/services/trackbacks/113484.html</trackback:ping><description><![CDATA[~对初学者属于深入理解吧，高手请勿在此浪费宝贵时间~<br><br>看到这样一个改错题：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;p[</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">];&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;s</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">12345</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">strcpy(p,s);<br>&nbsp;&nbsp;&nbsp;cout &lt;&lt; p &lt;&lt; endl;</span></div>
错误之处是很显然的，作为字符串字面值的"12345"会在结尾处自动加上空字符null，从而长度是6，上面的strcpy是会越界的，从而是个越界错误。<br>问题是我以为这样的程序编译的时候会出错呢!但是我在vc上运行时是可以输出正确结果的，这让我很是纳闷！后来找到了strcpy的源代码才知原因，strcpy函数是不进行越界处理的. 又因为strcpy连null一起复制，从而p能输出正确的结果"12345"
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img id=Codehighlighter1_0_281_Open_Image onclick="this.style.display='none'; Codehighlighter1_0_281_Open_Text.style.display='none'; Codehighlighter1_0_281_Closed_Image.style.display='inline'; Codehighlighter1_0_281_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_0_281_Closed_Image onclick="this.style.display='none'; Codehighlighter1_0_281_Closed_Text.style.display='none'; Codehighlighter1_0_281_Open_Image.style.display='inline'; Codehighlighter1_0_281_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_0_281_Closed_Text>/**/</span><span id=Codehighlighter1_0_281_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">The&nbsp;strcpy&nbsp;function&nbsp;copies&nbsp;strSource,&nbsp;including&nbsp;the&nbsp;terminating&nbsp;null&nbsp;character,&nbsp;to&nbsp;the&nbsp;location&nbsp;specified&nbsp;by&nbsp;strDestination.&nbsp;No&nbsp;overflow&nbsp;checking&nbsp;is&nbsp;performed&nbsp;when&nbsp;strings&nbsp;are&nbsp;copied&nbsp;or&nbsp;appended.&nbsp;The&nbsp;behavior&nbsp;of&nbsp;strcpy&nbsp;is&nbsp;undefined&nbsp;if&nbsp;the&nbsp;source&nbsp;and&nbsp;destination&nbsp;strings&nbsp;overlap.</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;__cdecl&nbsp;strcpy(</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;dst,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;src)&nbsp;<br><img id=Codehighlighter1_336_427_Open_Image onclick="this.style.display='none'; Codehighlighter1_336_427_Open_Text.style.display='none'; Codehighlighter1_336_427_Closed_Image.style.display='inline'; Codehighlighter1_336_427_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_336_427_Closed_Image onclick="this.style.display='none'; Codehighlighter1_336_427_Closed_Text.style.display='none'; Codehighlighter1_336_427_Open_Image.style.display='inline'; Codehighlighter1_336_427_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_336_427_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_336_427_Open_Text><span style="COLOR: #000000">{&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;cp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dst;&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">(&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">cp</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">src</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">&nbsp;)&nbsp;<br><img id=Codehighlighter1_385_407_Open_Image onclick="this.style.display='none'; Codehighlighter1_385_407_Open_Text.style.display='none'; Codehighlighter1_385_407_Closed_Image.style.display='inline'; Codehighlighter1_385_407_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_385_407_Closed_Image onclick="this.style.display='none'; Codehighlighter1_385_407_Closed_Text.style.display='none'; Codehighlighter1_385_407_Open_Image.style.display='inline'; Codehighlighter1_385_407_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif">;&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_385_407_Closed_Text>/**/</span><span id=Codehighlighter1_385_407_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;Copy&nbsp;src&nbsp;over&nbsp;dst&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000">&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">(&nbsp;dst&nbsp;);&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000">&nbsp;</span></div>
貌似strcpy虽然不进行越界处理，仍然是个挺好的函数呢，但是注意了，下面的代码就能暴露出strcpy 的缺点了.<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;p[</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">];<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">s&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">12345678</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">strcpy(p,s);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;p&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">endl;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">输出12345678，而不是我们所设想的12345</span></div>
为了不因不知s的长度而犯下错误，推荐使用strncpy。但是是不是用了strncpy就万无一失了呢？看下面的代码：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;p[</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">];<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;s&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">12345</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">strncpy(p,s,</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;p&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">endl;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">12345*&amp;^(后面表示乱码)</span></div>
不是都限制个数了么？为什么后面又有乱码？<br>问题来自在上述情形strncpy是不会复制字符串s后面的null的，不是以null结束的p不会输出正确结果的。<br>仍然给出strncpy的源代码：<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img id=Codehighlighter1_0_440_Open_Image onclick="this.style.display='none'; Codehighlighter1_0_440_Open_Text.style.display='none'; Codehighlighter1_0_440_Closed_Image.style.display='inline'; Codehighlighter1_0_440_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_0_440_Closed_Image onclick="this.style.display='none'; Codehighlighter1_0_440_Closed_Text.style.display='none'; Codehighlighter1_0_440_Open_Image.style.display='inline'; Codehighlighter1_0_440_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_0_440_Closed_Text>/**/</span><span id=Codehighlighter1_0_440_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">The&nbsp;strncpy&nbsp;function&nbsp;copies&nbsp;the&nbsp;initial&nbsp;count&nbsp;characters&nbsp;of&nbsp;strSource&nbsp;to&nbsp;strDest&nbsp;and&nbsp;returns&nbsp;strDest.&nbsp;If&nbsp;count&nbsp;is&nbsp;less&nbsp;than&nbsp;or&nbsp;equal&nbsp;to&nbsp;the&nbsp;length&nbsp;of&nbsp;strSource,&nbsp;a&nbsp;null&nbsp;character&nbsp;is&nbsp;not&nbsp;appended&nbsp;automatically&nbsp;to&nbsp;the&nbsp;copied&nbsp;string.&nbsp;If&nbsp;count&nbsp;is&nbsp;greater&nbsp;than&nbsp;the&nbsp;length&nbsp;of&nbsp;strSource,&nbsp;the&nbsp;destination&nbsp;string&nbsp;is&nbsp;padded&nbsp;with&nbsp;null&nbsp;characters&nbsp;up&nbsp;to&nbsp;length&nbsp;count.&nbsp;The&nbsp;behavior&nbsp;of&nbsp;strncpy&nbsp;is&nbsp;undefined&nbsp;if&nbsp;the&nbsp;source&nbsp;and&nbsp;destination&nbsp;strings&nbsp;overlap.</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;__cdecl&nbsp;strncpy&nbsp;(&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;dest,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;source,&nbsp;size_t&nbsp;count&nbsp;)&nbsp;<br><img id=Codehighlighter1_517_701_Open_Image onclick="this.style.display='none'; Codehighlighter1_517_701_Open_Text.style.display='none'; Codehighlighter1_517_701_Closed_Image.style.display='inline'; Codehighlighter1_517_701_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_517_701_Closed_Image onclick="this.style.display='none'; Codehighlighter1_517_701_Closed_Text.style.display='none'; Codehighlighter1_517_701_Open_Image.style.display='inline'; Codehighlighter1_517_701_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_517_701_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_517_701_Open_Text><span style="COLOR: #000000">{&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">start&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;dest;&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"><br><img id=Codehighlighter1_581_597_Open_Image onclick="this.style.display='none'; Codehighlighter1_581_597_Open_Text.style.display='none'; Codehighlighter1_581_597_Closed_Image.style.display='inline'; Codehighlighter1_581_597_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_581_597_Closed_Image onclick="this.style.display='none'; Codehighlighter1_581_597_Closed_Text.style.display='none'; Codehighlighter1_581_597_Open_Image.style.display='inline'; Codehighlighter1_581_597_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif"></span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(count&nbsp;</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">dest</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">source</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">))&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_581_597_Closed_Text>/**/</span><span id=Codehighlighter1_581_597_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;copy&nbsp;string&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000">&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">count</span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">;&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"><br><img id=Codehighlighter1_622_646_Open_Image onclick="this.style.display='none'; Codehighlighter1_622_646_Open_Text.style.display='none'; Codehighlighter1_622_646_Closed_Image.style.display='inline'; Codehighlighter1_622_646_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_622_646_Closed_Image onclick="this.style.display='none'; Codehighlighter1_622_646_Closed_Text.style.display='none'; Codehighlighter1_622_646_Open_Image.style.display='inline'; Codehighlighter1_622_646_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif"></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(count)&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_622_646_Closed_Text>/**/</span><span id=Codehighlighter1_622_646_Open_Text><span style="COLOR: #008000">/*</span><span style="COLOR: #008000">&nbsp;pad&nbsp;out&nbsp;with&nbsp;zeroes&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000">&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">count)&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">dest</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">\0</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">;&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">(start);&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000">&nbsp;</span></div>
那strncpy这么不稳定，为何用它？strncpy经常用于修改一个长字符串中间的一部分（看出不复制null的原因了吧！），如果实在要用到上述的代码上，就在代码最后加上p[5] = '\0'; 吧！ <br><br><span style="COLOR: red">函数名: stpcpy <br>功&nbsp; 能: 拷贝一个字符串到另一个 <br>用&nbsp; 法: char *stpcpy(char *destin, char *source);</span> <br>程序例: <br>#include &lt;stdio.h&gt; <br>#include &lt;string.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char string[10]; <br>&nbsp;&nbsp; char *str1 = "abcdefghi"; <br>&nbsp;&nbsp; stpcpy(string, str1); <br>&nbsp;&nbsp; printf("%sn", string); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strcat <br>功&nbsp; 能: 字符串拼接函数 <br>用&nbsp; 法: char *strcat(char *destin, char *source); <br></span>程序例: <br>#include &lt;string.h&gt; <br>#include &lt;stdio.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char destination[25]; <br>&nbsp;&nbsp; char *blank = " ", *c = "C++", *Borland = "Borland"; <br>&nbsp;&nbsp; strcpy(destination, Borland); <br>&nbsp;&nbsp; strcat(destination, blank); <br>&nbsp;&nbsp; strcat(destination, c); <br>&nbsp;&nbsp; printf("%sn", destination); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strchr <br>功&nbsp; 能: 在一个串中查找给定字符的第一个匹配之处 <br>用&nbsp; 法: char *strchr(char *str, char c);</span> <br>程序例: <br>#include &lt;string.h&gt; <br>#include &lt;stdio.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp;&nbsp; char string[15]; <br>&nbsp;&nbsp;&nbsp; char *ptr, c = 'r'; <br>&nbsp;&nbsp;&nbsp; strcpy(string, "This is a string"); <br>&nbsp;&nbsp;&nbsp; ptr = strchr(string, c); <br>&nbsp;&nbsp;&nbsp; if (ptr) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("The character %c is at position: %d\n", c, <span style="BACKGROUND-COLOR: yellow"><strong>ptr-string</strong></span>);//&nbsp;不明白&nbsp;<br>&nbsp;&nbsp;&nbsp; else <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("The character was not foundn"); <br>&nbsp;&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strcmp <br>功&nbsp; 能: 串比较 <br>用&nbsp; 法: int strcmp(char *str1, char *str2); <br>看Asic码，str1&gt;str2，返回值 &gt; 0；两串相等，返回0</span><br>程序例: <br>#include &lt;string.h&gt; <br>#include &lt;stdio.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp;&nbsp; char *buf1 = "aaa", *buf2 = "bbb", *buf3 = "ccc"; <br>&nbsp;&nbsp;&nbsp; int ptr; <br>&nbsp;&nbsp;&nbsp; ptr = strcmp(buf2, buf1); <br>&nbsp;&nbsp;&nbsp; if (ptr &gt; 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is greater than buffer 1n"); <br>&nbsp;&nbsp;&nbsp; else <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is less than buffer 1n"); <br>&nbsp;&nbsp;&nbsp; ptr = strcmp(buf2, buf3); <br>&nbsp;&nbsp;&nbsp; if (ptr &gt; 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is greater than buffer 3n"); <br>&nbsp;&nbsp;&nbsp; else <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is less than buffer 3n"); <br>&nbsp;&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strncmpi <br>功&nbsp; 能: 将一个串中的一部分与另一个串比较, 不管大小写 <br>用&nbsp; 法: int strncmpi(char *str1, char *str2, unsigned maxlen);</span> <br>程序例: <br>#include &lt;string.h&gt; <br>#include &lt;stdio.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char *buf1 = "BBB", *buf2 = "bbb"; <br>&nbsp;&nbsp; int ptr; <br>&nbsp;&nbsp; ptr = strcmpi(buf2, buf1); <br>&nbsp;&nbsp; if (ptr &gt; 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is greater than buffer 1n"); <br>&nbsp;&nbsp; if (ptr &lt; 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is less than buffer 1n"); <br>&nbsp;&nbsp; if (ptr == 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 equals buffer 1n"); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strcpy <br>功&nbsp; 能: 串拷贝 <br>用&nbsp; 法: char *strcpy(char *str1, char *str2);</span> <br>程序例: <br>#include &lt;stdio.h&gt; <br>#include &lt;string.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp;&nbsp; char string[10]; <br>&nbsp;&nbsp;&nbsp; char *str1 = "abcdefghi"; <br>&nbsp;&nbsp;&nbsp; strcpy(string, str1); <br>&nbsp;&nbsp;&nbsp; printf("%sn", string); <br>&nbsp;&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strcspn <br>功&nbsp; 能: 在串中查找第一个给定字符集内容的段 <br>用&nbsp; 法: int strcspn(char *str1, char *str2);</span> <br>程序例: <br>#include &lt;stdio.h&gt; <br>#include &lt;string.h&gt; <br>#include &lt;alloc.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp;&nbsp; char *string1 = "1234567890"; <br>&nbsp;&nbsp;&nbsp; char *string2 = "747DC8"; <br>&nbsp;&nbsp;&nbsp; int length; <br>&nbsp;&nbsp;&nbsp; length = strcspn(string1, string2); <br>&nbsp;&nbsp;&nbsp; printf("Character where strings intersect is at position %dn", length); <br>&nbsp;&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strdup <br>功&nbsp; 能: 将串拷贝到新建的位置处 <br>用&nbsp; 法: char *strdup(char *str);</span> <br>程序例: <br>#include &lt;stdio.h&gt; <br>#include &lt;string.h&gt; <br>#include &lt;alloc.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp;&nbsp; char *dup_str, *string = "abcde"; <br>&nbsp;&nbsp;&nbsp; dup_str = strdup(string); <br>&nbsp;&nbsp;&nbsp; printf("%sn", dup_str); <br>&nbsp;&nbsp;&nbsp; free(dup_str); <br>&nbsp;&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: stricmp <br>功&nbsp; 能: 以大小写不敏感方式比较两个串 <br>用&nbsp; 法: int stricmp(char *str1, char *str2);</span> <br>程序例: <br>#include &lt;string.h&gt; <br>#include &lt;stdio.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char *buf1 = "BBB", *buf2 = "bbb"; <br>&nbsp;&nbsp; int ptr; <br>&nbsp;&nbsp; ptr = stricmp(buf2, buf1); <br>&nbsp;&nbsp; if (ptr &gt; 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is greater than buffer 1n"); <br>&nbsp;&nbsp; if (ptr &lt; 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is less than buffer 1n"); <br>&nbsp;&nbsp; if (ptr == 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 equals buffer 1n"); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strerror <br>功&nbsp; 能: 返回指向错误信息字符串的指针 <br>用&nbsp; 法: char *strerror(int errnum);</span> <br>程序例: <br>#include &lt;stdio.h&gt; <br>#include &lt;errno.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char *buffer; <br>&nbsp;&nbsp; buffer = strerror(errno); <br>&nbsp;&nbsp; printf("Error: %sn", buffer); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strcmpi <br>功&nbsp; 能: 将一个串与另一个比较, 不管大小写 <br>用&nbsp; 法: int strcmpi(char *str1, char *str2);</span> <br>程序例: <br>#include &lt;string.h&gt; <br>#include &lt;stdio.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char *buf1 = "BBB", *buf2 = "bbb"; <br>&nbsp;&nbsp; int ptr; <br>&nbsp;&nbsp; ptr = strcmpi(buf2, buf1); <br>&nbsp;&nbsp; if (ptr &gt; 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is greater than buffer 1n"); <br>&nbsp;&nbsp; if (ptr &lt; 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is less than buffer 1n"); <br>&nbsp;&nbsp; if (ptr == 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 equals buffer 1n"); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strncmp <br>功&nbsp; 能: 串比较 <br>用&nbsp; 法: int strncmp(char *str1, char *str2, int maxlen);</span> <br>程序例: <br>#include &lt;string.h&gt; <br>#include &lt;stdio.h&gt; <br>int&nbsp; main(void) <br>{ <br>&nbsp;&nbsp; char *buf1 = "aaabbb", *buf2 = "bbbccc", *buf3 = "ccc"; <br>&nbsp;&nbsp; int ptr; <br>&nbsp;&nbsp; ptr = strncmp(buf2,buf1,3); <br>&nbsp;&nbsp; if (ptr &gt; 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is greater than buffer 1n"); <br>&nbsp;&nbsp; else <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is less than buffer 1n"); <br>&nbsp;&nbsp; ptr = strncmp(buf2,buf3,3); <br>&nbsp;&nbsp; if (ptr &gt; 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is greater than buffer 3n"); <br>&nbsp;&nbsp; else <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is less than buffer 3n"); <br>&nbsp;&nbsp; return(0); <br>} <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strncmpi <br>功&nbsp; 能: 把串中的一部分与另一串中的一部分比较, 不管大小写 <br>用&nbsp; 法: int strncmpi(char *str1, char *str2);</span> <br>程序例: <br>#include &lt;string.h&gt; <br>#include &lt;stdio.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char *buf1 = "BBBccc", *buf2 = "bbbccc"; <br>&nbsp;&nbsp; int ptr; <br>&nbsp;&nbsp; ptr = strncmpi(buf2,buf1,3); <br>&nbsp;&nbsp; if (ptr &gt; 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is greater than buffer 1n"); <br>&nbsp;&nbsp; if (ptr &lt; 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is less than buffer 1n"); <br>&nbsp;&nbsp; if (ptr == 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 equals buffer 1n"); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br><span style="COLOR: red">&nbsp; <br>函数名: strncpy <br>功&nbsp; 能: 串拷贝 <br>用&nbsp; 法: char *strncpy(char *destin, char *source, int maxlen);</span> <br>程序例: <br>#include &lt;stdio.h&gt; <br>#include &lt;string.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char string[10]; <br>&nbsp;&nbsp; char *str1 = "abcdefghi"; <br>&nbsp;&nbsp; strncpy(string, str1, 3); <br>&nbsp;&nbsp; string[3] = ''; <br>&nbsp;&nbsp; printf("%sn", string); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strnicmp <br>功&nbsp; 能: 不注重大小写地比较两个串 <br>用&nbsp; 法: int strnicmp(char *str1, char *str2, unsigned maxlen);</span> <br>程序例: <br>#include &lt;string.h&gt; <br>#include &lt;stdio.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char *buf1 = "BBBccc", *buf2 = "bbbccc"; <br>&nbsp;&nbsp; int ptr; <br>&nbsp;&nbsp; ptr = strnicmp(buf2, buf1, 3); <br>&nbsp;&nbsp; if (ptr &gt; 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is greater than buffer 1n"); <br>&nbsp;&nbsp; if (ptr &lt; 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 is less than buffer 1n"); <br>&nbsp;&nbsp; if (ptr == 0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("buffer 2 equals buffer 1n"); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strnset <br>功&nbsp; 能: 将一个串中的所有字符都设为指定字符 <br>用&nbsp; 法: char *strnset(char *str, char ch, unsigned n);</span> <br>程序例: <br>#include &lt;stdio.h&gt; <br>#include &lt;string.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char *string = "abcdefghijklmnopqrstuvwxyz"; <br>&nbsp;&nbsp; char letter = 'x'; <br>&nbsp;&nbsp; printf("string before strnset: %sn", string); <br>&nbsp;&nbsp; strnset(string, letter, 13); <br>&nbsp;&nbsp; printf("string after&nbsp; strnset: %sn", string); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strpbrk <br>功&nbsp; 能: 在串中查找给定字符集中的字符 <br>用&nbsp; 法: char *strpbrk(char *str1, char *str2);</span> <br>程序例: <br>#include &lt;stdio.h&gt; <br>#include &lt;string.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char *string1 = "abcdefghijklmnopqrstuvwxyz"; <br>&nbsp;&nbsp; char *string2 = "onm"; <br>&nbsp;&nbsp; char *ptr; <br>&nbsp;&nbsp; ptr = strpbrk(string1, string2); <br>&nbsp;&nbsp; if (ptr) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("strpbrk found first character: %cn", *ptr); <br>&nbsp;&nbsp; else <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("strpbrk didn't find character in setn"); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strrchr <br>功&nbsp; 能: 在串中查找指定字符的最后一个出现 <br>用&nbsp; 法: char *strrchr(char *str, char c);</span> <br>程序例: <br>#include &lt;string.h&gt; <br>#include &lt;stdio.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char string[15]; <br>&nbsp;&nbsp; char *ptr, c = 'r'; <br>&nbsp;&nbsp; strcpy(string, "This is a string"); <br>&nbsp;&nbsp; ptr = strrchr(string, c); <br>&nbsp;&nbsp; if (ptr) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("The character %c is at position: %dn", c, ptr-string); <br>&nbsp;&nbsp; else <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("The character was not foundn"); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strrev <br>功&nbsp; 能: 串倒转 <br>用&nbsp; 法: char *strrev(char *str);</span> <br>程序例: <br>#include &lt;string.h&gt; <br>#include &lt;stdio.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char *forward = "string"; <br>&nbsp;&nbsp; printf("Before strrev(): %sn", forward); <br>&nbsp;&nbsp; strrev(forward); <br>&nbsp;&nbsp; printf("After strrev():&nbsp; %sn", forward); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br><span style="COLOR: red">函数名: strset <br>功&nbsp; 能: 将一个串中的所有字符都设为指定字符 <br>用&nbsp; 法: char *strset(char *str, char c);</span> <br>程序例: <br>#include &lt;stdio.h&gt; <br>#include &lt;string.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char string[10] = "123456789"; <br>&nbsp;&nbsp; char symbol = 'c'; <br>&nbsp;&nbsp; printf("Before strset(): %sn", string); <br>&nbsp;&nbsp; strset(string, symbol); <br>&nbsp;&nbsp; printf("After strset():&nbsp; %sn", string); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strspn <br>功&nbsp; 能: 在串中查找指定字符集的子集的第一次出现 <br>用&nbsp; 法: int strspn(char *str1, char *str2);</span> <br>程序例: <br>#include &lt;stdio.h&gt; <br>#include &lt;string.h&gt; <br>#include &lt;alloc.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char *string1 = "1234567890"; <br>&nbsp;&nbsp; char *string2 = "123DC8"; <br>&nbsp;&nbsp; int length; <br>&nbsp;&nbsp; length = strspn(string1, string2); <br>&nbsp;&nbsp; printf("Character where strings differ is at position %dn", length); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strstr <br>功&nbsp; 能: 在串中查找指定字符串的第一次出现 <br>用&nbsp; 法: char *strstr(char *str1, char *str2);</span> <br>程序例: <br>#include &lt;stdio.h&gt; <br>#include &lt;string.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char *str1 = "Borland International", *str2 = "nation", *ptr; <br>&nbsp;&nbsp; ptr = strstr(str1, str2); <br>&nbsp;&nbsp; printf("The substring is: %sn", ptr); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strtod <br>功&nbsp; 能: 将字符串转换为double型值 <br>用&nbsp; 法: double strtod(char *str, char **endptr); <br></span>程序例: <br>#include &lt;stdio.h&gt; <br>#include &lt;stdlib.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char input[80], *endptr; <br>&nbsp;&nbsp; double value; <br>&nbsp;&nbsp; printf("Enter a floating point number:"); <br>&nbsp;&nbsp; gets(input); <br>&nbsp;&nbsp; value = strtod(input, &amp;endptr); <br>&nbsp;&nbsp; printf("The string is %s the number is %lfn", input, value); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strtok <br>功&nbsp; 能: 查找由在第二个串中指定的分界符分隔开的单词 <br>用&nbsp; 法: char *strtok(char *str1, char *str2);</span> <br>程序例: <br>#include &lt;string.h&gt; <br>#include &lt;stdio.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char input[16] = "abc,d"; <br>&nbsp;&nbsp; char *p; <br>&nbsp;&nbsp; /* strtok places a NULL terminator <br>&nbsp;&nbsp; in front of the token, if found */ <br>&nbsp;&nbsp; p = strtok(input, ","); <br>&nbsp;&nbsp; if (p)&nbsp;&nbsp; printf("%sn", p); <br>&nbsp;&nbsp; /* A second call to strtok using a NULL <br>&nbsp;&nbsp; as the first parameter returns a pointer <br>&nbsp;&nbsp; to the character following the token&nbsp; */ <br>&nbsp;&nbsp; p = strtok(NULL, ","); <br>&nbsp;&nbsp; if (p)&nbsp;&nbsp; printf("%sn", p); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: strtol <br>功&nbsp; 能: 将串转换为长整数 <br>用&nbsp; 法: long strtol(char *str, char **endptr, int base);</span> <br>程序例: <br>#include &lt;stdlib.h&gt; <br>#include &lt;stdio.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char *string = "87654321", *endptr; <br>&nbsp;&nbsp; long lnumber; <br>&nbsp;&nbsp; /* strtol converts string to long integer&nbsp; */ <br>&nbsp;&nbsp; lnumber = strtol(string, &amp;endptr, 10); <br>&nbsp;&nbsp; printf("string = %s&nbsp; long = %ldn", string, lnumber); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br><span style="COLOR: red">函数名: strupr <br>功&nbsp; 能: 将串中的小写字母转换为大写字母 <br>用&nbsp; 法: char *strupr(char *str);</span> <br>程序例: <br>#include &lt;stdio.h&gt; <br>#include &lt;string.h&gt; <br>int main(void) <br>{ <br>&nbsp;&nbsp; char *string = "abcdefghijklmnopqrstuvwxyz", *ptr; <br>&nbsp;&nbsp; /* converts string to upper case characters */ <br>&nbsp;&nbsp; ptr = strupr(string); <br>&nbsp;&nbsp; printf("%sn", ptr); <br>&nbsp;&nbsp; return 0; <br>} <br>&nbsp; <br>&nbsp; <br>&nbsp; <br><span style="COLOR: red">函数名: swab <br>功&nbsp; 能: 交换字节 <br>用&nbsp; 法: void swab (char *from, char *to, int nbytes);</span> <br>程序例: <br>#include &lt;stdlib.h&gt; <br>#include &lt;stdio.h&gt; <br>#include &lt;string.h&gt; <br>char source[15] = "rFna koBlrna d"; <br>char target[15]; <br>int main(void) <br>{ <br>&nbsp;&nbsp; swab(source, target, strlen(source)); <br>&nbsp;&nbsp; printf("This is target: %sn", target); <br>&nbsp;&nbsp; return 0; <br>}<br><br><br><br>PS:isalpha()是字符函数，不是字符串函数，<br><br>isalpha <br>&nbsp; <br><br><br><span style="COLOR: red">&nbsp; 原型：extern int isalpha(int c);<br>&nbsp; <br>&nbsp; 用法：#include &lt;ctype.h&gt;<br>&nbsp; <br>&nbsp; 功能：判断字符c是否为英文字母<br>&nbsp; <br>&nbsp; 说明：当c为英文字母a-z或A-Z时，返回非零值，否则返回零</span>。<br>&nbsp; <br>&nbsp; 举例：<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // isalpha.c<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #include &lt;syslib.h&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #include &lt;ctype.h&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #include &lt;stdio.h&gt;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; main()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int c;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clrscr();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // clear screen<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("Press a key");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(;;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c=getchar();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clrscr();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("%c: %s letter",c,isalpha(c)?"is":"not");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0; // just to avoid warnings by compiler<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>
<img src ="http://www.cppblog.com/tdweng/aggbug/113484.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tdweng/" target="_blank">心羽</a> 2010-04-25 02:07 <a href="http://www.cppblog.com/tdweng/articles/113484.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>