﻿<?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/mydriverc/category/4506.html</link><description>如果想飞得高，就该把地平线忘掉</description><language>zh-cn</language><lastBuildDate>Mon, 19 May 2008 13:36:51 GMT</lastBuildDate><pubDate>Mon, 19 May 2008 13:36:51 GMT</pubDate><ttl>60</ttl><item><title>关于C++类内const函数</title><link>http://www.cppblog.com/mydriverc/articles/35403.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 28 Oct 2007 18:52:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35403.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35403.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35403.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35403.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35403.html</trackback:ping><description><![CDATA[据说有这种面试题：<br />class A<br />{<br />        public :<br />        char get_m() const<br />        {<br />                 return m;<br />        }<br />        private:<br />        char m;<br />}<br />请在函数get_m中改变m的值。<br /><br />我想，对于这种流氓问题，只好使用流氓的做法：<br />        char get_m() const<br />        {<br />                char * p = (char *) &amp;m;<br />                *p = 'C';<br />                 return m;<br />        }<br />呵呵，可以做到，因为类内const函数是通过“把类内成员都作为const”来实现的。<br />不过这是我这种“流氓程序员”的做法。<br /><br />实际上，经过同事的教导，应该使用mutable修饰符：<br />mutable char m;<br />这样即使在类的const函数内，m的类型也是可以改变的了。<br /><br />另外，如果想不要这份工作，也可以这么写：<br />#define const <br />哈哈，这样面试官就不敢要你啦。:D<br /><br /><img src ="http://www.cppblog.com/mydriverc/aggbug/35403.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-29 02:52 <a href="http://www.cppblog.com/mydriverc/articles/35403.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>const成员函数</title><link>http://www.cppblog.com/mydriverc/articles/35401.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 28 Oct 2007 18:49:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35401.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35401.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35401.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35401.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35401.html</trackback:ping><description><![CDATA[
		<font id="zoom">
				<p>
						<span class="style5">第五节　const成员函数 </span> </p>
				<p> 一些成员函数改变对象，一些成员函数不改变对象。 </p>
				<p> 例如： <br /> int Point::GetY() <br /> { <br /> 　 return yVal; <br /> } <br /> 　　 这个函数被调用时，不改变Point对象，而下面的函数改变Point对象： <br /> void Point:: SetPt (int x, int y) <br /> { <br /> 　 xVal=x; <br /> 　 yVal=y; <br /> } <br /> 　　 为了使成员函数的意义更加清楚，我们可在不改变对象的成员函数的函数原型中加上const说明： </p>
				<table border="0" cellpadding="0" cellspacing="0">
						<tbody>
								<tr>
										<td colspan="2">
												<img src="http://c.mephp.com/C/text/ch10/index5_1x1pixel.gif" alt="" height="1" width="1" />
										</td>
								</tr>
								<tr>
										<td width="35">
												<img src="http://c.mephp.com/C/text/ch10/images/lt.gif" alt="例题" height="20" width="25" />
										</td>
										<td>
												<strong>例10-15 </strong>
										</td>
								</tr>
								<tr>
										<td> </td>
										<td>
												<p class="style6">class Point <br />         { <br />         　 public: <br />         　　 int GetX() const; <br />         　　 int GetY() const; </p>
												<p class="style6">　　void SetPt (int, int); <br />         　　 void OffsetPt (int, int); <br />         　 private: <br />         　　 int xVal, yVal; <br />         }; </p>
										</td>
								</tr>
								<tr>
										<td colspan="2">
												<img src="http://c.mephp.com/C/text/ch10/index5_1x1pixel.gif" alt="" height="1" width="1" />
										</td>
								</tr>
						</tbody>
				</table>                 　　 const成员函数应该在函数原型说明和函数定义中都增加const限定：                 <table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td colspan="2"><img src="http://c.mephp.com/C/text/ch10/index5_1x1pixel.gif" alt="" height="1" width="1" /></td></tr><tr><td width="35"><img src="http://c.mephp.com/C/text/ch10/images/lt.gif" alt="例题" height="20" width="25" /></td><td><strong>例10-16 </strong></td></tr><tr><td> </td><td><p class="style6">int Point::GetY() const <br />         { <br />         　 return yVal; <br />         } </p><p class="style6">class Set { <br />         public: <br />         　 Set (void){ card = 0; } <br />         　 bool Member(const int) const; <br />         　 void AddElem(const int); <br />         　 //... <br />         }; </p><p class="style6">bool Set::Member (const int elem) const <br />         { <br />         　 //... <br />         } </p></td></tr><tr><td colspan="2"><img src="http://c.mephp.com/C/text/ch10/index5_1x1pixel.gif" alt="" height="1" width="1" /></td></tr></tbody></table>                 　　 <p class="style4">非常量成员函数不能被常量成员对象调用，因为它可能企图修改常量的数据成员： <br />   　　 const Set s; <br />   　　 s.AddElem(10); // 非法: AddElem不是常量成员函数 <br />   　　 s.Member(10); // 正确 <br />   　　 但构造函数和析构函数对这个规则例外，它们从不定义为常量成员，但可被常量对象调用（被自动调用）。它们也能给常量的数据成员赋值，除非数据成员本身是常量。</p>                 　　 <p> </p><p><span class="style4">为什么需要const成员函数？ <br />
　　
我们定义的类的成员函数中，常常有一些成员函数不改变类的数据成员，也就是说，这些函数是"只读"函数，而有一些函数要修改类数据成员的值。如果把不改变
数据成员的函数都加上const关键字进行标识，显然，可提高程序的可读性。其实，它还能提高程序的可靠性，已定义成const的成员函数，一旦企图修改
数据成员的值，则编译器按错误处理。</span><br /><strong class="style5">const成员函数和const对象 </strong><br /> 　　 <span class="nav">实际上，const成员函数还有另外一项作用，即常量对象相关。对于内置的数据类型，我们可以定义它们的常量，用户自定义的类也一样，可以定义它们的常量对象。例如，定义一个整型常量的方法为： <br /> 　　 const int i=1 ； <br /> 同样，也可以定义常量对象，假定有一个类classA，定义该类的常量对象的方法为： <br /> 　　 const classA a(2)； <br /> 　　 这里，a是类classA的一个const对象，"2"传给它的构造函数参数。const对象的数据成员在对象寿命期内不能改变。但是，如何保证该类的数据成员不被改变呢？ <br /> 　　 为了确保const对象的数据成员不会被改变，在C++中，const对象只能调用const成员函数。如果一个成员函数实际上没有对数据成员作任何形式的修改，但是它没有被const关键字限定的，也不能被常量对象调用。下面通过一个例子来说明这个问题： </span></p><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td colspan="2"><img src="http://c.mephp.com/C/text/ch10/index5_1x1pixel.gif" alt="" height="1" width="1" /></td></tr><tr><td width="35"><img src="http://c.mephp.com/C/text/ch10/images/lt.gif" alt="例题" height="20" width="25" /></td><td><strong>例10-17 </strong></td></tr><tr><td> </td><td><p class="style6">class C <br />         { <br />         　 int X; <br />         public: <br />         　 int GetX() <br />         　 { <br />         　　 return X; <br />         　 } <br />         　 void SetX(int X) <br />         　 { <br />         　　 this-&gt;X = X; <br />         　 } <br />         }; <br />         void main() <br />         { <br />         　 const C constC; <br />         　 cout&lt;&lt;constC.GetX(); <br />         } </p></td></tr><tr><td colspan="2"><img src="http://c.mephp.com/C/text/ch10/index5_1x1pixel.gif" alt="" height="1" width="1" /></td></tr></tbody></table>                 　　 <p><span class="style4">如果我们编译上面的程序代码，编译器会出现错误提示：constC是个常量对象，它只能调用const成员函数。虽然GetX( )函数实际上并没有改变数据成员X，由于没有const关键字限定，所以仍旧不能被constC对象调用。如果我们将上述加粗的代码： <br />   　　 int GetX() <br />   改写成： <br />   　　 int GetX()const <br />   再重新编译，就没有问题了。</span></p>                 　　  <strong class="style5">const成员函数的使用 </strong><br />
　　
const成员函数表示该成员函数只能读类数据成员，而不能修改类成员数据。定义const成员函数时，把const关键字放在函数的参数表和函数体之
间。有人可能会问：为什么不将const放在函数声明前呢？因为这样做意味着函数的返回值是常量，意义完全不同。下面是定义const成员函数的一个实
例： <br /> 　　 class X <br /> 　　 { <br /> 　　　 int i; <br /> 　　　 public: <br /> 　　　 int f() const; <br /> 　　 }; <br /> 　　 关键字const必须用同样的方式重复出现在函数实现里，否则编译器会把它看成一个不同的函数： <br /> 　　 int X::f() const <br /> 　　 { <br /> 　　　 return i; <br /> 　　 } <br /> 　　 如果f( )试图用任何方式改变i或调用另一个非const成员函数，编译器将给出错误信息。任何不修改成员数据的函数都应该声明为const函数，这样有助于提高程序的可读性和可靠性。</font>
		<br />
<img src ="http://www.cppblog.com/mydriverc/aggbug/35401.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-29 02:49 <a href="http://www.cppblog.com/mydriverc/articles/35401.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>构造析构顺序</title><link>http://www.cppblog.com/mydriverc/articles/35400.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 28 Oct 2007 18:41:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35400.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35400.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35400.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35400.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35400.html</trackback:ping><description><![CDATA[#include &lt;iostream.h&gt;<br />//using namespace std;<br />class A{<br />public:<br />    int i;<br />    A(int m)<br />    {<br />        i=m;<br />    cout&lt;&lt;i&lt;&lt;" A con"&lt;&lt;endl;<br />    }<br />    ~A()<br />    {<br />    cout&lt;&lt;i&lt;&lt;"  A des"&lt;&lt;endl;<br />    }<br />};<br />A a(0);<br />int main()<br />{<br />    cout&lt;&lt;"main"&lt;&lt;endl;<br />A b(1);<br />static A c(2);<br />cout&lt;&lt;"unmain"&lt;&lt;endl;<br />}<br />0 A con<br />main<br />1 A con<br />2 A con<br />unmain<br />1 A des<br />2 A des<br />0 A des<br /><br /><br />#include &lt;iostream.h&gt;<br />//using namespace std;<br />class A{<br />public:<br />    int i;<br />    A(int m)<br />    {<br />        i=m;<br />    cout&lt;&lt;i&lt;&lt;" A con"&lt;&lt;endl;<br />    }<br />    ~A()<br />    {<br />    cout&lt;&lt;i&lt;&lt;"  A des"&lt;&lt;endl;<br />    }<br />};<br />A a(0);<br />int main()<br />{<br />    cout&lt;&lt;"main"&lt;&lt;endl;<br />A b(1);<br />A c(2);<br />cout&lt;&lt;"unmain"&lt;&lt;endl;<br />}<br /><br />0 A con<br />main<br />1 A con<br />2 A con<br />3 A con<br />unmain<br />2 A des<br />1 A des<br />3 A des<br />0 A des<br /><br /><img src ="http://www.cppblog.com/mydriverc/aggbug/35400.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-29 02:41 <a href="http://www.cppblog.com/mydriverc/articles/35400.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++构造函数与析构函数执行顺序 ？？？</title><link>http://www.cppblog.com/mydriverc/articles/35398.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 28 Oct 2007 18:31:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35398.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35398.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35398.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35398.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35398.html</trackback:ping><description><![CDATA[
		<div>
				<span style="font-size: 14pt;"> 今天在测试一个构造函数和析构函数的用例的时候，发现我们所钟爱的VC6.0实在是Bug问题越来越多，对于学习C++的新手来讲，有必要在这里给大家说明一下。</span>
		</div>
		<span style="font-size: 14pt;">
				<p>构造函数顺序为：</p>
				<ol>
						<li>
								<span style="font-size: 10pt;"> 全局对象的构造函数； </span>
						</li>
						<li>
								<span style="font-size: 10pt;"> main函数中对象的构造函数，包括automatic、static依次调用； </span>
						</li>
						<li>
								<span style="font-size: 10pt;"> main中遇到函数中有局部对象时，进入到函数中调用局部对象的构造函数。</span>
						</li>
				</ol>
				<p>
						<span style="font-size: 10pt;">     注：static对象的构造函数永远只调用一次。</span>
				</p>
				<p>析构函数顺序为：</p>
				<ol>
						<li>
								<span style="font-size: 10pt;">退出函数时，执行函数内构造的automatic对象的析构函数，注：static对象不析构； </span>
						</li>
						<li>
								<span style="font-size: 10pt;">main函数中按构造的逆序析构automatic对象； </span>
						</li>
						<li>
								<span style="font-size: 10pt;">调用函数中定义的static对象的析构函数； </span>
						</li>
						<li>
								<span style="font-size: 10pt;">调用main中定义的static对象的析构函数； </span>
						</li>
						<li>
								<span style="font-size: 10pt;">最后调用全局对象的析构函数。</span>
						</li>
				</ol>
				<p>
						<span style="font-size: 10pt;">注：复合中的构造、析构顺序</span>
				</p>
				<p>
						<span style="font-size: 10pt;">     构造：按声明对象的顺序来构造成员对象，而不是按照构造函数成员初始值列表中列出的顺序；而且在包含它们的类对象(宿主对象)被构造之前构造。即：由内向外构造。</span>
				</p>
				<p>
						<span style="font-size: 10pt;">    析构：按对象构造的逆序析构。对于复合对象，先析构主对象，再析构其包含的对象。</span>
				</p>
				<div>
						<span style="font-size: 14pt;">比如有以下的测试用例：</span>
				</div>
				<blockquote dir="ltr" style="margin-right: 0px;">
						<blockquote dir="ltr" style="margin-right: 0px;">
								<div>
										<span style="font-size: 10pt;">//＃i nclude &lt;iostream.h&gt;<br />＃i nclude &lt;iostream&gt;<br />using namespace std;<br />class Demo {<br /> int id;<br />public: <br /> Demo(int i)  <br /> { id = i; <br /> cout &lt;&lt; "id=" &lt;&lt; id &lt;&lt; ",Con" &lt;&lt; endl; }<br /> ~Demo()<br /> { cout &lt;&lt; "id=" &lt;&lt; id &lt;&lt; ",Des" &lt;&lt;endl; }<br />};</span>
								</div>
								<div>
										<span style="font-size: 10pt;">Demo d1(4);</span>
								</div>
								<div>
										<span style="font-size: 10pt;">void fun(Demo d) {<br /> static Demo d2(2);<br /> Demo d3(3);<br /> cout &lt;&lt; "fun" &lt;&lt; endl;  <br />}<br />void main ()  {<br /> cout &lt;&lt;"main"&lt;&lt; endl;<br /> fun(d1);<br /> cout &lt;&lt; "endmain" &lt;&lt; endl;<br /> fun(d1); <br /> Demo * p = new Demo(8);<br /> <br />}</span>
								</div>
								<br />
						</blockquote>
				</blockquote>
				<div dir="ltr">程序执行的时候，在VC6 withSp6下运行的结果</div>
				<blockquote dir="ltr" style="margin-right: 0px;">
						<blockquote dir="ltr" style="margin-right: 0px;">
								<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">id=4,Con</span>
								</p>
								<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">main</span>
								</p>
								<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">id=2,Con</span>
								</p>
								<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">id=3,Con</span>
								</p>
								<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">fun</span>
								</p>
								<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">id=3,Des</span>
								</p>
								<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">id=4,Des</span>
								</p>
								<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">endmain</span>
								</p>
								<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">id=3,Con</span>
								</p>
								<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">fun</span>
								</p>
								<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">id=3,Des</span>
								</p>
								<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">id=4,Des</span>
								</p>
								<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">id=8,Con</span>
								</p>
								<div class="MsoNormal" style="margin: 0cm 0cm 0pt;">
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">id=2,Des</span>
								</div>
								<div class="MsoNormal" style="margin: 0cm 0cm 0pt;">
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">
										</span>
										<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">//id=4,Des //在用&lt;iostream.h&gt;的时候才有此句输出</span>
								</div>
						</blockquote>
				</blockquote>
				<div class="MsoNormal" dir="ltr" style="margin: 0cm 0cm 0pt;">
						<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">        其中包含有注释的部分，为调整包含的头文件为&lt;iostream.h&gt;的情况下才有的输出。如果使用 命名空间的std的话，没有最后的一句输出。</span>
				</div>
				<div class="MsoNormal" dir="ltr" style="margin: 0cm 0cm 0pt;">
						<span style="font-size: 12pt; font-family: Times New Roman;" lang="EN-US">        从百度上找了半天，才发现不是没有调用全局变量的析构函数，而是因为我们所用的编译器有问题，这是MS的产品对于C++的支持做的不是尽善尽美，有网友说在Vc7.0中好想消除了这个Bug。</span>
				</div>
		</span>
<img src ="http://www.cppblog.com/mydriverc/aggbug/35398.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-29 02:31 <a href="http://www.cppblog.com/mydriverc/articles/35398.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>头文件  extern</title><link>http://www.cppblog.com/mydriverc/articles/35396.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 28 Oct 2007 18:02:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35396.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35396.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35396.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35396.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35396.html</trackback:ping><description><![CDATA[
		<br />　　试题4：为什么标准头文件都有类似以下的结构？ <br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>#ifndef __INCvxWorksh<br />#define __INCvxWorksh <br />#ifdef __cplusplus<br /><br />extern "C" {<br />#endif <br />/*...*/ <br />#ifdef __cplusplus<br />}<br /><br />#endif <br />#endif /* __INCvxWorksh */</td></tr></tbody></table><br />　　解答：<br /><br />　　头文件中的编译宏<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>#ifndef　__INCvxWorksh<br />#define　__INCvxWorksh<br />#endif </td></tr></tbody></table><br />　　的作用是防止被重复引用。<br /><br />　　作为一种面向对象的语言，C++支持函数重载，而过程式语言C则不支持。函数被C++编译后在symbol库中的名字与C语言的不同。例如，假设某个函数的原型为： <br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>void foo(int x, int y);</td></tr></tbody></table><p><br />　　该函数被C编译器编译后在symbol库中的名字为_foo，而C++编译器则会产生像_foo_int_int之类的名字。_foo_int_int这样的名字包含了函数名和函数参数数量及类型信息，C++就是考这种机制来实现函数重载的。<br /><br />　　为了实现C和C++的混合编程，C++提供了C连接交换指定符号extern "C"来解决名字匹配问题，函数声明前加上extern "C"后，则编译器就会按照C语言的方式将该函数编译为_foo，这样C语言中就可以调用C++的函数了。</p><img src ="http://www.cppblog.com/mydriverc/aggbug/35396.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-29 02:02 <a href="http://www.cppblog.com/mydriverc/articles/35396.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>BOOL和bool的区别</title><link>http://www.cppblog.com/mydriverc/articles/35395.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 28 Oct 2007 17:46:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35395.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35395.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35395.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35395.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35395.html</trackback:ping><description><![CDATA[一：在网上找到了BOOL和bool的区别：<br />1、类型不同<br />BOOL为int型<br />bool为布尔型<br />2、长度不同<br />bool只有一个字节<br />BOOL长度视实际环境来定，一般可认为是4个字节<br />3、取值不同<br />bool取值false和true，是0和1的区别<br />BOOL取值FALSE和TRUE，是0和非0的区别<br />二：<br />bool是标准C++数据类型，可取值true和false。单独占一个字节，<br />如果数个bool对象列在一起，可能会各占一个bit，这取决于编译器。<br /><br />BOOL是微软定义的typedef int BOOL。与bool不同，它是一个三值逻辑<br /><br />，<br />TRUE/FALSE/ERROR，返回值为&gt;0的整数为TRUE，0为FALSE，-1为ERROR。<br />Win32 API中很多返回值为BOOL的函数都是三值逻辑。比如GetMessage<br /><br />().<br />三：<br />大BOOL和小bool之间的区别：<br />1、类型不同<br />BOOL为int型<br />bool为布尔型<br />2、长度不同<br />bool只有一个字节<br />BOOL长度视实际环境来定，一般可认为是4个字节<br />3、取值不同<br />bool取值false和true，是0和1的区别<br />BOOL取值FALSE和TRUE，是0和非0的区别<br />4、例子<br />bool x=3;  //告警<br />bool x=1;  //正确<br />BOOL x=3;  //正确<br />BOOL x=3.3;  //告警<br />注：windows为了兼容问题定义的基础变量。<br />typedef unsigned long       DWORD;<br />typedef int                 BOOL;<br />typedef unsigned char       BYTE;<br />typedef unsigned short      WORD;<br />typedef float               FLOAT;<br />typedef FLOAT               *PFLOAT;<br />typedef BOOL near           *PBOOL;<br />typedef BOOL far            *LPBOOL;<br />typedef BYTE near           *PBYTE;<br />typedef BYTE far            *LPBYTE;<br />typedef int near            *PINT;<br />typedef int far             *LPINT;  //   maximum   heap   size <br /><br /> <br />  );  <br /><br /><img src ="http://www.cppblog.com/mydriverc/aggbug/35395.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-29 01:46 <a href="http://www.cppblog.com/mydriverc/articles/35395.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>++ ？？？？？？</title><link>http://www.cppblog.com/mydriverc/articles/35394.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 28 Oct 2007 17:42:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35394.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35394.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35394.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35394.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35394.html</trackback:ping><description><![CDATA[int main()<br />{<br />    int i=0;<br />    printf("%d,%d,%d",(++i),(++i),(++i));<br />}<br />3 2 1<br /><br />int main()<br />{<br />    int i=0;<br />    printf("%d,%d,%d",(i++),(i++),(i++));<br />}<br />0 0 0<br /><img src ="http://www.cppblog.com/mydriverc/aggbug/35394.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-29 01:42 <a href="http://www.cppblog.com/mydriverc/articles/35394.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Strcpy与memcpy两函数的经典实现</title><link>http://www.cppblog.com/mydriverc/articles/35393.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 28 Oct 2007 17:23:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35393.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35393.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35393.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35393.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35393.html</trackback:ping><description><![CDATA[char *strcpy(char *des, const char *src){<br />       assert((des != NULL) &amp;&amp; (src != NULL));<br />       char *add = des;<br />       while ((*des++ = *src++) != ‘\0’) ;<br />return des;<br />}<br /> <br />void  *memcpy(void *pvTo, const void *pvFrom, size_t size) {<br />       assert((pvTo != NULL) &amp;&amp; (pvFrom != NULL));      // 使用断言<br />       byte *pbTo = (byte *) pvTo;         // 防止改变pvTo的地址<br />       byte *pbFrom = (byte *) pvFrom; // 防止改变pvFrom的地址<br />       while(size -- &gt; 0 <a href="http://www.blogcn.com/images/wink.gif" target="_blank"><img src="http://www.blogcn.com/images/wink.gif" onload="if(this.width&gt;screen.width/2)this.style.width=screen.width/2;" border="0" /></a><br />              *pbTo ++ = *pbFrom ++ ;<br />       return pvTo;<br />}<img src ="http://www.cppblog.com/mydriverc/aggbug/35393.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-29 01:23 <a href="http://www.cppblog.com/mydriverc/articles/35393.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sizeof</title><link>http://www.cppblog.com/mydriverc/articles/35391.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 28 Oct 2007 17:12:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35391.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35391.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35391.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35391.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35391.html</trackback:ping><description><![CDATA[试题2：以下为Windows NT下的32位C++程序，请计算sizeof的值<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>void Func ( char str[100] )<br />{<br />　sizeof( str ) = ?<br />}<br /><br />void *p = malloc( 100 );<br />sizeof ( p ) = ?</td></tr></tbody></table><br />　　解答：<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>sizeof( str ) = 4<br />sizeof ( p ) = 4</td></tr></tbody></table><br />　　剖析：<br /><br />　　Func ( char str[100] )函数中数组名作为函数形参时，在函数体内，数组名失去了本身的内涵，仅仅只是一个指针；在失去其内涵的同时，它还失去了其常量特性，可以作自增、自减等操作，可以被修改。<br /><br />　　数组名的本质如下：<br /><br />　　（1）数组名指代一种数据结构，这种数据结构就是数组；<br /><br />　　例如：<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>char str[10];<br />cout &lt;&lt; sizeof(str) &lt;&lt; endl;</td></tr></tbody></table><br />　　输出结果为10，str指代数据结构char[10]。<br /><br />　　（2）数组名可以转换为指向其指代实体的指针，而且是一个指针常量，不能作自增、自减等操作，不能被修改；<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>char str[10]; <br />str++; //编译出错，提示str不是左值　</td></tr></tbody></table><br />　　（3）数组名作为函数形参时，沦为普通指针。<br /><br />　　Windows NT 32位平台下，指针的长度（占用内存的大小）为4字节，故sizeof( str ) 、sizeof ( p ) 都为4。<br /><img src ="http://www.cppblog.com/mydriverc/aggbug/35391.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-29 01:12 <a href="http://www.cppblog.com/mydriverc/articles/35391.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>分别给出BOOL，int，float，指针变量 与“零值”比较的 if 语句</title><link>http://www.cppblog.com/mydriverc/articles/35390.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 28 Oct 2007 17:08:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35390.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35390.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35390.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35390.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35390.html</trackback:ping><description><![CDATA[试题1：分别给出BOOL，int，float，指针变量 与“零值”比较的 if 语句（假设变量名为var）<br /><br />　　解答：<br /><br />　　　BOOL型变量：if(!var)<br /><br />　　　int型变量： if(var==0)<br /><br />　　　float型变量：<br /><br />　　　const float EPSINON = 0.00001;<br /><br />　　　if ((x &gt;= - EPSINON) &amp;&amp; (x &lt;= EPSINON)<br /><br />　　　指针变量：　　if(var==NULL)<br /><br />　　剖析：<br /><br />　　考查对0值判断的“内功”，BOOL型变量的0判断完全可以写成if(var==0)，而int型变量也可以写成if(!var)，指针变量的判断也可以写成if(!var)，上述写法虽然程序都能正确运行，但是未能清晰地表达程序的意思。<table align="left" border="0" cellpadding="0" cellspacing="0"><tbody><tr><td valign="top"><table align="left" border="0" cellpadding="0" cellspacing="4" width="350"><tbody><tr><td> </td></tr></tbody></table></td></tr><tr><td> </td></tr></tbody></table><br /><br />　
　一般的，如果想让if判断一个变量的“真”、“假”，应直接使用if(var)、if(!var)，表明其为“逻辑”判断；如果用if判断一个数值型变
量(short、int、long等)，应该用if(var==0)，表明是与0进行“数值”上的比较；而判断指针则适宜用if(var==NULL)，
这是一种很好的编程习惯。<br /><br />　　浮点型变量并不精确，所以不可将float变量用“==”或“！=”与数字比较，应该设法转化成“&gt;=”或“&lt;=”形式。如果写成if (x == 0.0)，则判为错，得0分。<img src ="http://www.cppblog.com/mydriverc/aggbug/35390.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-29 01:08 <a href="http://www.cppblog.com/mydriverc/articles/35390.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GetMemory 改错</title><link>http://www.cppblog.com/mydriverc/articles/35389.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 28 Oct 2007 17:03:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35389.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35389.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35389.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35389.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35389.html</trackback:ping><description><![CDATA[试题4：<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>void GetMemory( char *p )<br />{<br />　p = (char *) malloc( 100 );<br />}<br /><br />void Test( void ) <br />{<br />　char *str = NULL;<br />　GetMemory( str ); <br />　strcpy( str, "hello world" );<br />　printf( str );<br />}</td></tr></tbody></table><br />　　试题5：<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>char *GetMemory( void )<br />{ <br />　char p[] = "hello world"; <br />　return p; <br />}<br /><br />void Test( void )<br />{ <br />　char *str = NULL; <br />　str = GetMemory(); <br />　printf( str ); <br />}</td></tr></tbody></table><br />　　试题6：<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>void GetMemory( char **p, int num )<br />{<br />　*p = (char *) malloc( num );<br />}<br /><br />void Test( void )<br />{<br />　char *str = NULL;<br />　GetMemory( &amp;str, 100 );<br />　strcpy( str, "hello" ); <br />　printf( str ); <br />}</td></tr></tbody></table><br />　　试题7：<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>void Test( void )<br />{<br />　char *str = (char *) malloc( 100 );<br />　strcpy( str, "hello" );<br />　free( str ); <br />　... //省略的其它语句<br />}</td></tr></tbody></table><br />　　解答：<br /><br />　　试题4传入中GetMemory( char *p )函数的形参为字符串指针，在函数内部修改形参并不能真正的改变传入形参的值，执行完<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>char *str = NULL;<br />GetMemory( str ); </td></tr></tbody></table><br />　　后的str仍然为NULL；<br /><br />　　试题5中<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>char p[] = "hello world"; <br />return p; </td></tr></tbody></table><br />　　的p[]数组为函数内的局部自动变量，在函数返回后，内存已经被释放。这是许多程序员常犯的错误，其根源在于不理解变量的生存期。<br /><br />　　试题6的GetMemory避免了试题4的问题，传入GetMemory的参数为字符串指针的指针，但是在GetMemory中执行申请内存及赋值语句<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>*p = (char *) malloc( num );</td></tr></tbody></table><br />　　后未判断内存是否申请成功，应加上：<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>if ( *p == NULL )<br />{<br />　...//进行申请内存失败处理<br />}</td></tr></tbody></table><br />　　试题7存在与试题6同样的问题，在执行<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>char *str = (char *) malloc(100);</td></tr></tbody></table><br />　　后未进行内存是否申请成功的判断；<b>另外，在free(str)后未置str为空，导致可能变成一个“野”指针，应加上：<br /><br /></b><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td><b>str = NULL;</b></td></tr></tbody></table><br />　　试题6的Test函数中也未对malloc的内存进行释放。<br /><br />　　剖析：<br /><br />　　试题4～7考查面试者对内存操作的理解程度，基本功扎实的面试者一般都能正确的回答其中50~60的错误。但是要完全解答正确，却也绝非易事。<br /><br />　　对内存操作的考查主要集中在：<br /><br />　　（1）指针的理解；<br /><br />　　（2）变量的生存期及作用范围；<br /><br />　　（3）良好的动态内存申请和释放习惯。<br /><br />　　再看看下面的一段程序有什么错误：<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>swap( int* p1,int* p2 )<br />{<br />　int *p;<br />　*p = *p1;<br />　*p1 = *p2;<br />　*p2 = *p;<br />}</td></tr></tbody></table><br />　　在swap函数中，p是一个“野”指针，有可能指向系统区，导致程序运行的崩溃。在VC++中DEBUG运行时提示错误“Access Violation”。该程序应该改为：<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>swap( int* p1,int* p2 )<br />{<br />　int p;<br />　p = *p1;<br />　*p1 = *p2;<br />　*p2 = p;<br />}</td></tr></tbody></table><img src ="http://www.cppblog.com/mydriverc/aggbug/35389.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-29 01:03 <a href="http://www.cppblog.com/mydriverc/articles/35389.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>strcpy</title><link>http://www.cppblog.com/mydriverc/articles/35388.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 28 Oct 2007 16:56:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35388.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35388.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35388.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35388.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35388.html</trackback:ping><description><![CDATA[试题1：<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>void test1()<br />{<br />　char string[10];<br />　char* str1 = "0123456789";<br />　strcpy( string, str1 );<br />}</td></tr></tbody></table><br />　　试题2：<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>void test2()<br />{<br />　char string[10], str1[10];<br />　int i;<br />　for(i=0; i&lt;10; i++)<br />　{<br />　　str1[i] = 'a';<br />　}<br />　strcpy( string, str1 );<br />}</td></tr></tbody></table><br />　　试题3：<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>void test3(char* str1)<br />{<br />　char string[10];<br />　if( strlen( str1 ) &lt;= 10 )<br />　{<br />　　strcpy( string, str1 );<br />　}<br />}</td></tr></tbody></table><br />　　解答：<br /><br />　　试题1字符串str1需要11个字节才能存放下（包括末尾的’\0’），而string只有10个字节的空间，strcpy会导致数组越界；<br /><br />　
　对试题2，如果面试者指出字符数组str1不能在数组内结束可以给3分；如果面试者指出strcpy(string,
str1)调用使得从str1内存起复制到string内存起所复制的字节数具有不确定性可以给7分，在此基础上指出库函数strcpy工作方式的给10
分；<br /><br />　　对试题3，if(strlen(str1) &lt;= 10)应改为if(strlen(str1) &lt; 10)，因为strlen的结果未统计’\0’所占用的1个字节。<br /><br />　　剖析：<br /><br />　　考查对基本功的掌握：<br /><br />　　(1)字符串以’\0’结尾；<br /><br />　　(2)对数组越界把握的敏感度；<br /><br />　　(3)库函数strcpy的工作方式，如果编写一个标准strcpy函数的总分值为10，下面给出几个不同得分的答案：<br /><br />　　2分<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>void strcpy( char *strDest, char *strSrc )<br />{<br />　 while( (*strDest++ = * strSrc++) != ‘\0’ );<br />}</td></tr></tbody></table><br />　　4分<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>void strcpy( char *strDest, const char *strSrc ) <br />//将源字符串加const，表明其为输入参数，加2分<br />{<br />　 while( (*strDest++ = * strSrc++) != ‘\0’ );<br />}</td></tr></tbody></table><br />　　7分<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>void strcpy(char *strDest, const char *strSrc) <br />{<br />　//对源地址和目的地址加非0断言，加3分<br />　assert( (strDest != NULL) &amp;&amp; (strSrc != NULL) );<br />　while( (*strDest++ = * strSrc++) != ‘\0’ );<br />}</td></tr></tbody></table><br />　　10分<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>//为了实现链式操作，将目的地址返回，加3分！<br /><br />char * strcpy( char *strDest, const char *strSrc ) <br />{<br />　assert( (strDest != NULL) &amp;&amp; (strSrc != NULL) );<br />　char *address = strDest; <br />　while( (*strDest++ = * strSrc++) != ‘\0’ ); <br />　　return address;<br />}</td></tr></tbody></table><br />　　从2分到10分的几个答案我们可以清楚的看到，小小的strcpy竟然暗藏着这么多玄机，真不是盖的！需要多么扎实的基本功才能写一个完美的strcpy啊！<br />(4)对strlen的掌握，它没有包括字符串末尾的'\0'。<br /><br />　读者看了不同分值的strcpy版本，应该也可以写出一个10分的strlen函数了，完美的版本为： int strlen( const char *str ) //输入参数const<br /><br />                        {<br />　assert( strt != NULL ); //断言字符串地址非0<br />　int len;<br />　while( (*str++) != '\0' ) <br />　{ <br />　　len++; <br />　} <br />　return len;<br />}<br /><br /><img src ="http://www.cppblog.com/mydriverc/aggbug/35388.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-29 00:56 <a href="http://www.cppblog.com/mydriverc/articles/35388.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>new 和 malloc</title><link>http://www.cppblog.com/mydriverc/articles/35387.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 28 Oct 2007 16:50:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35387.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35387.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35387.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35387.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35387.html</trackback:ping><description><![CDATA[
		<div>
				<div>malloc与free是C++/C语言的标准库函数，new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。   <br /> 
对于非内部数据类型的对象而言，光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数，对象在消亡之前要自动执行析构函
数。由于malloc/free是库函数而不是运算符，不在编译器控制权限之内，不能够把执行构造函数和析构函数的任务强加于malloc/free。
  <br />  因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new，以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。   <br />  我们先看一看malloc/free和new/delete如何实现对象的动态内存管理。   <br />    <br />  class   Obj   <br />  {   <br />  public   :   <br />  Obj(void){   cout   &lt;&lt;   “Initialization”   &lt;&lt;   endl;   }   <br />  ~Obj(void){   cout   &lt;&lt;   “Destroy”   &lt;&lt;   endl;   }   <br />  void Initialize(void){   cout   &lt;&lt;   “Initialization”   &lt;&lt;   endl;   }   <br />  void         Destroy(void){   cout   &lt;&lt;   “Destroy”   &lt;&lt;   endl;   }   <br />  };   <br />  void   UseMallocFree(void)   <br />  {   <br />  Obj     *a   =   (obj   *)malloc(sizeof(obj)); //   申请动态内存   <br />  a-&gt;Initialize(); //   初始化   <br />  //…   <br />  a-&gt;Destroy(); //   清除工作   <br />  free(a); //   释放内存   <br />  }   <br />  void   UseNewDelete(void)   <br />  {   <br />  Obj     *a   =   new   Obj; //   申请动态内存并且初始化   <br />  //…   <br />  delete   a; //   清除并且释放内存   <br />  }   <br />    用malloc/free和new/delete如何实现对象的动态内存管理   <br />    <br /> 
类Obj的函数Initialize模拟了构造函数的功能，函数Destroy模拟了析构函数的功能。函数UseMallocFree中，由于
malloc/free不能执行构造函数与析构函数，必须调用成员函数Initialize和Destroy来完成初始化与清除工作。函数
UseNewDelete则简单得多。   <br />  所以我们不要企图用malloc/free来完成动态对象的内存管理，应该用new/delete。由于内部数据类型的“对象”没有构造与析构的过程，对它们而言malloc/free和new/delete是等价的。   <br />  既然new/delete的功能完全覆盖了malloc/free，为什么C++不把malloc/free淘汰出局呢？这是因为C++程序经常要调用C函数，而C程序只能用malloc/free管理动态内存。   <br /> 
如果用free释放“new创建的动态对象”，那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内
存”，理论上讲程序不会出错，但是该程序的可读性很差。所以new/delete必须配对使用，malloc/free也一样。   <br /></div>
				<div>函数malloc的原型如下：   <br />  void   *   malloc(size_t   size);   <br />  用malloc申请一块长度为length的整数类型的内存，程序如下：   <br />  int     *p   =   (int   *)   malloc(sizeof(int)   *   length);   <br />  我们应当把注意力集中在两个要素上：“类型转换”和“sizeof”。   <br /> 
malloc返回值的类型是void   *，所以在调用malloc时要显式地进行类型转换，将void   *  
转换成所需要的指针类型。malloc函数本身并不识别要申请的内存是什么类型，它只关心内存的总字节数。我们通常记不住int,  
float等数据类型的变量的确切字节数。   <br />    <br />  运算符new使用起来要比函数malloc简单得多，例如：   <br />  int     *p1   =   (int   *)malloc(sizeof(int)   *   length);   <br />  int     *p2   =   new   int[length];   <br />  这是因为new内置了sizeof、类型转换和类型安全检查功能。对于非内部数据类型的对象而言，new在创建动态对象的同时完成了初始化工作。如果对象有多个构造函数，那么new的语句也可以有多种形式。例如   <br />  class   Obj   <br />  {   <br />  public   :   <br />  Obj(void); //   无参数的构造函数   <br />  Obj(int   x); //   带一个参数的构造函数   <br />  …   <br />  }   <br />  void   Test(void)   <br />  {   <br />  Obj     *a   =   new   Obj;   <br />  Obj     *b   =   new   Obj(1); //   初值为1   <br />  …   <br />  delete   a;   <br />  delete   b;   <br />  }   <br />  如果用new创建对象数组，那么只能使用对象的无参数构造函数。</div>
				<div> </div>
				<div>区别两个   <br />    <br />  1   new是操作符   <br />      malloc是库函数   <br />    <br />  2   new可以调用构造函数，malloc不可以   <br />    <br />    <br />  还有，这两个函数不存在内存分配大小问题   <br />  这两个操作是在堆里面申请内存空间，除非空间不够了，返回BULL指针，否则都没有问题的，如果你出现了某种情况，看看是不是其它的问题。   <br />new   最终调用的是HeapAlloc,而HeapAlloc声明如下：   <br />  LPVOID   HeapAlloc(   <br />      HANDLE   hHeap,     //   handle   to   the   private   heap   block   <br />      DWORD   dwFlags,   //   heap   allocation   control   flags   <br />      DWORD   dwBytes     //   number   of   bytes   to   allocate   <br />  );   <br />  其中第一个参数必须是HeapCreate或GetProcessHeap   函数的返回句柄。   <br />  如果是HeapCreate的话（如下：）   <br />  HANDLE   HeapCreate(   <br />      DWORD   flOptions,             //   heap   allocation   flag   <br />      DWORD   dwInitialSize,     //   initial   heap   size   <br />      DWORD   dwMaximumSize       //   maximum   heap   size   <br />  );   <br />  那么当该函数的最后一个参数非0时，所创建的堆要比0x7FFF8(512k)略小。如果为0，则大小受到可用内存的限制。   <br />  还有，new申请的内存不可移动，会造成内存碎片。</div>
				<div> </div>
				<div> </div>
				<div>内存分配最终都堆(HEAP)上操作,允许的最大空间是_HEAP_MAXREQ=0xFFFFFFE0,但C运行库会在每次额外分配一个
_CrtMemBlockHeader结构在该次分配的内存起始处,同时在结束处多分配nNoMansLadnSize=4个字节的内存用于检测检查调
试.因此通常的高效内存管理技术都是将多次小空间分配合并成一次大空间分配,或只进行一次分配,回收时不释放以直接用于下次分配的   .   <br />  可分配空间并不等于一定可以分配到,这受环境的直接影响,如页文件的大小,系统已经占用的空间等.   <br />  当所给参数太大,会有运行时警告:Invalid   allocation   size:   %u   bytes.</div>
		</div>
<img src ="http://www.cppblog.com/mydriverc/aggbug/35387.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-29 00:50 <a href="http://www.cppblog.com/mydriverc/articles/35387.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>类中的常量</title><link>http://www.cppblog.com/mydriverc/articles/35286.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Fri, 26 Oct 2007 17:04:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35286.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35286.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35286.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35286.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35286.html</trackback:ping><description><![CDATA[类中的常量<br />
有时我们希望某些常量只在类中有效。由于#define 定义的宏常量是全局的，不能<br />
达到目的，于是想当然地觉得应该用const 修饰数据成员来实现。const 数据成员的确<br />
是存在的，但其含义却不是我们所期望的。const 数据成员只在某个对象生存期内是常<br />
量，而对于整个类而言却是可变的，因为类可以创建多个对象，不同的对象其const 数<br />
据成员的值可以不同。<br />
不能在类声明中初始化const 数据成员。以下用法是错误的，因为类的对象未被创<br />
建时，编译器不知道SIZE 的值是什么。<br />
class A<br />
{…<br />
const int SIZE = 100; // 错误，企图在类声明中初始化const 数据成员<br />
int array[SIZE]; // 错误，未知的SIZE<br />
};<br />
const 数据成员的初始化只能在类构造函数的初始化表中进行，例如<br />
class A<br />
{…<br />
A(int size); // 构造函数<br />
const int SIZE ;<br />
};<br />
A::A(int size) : SIZE(size) // 构造函数的初始化表<br />
{<br />
…<br />
}<br />
A a(100); // 对象 a 的SIZE 值为100<br />
A b(200); // 对象 b 的SIZE 值为200<br />
怎样才能建立在整个类中都恒定的常量呢？别指望const 数据成员了，应该用类中<br />
的枚举常量来实现。例如<br />
class A<br />
{…<br />
enum { SIZE1 = 100, SIZE2 = 200}; // 枚举常量<br />
int array1[SIZE1];<br />
int array2[SIZE2];<br />
};<br />
枚举常量不会占用对象的存储空间，它们在编译时被全部求值。枚举常量的缺点是：<br />
它的隐含数据类型是整数，其最大值有限，且不能表示浮点数（如PI=3.14159）。<br /><img src ="http://www.cppblog.com/mydriverc/aggbug/35286.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-27 01:04 <a href="http://www.cppblog.com/mydriverc/articles/35286.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么是堆内存分配栈内存分配</title><link>http://www.cppblog.com/mydriverc/articles/35284.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Fri, 26 Oct 2007 16:42:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35284.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35284.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35284.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35284.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35284.html</trackback:ping><description><![CDATA[五大内存分区 <br />
在C++中，内存分成5个区，他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。 <br />
栈，就是那些由编译器在需要的时候分配，在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。 <br />
堆，就是那些由new分配的内存块，他们的释放编译器不去管，由我们的应用程序去控制，一般一个new就要对应一个delete。如果程序员没有释放掉，那么在程序结束后，操作系统会自动回收。 <br />
自由存储区，就是那些由malloc等分配的内存块，他和堆是十分相似的，不过它是用free来结束自己的生命的。 <br />
全局/静态存储区，全局变量和静态变量被分配到同一块内存中，在以前的C语言中，全局变量又分为初始化的和未初始化的，在C++里面没有这个区分了，他们共同占用同一块内存区。 <br />
常量存储区，这是一块比较特殊的存储区，他们里面存放的是常量，不允许修改（当然，你要通过非正当手段也可以修改，而且方法很多，在《const的思考》一文中，我给出了6种方法） <br /><br />
明确区分堆与栈 <br />
在bbs上，堆与栈的区分问题，似乎是一个永恒的话题，由此可见，初学者对此往往是混淆不清的，所以我决定拿他第一个开刀。 <br />
首先，我们举一个例子： <br />
void f() { int* p=new int[5]; } <br />
这条短短的一句话就包含了堆与栈，看到new，我们首先就应该想到，我们分配了一块堆内存，那么指针p呢？他分配的是一块栈内存，所以这句话的意思就是：
在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小，然后调用operator
new分配内存，然后返回这块内存的首地址，放入栈中，他在VC6下的汇编代码如下： <br />
00401028 push 14h <br />
0040102A call operator new (00401060) <br />
0040102F add esp,4 <br />
00401032 mov dword ptr [ebp-8],eax <br />
00401035 mov eax,dword ptr [ebp-8] <br />
00401038 mov dword ptr [ebp-4],eax <br />
这里，我们为了简单并没有释放内存，那么该怎么去释放呢？是delete p么？澳，错了，应该是delete []p，这是为了告诉编译器：我删除的是一个数组，VC6就会根据相应的Cookie信息去进行释放内存的工作。 <br />
好了，我们回到我们的主题：堆和栈究竟有什么区别？ <br />
主要的区别由以下几点： <br />
1、管理方式不同； <br />
2、空间大小不同； <br />
3、能否产生碎片不同； <br />
4、生长方向不同； <br />
5、分配方式不同； <br />
6、分配效率不同； <br />
管理方式：对于栈来讲，是由编译器自动管理，无需我们手工控制；对于堆来说，释放工作由程序员控制，容易产生memory leak。 <br />
空间大小：一般来讲在32位系统下，堆内存可以达到4G的空间，从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲，一般都是有一定的空间大小的，例如，在VC6下面，默认的栈空间大小是1M（好像是，记不清楚了）。当然，我们可以修改： <br />
打开工程，依次操作菜单如下：Project-&gt;Setting-&gt;Link，在Category 中选中Output，然后在Reserve中设定堆栈的最大值和commit。 <br />
注意：reserve最小值为4Byte；commit是保留在虚拟内存的页文件里面，它设置的较大会使栈开辟较大的值，可能增加内存的开销和启动时间。 <br />
碎片问题：对于堆来讲，频繁的new/delete势必会造成内存空间的不连续，从而造成大量的碎片，使程序效率降低。对于栈来讲，则不会存在这个问题，
因为栈是先进后出的队列，他们是如此的一一对应，以至于永远都不可能有一个内存块从栈中间弹出，在他弹出之前，在他上面的后进的栈内容已经被弹出，详细的
可以参考数据结构，这里我们就不再一一讨论了。 <br />
生长方向：对于堆来讲，生长方向是向上的，也就是向着内存地址增加的方向；对于栈来讲，它的生长方向是向下的，是向着内存地址减小的方向增长。 <br />
分配方式：堆都是动态分配的，没有静态分配的堆。栈有2种分配方式：静态分配和动态分配。静态分配是编译器完成的，比如局部变量的分配。动态分配由alloca函数进行分配，但是栈的动态分配和堆是不同的，他的动态分配是由编译器进行释放，无需我们手工实现。 <br />
分配效率：栈是机器系统提供的数据结构，计算机会在底层对栈提供支持：分配专门的寄存器存放栈的地址，压栈出栈都有专门的指令执行，这就决定了栈的效率比
较高。堆则是C/C++函数库提供的，它的机制是很复杂的，例如为了分配一块内存，库函数会按照一定的算法（具体的算法可以参考数据结构/操作系统）在堆
内存中搜索可用的足够大小的空间，如果没有足够大小的空间（可能是由于内存碎片太多），就有可能调用系统功能去增加程序数据段的内存空间，这样就有机会分
到足够大小的内存，然后进行返回。显然，堆的效率比栈要低得多。 <br />
从这里我们可以看到，堆和栈相比，由于大量new/delete的使用，容易造成大量的内存碎片；由于没有专门的系统支持，效率很低；由于可能引发用户态
和核心态的切换，内存的申请，代价变得更加昂贵。所以栈在程序中是应用最广泛的，就算是函数的调用也利用栈去完成，函数调用过程中的参数，返回地址，
EBP和局部变量都采用栈的方式存放。所以，我们推荐大家尽量用栈，而不是用堆。 <br />
虽然栈有如此众多的好处，但是由于和堆相比不是那么灵活，有时候分配大量的内存空间，还是用堆好一些。 <br />
无论是堆还是栈，都要防止越界现象的发生（除非你是故意使其越界），因为越界的结果要么是程序崩溃，要么是摧毁程序的堆、栈结构，产生以想不到的结果,就
算是在你的程序运行过程中，没有发生上面的问题，你还是要小心，说不定什么时候就崩掉，那时候debug可是相当困难的：） <br />
对了，还有一件事，如果有人把堆栈合起来说，那它的意思是栈，可不是堆，呵呵，清楚了？<img src ="http://www.cppblog.com/mydriverc/aggbug/35284.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-27 00:42 <a href="http://www.cppblog.com/mydriverc/articles/35284.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 的“函数内联”</title><link>http://www.cppblog.com/mydriverc/articles/35279.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Fri, 26 Oct 2007 16:23:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35279.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35279.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35279.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35279.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35279.html</trackback:ping><description><![CDATA[让我们看看C++ 的“函数内联”是如何工作的。对于任何内联函数，编译器在符号<br />表里放入函数的声明（包括名字、参数类型、返回值类型）。如果编译器没有发现内联函<br />数存在错误，那么该函数的代码也被放入符号表里。在调用一个内联函数时，编译器首<br />先检查调用是否正确（进行类型安全检查，或者进行自动类型转换，当然对所有的函数<br />都一样）。如果正确，内联函数的代码就会直接替换函数调用，于是省去了函数调用的开<br />销。这个过程与预处理有显著的不同，因为预处理器不能进行类型安全检查，或者进行<br />自动类型转换。假如内联函数是成员函数，对象的地址（this）会被放在合适的地方，<br />这也是预处理器办不到的。<br />C++ 语言的函数内联机制既具备宏代码的效率，又增加了安全性，而且可以自由操<br />作类的数据成员。所以在C++ 程序中，应该用内联函数取代所有宏代码，“断言assert”<br />恐怕是唯一的例外。assert 是仅在Debug 版本起作用的宏，它用于检查“不应该”发生<br />的情况。为了不在程序的Debug 版本和Release 版本引起差别，assert 不应该产生任何副<br />作用。如果assert 是函数，由于函数调用会引起内存、代码的变动，那么将导致Debug<br />版本与Release 版本存在差异。所以assert 不是函数，而是宏。<img src ="http://www.cppblog.com/mydriverc/aggbug/35279.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-27 00:23 <a href="http://www.cppblog.com/mydriverc/articles/35279.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>/</title><link>http://www.cppblog.com/mydriverc/articles/35255.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Fri, 26 Oct 2007 09:47:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35255.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35255.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35255.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35255.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35255.html</trackback:ping><description><![CDATA[#include &lt;stdio.h&gt;<br />int main()<br />{<br />   int i=102/4*6;<br />   printf("%d\n",i);<br />   i=float(102/4)*6;<br />   printf("%d\n",i);<br />   i=float(102)/4*6;<br />   printf("%d\n",i);<br /><br /><br />   float a=102/4;<br />   float b=float(102)/4;<br />   printf("%f %f\n",a,b);<br />   return 1;<br />}<br />150<br />150<br />153<br />25.0000000<br />25.500000<br /><img src ="http://www.cppblog.com/mydriverc/aggbug/35255.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-26 17:47 <a href="http://www.cppblog.com/mydriverc/articles/35255.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 中不能重载的运算符</title><link>http://www.cppblog.com/mydriverc/articles/35252.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Fri, 26 Oct 2007 09:30:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/35252.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/35252.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/35252.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/35252.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/35252.html</trackback:ping><description><![CDATA[C/C++ 里大多数运算符都可以在 C++ 中被重载。C 的运算符中只有 <tt>.</tt><tt></tt>和 <tt>?:</tt>（以及 <tt>sizeof</tt>，技术上可以看作一个运算符）不可以被重载。C++ 增加了一些自己的运算符，除了 <tt>:: </tt>和 <tt>.* 外</tt>，大多数都可以被重载。<img src ="http://www.cppblog.com/mydriverc/aggbug/35252.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-26 17:30 <a href="http://www.cppblog.com/mydriverc/articles/35252.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>scanf 详解</title><link>http://www.cppblog.com/mydriverc/articles/34815.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 21 Oct 2007 17:24:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/34815.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/34815.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/34815.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/34815.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/34815.html</trackback:ping><description><![CDATA[# include &lt;stdio.h&gt;;<br />int scanf( const char *format, ... );<br /><br />    函数 scanf() 是从标准输入流 stdin 中读内容的通用子程序，可以读入全部固有类型的数据并自动转换成机内形式。scanf() 是 printf() 的补函数。<br /><br />    在 C99 中，format 用 restrict 修饰。<br /><br />    format 指向的控制串由以下三类字符组成：<br />       ● 格式说明符<br />       ● 空白符<br />       ● 非空白符<br />    输入格式说明符前缀为百分号(%)，告诉 scanf() 下次读入何种数据类型。这些格式说明符的清单如下表所示：<br />    ┏━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓<br />    ┃ 代  码 │             意                          义             ┃<br />    ┠────┼────────────────────────────┨<br />    ┃   %a   │读浮点值(仅适用于 C99)                                  ┃<br />    ┃   %A   │读浮点值(仅适用于 C99)                                  ┃<br />    ┃   %c   │读单字符                                                ┃<br />    ┃   %d   │读十进制整数                                            ┃<br />    ┃   %i   │读十进制、八进制、十六进制整数                          ┃<br />    ┃   %e   │读浮点数                                                ┃<br />    ┃   %E   │读浮点数                                                ┃<br />    ┃   %f   │读浮点数                                                ┃<br />    ┃   %F   │读浮点数(仅适用于 C99)                                  ┃<br />    ┃   %g   │读浮点数                                                ┃<br />    ┃   %G   │读浮点数                                                ┃<br />    ┃   %o   │读八进制数                                              ┃<br />    ┃   %s   │读字符串                                                ┃<br />    ┃   %x   │读十六进制数                                            ┃<br />    ┃   %X   │读十六进制数                                            ┃<br />    ┃   %p   │读指针值                                                ┃<br />    ┃   %n   │至此已读入值的等价字符数                                ┃<br />    ┃   %u   │读无符号十进制整数                                      ┃<br />    ┃  %[ ]  │扫描字符集合                                            ┃<br />    ┃   %%   │读 % 符号(百分号)                                       ┃<br />    ┗━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛<br /> 
  例如： %s 表示读串而 %d 表示读整数。格式串的处理顺序为从左到右，格式说明符逐一与变元表中的变元匹配。为了读取长整数，可以将
l(ell) 放在格式说明符的前面；为了读取短整数，可以将 h 放在格式说明符的前面。这些修饰符可以与 d、i、o、u 和 x
格式代码一起使用。<br /><br />    默认情况下，a、f、e 和 g 告诉 scanf() 为 float 分配数据。 如果将
l(ell) 放在这些修饰符的前面，则 scanf() 为 double 分配数据。使用 L 就是告诉 scanf()，接收数据的变量是
long double 型变量。<br /><br />    如果使用的现代编译器程序支持 1995 年增加的宽字符特性， 则可以与 c
格式代码一起，用 l 修饰符说明类型 wchar_t 的宽字符指针；也可以与 s 格式代码一起，用 l 修饰符说明宽字符串的指针。l
修饰符也可以用于修饰扫描集，以说明宽字符。<br /><br />    控制串中的空白符使 scanf() 在输入流中跳过一个或多个空白行。空白符可以是空格(space)、制表符(tab)和新行符(newline)。 本质上，控制串中的空白符使 scanf() 在输入流中读，但不保存结果，直到发现非空白字符为止。<br /><br />    非空白符使 scanf() 在流中读一个匹配的字符并忽略之。例如，"%d,%d" 使 scanf() 先读入一个整数，读入中放弃逗号，然后读另一个整数。如未发现匹配，scanf() 返回。<br /><br />    scanf() 中用于保存读入值的变元必须都是变量指针，即相应变量的地址。<br /><br />    在输入流中，数据项必须由空格、制表符和新行符分割。逗号和分号等不是分隔符，比如以下代码：<br />    scanf( "%d %d", &amp;r, &amp;c );<br />将接受输入 10 20，但遇到 10,20 则失败。<br /><br />    <b>百分号(%)与格式符之间的星号(*)表示读指定类型的数据但不保存。</b>因此，<br />    scanf( "%d %*c %d", &amp;x, &amp;y );<br />对 10/20 的读入操作中，10 放入变量 x，20 放入 y。<br /><br />    格式命令可以说明最大域宽。 在百分号(%)与格式码之间的整数用于限制从对应域读入的最大字符数。例如，希望向 address 读入不多于 20 个字符时，可以书写成如下形式：<br />    scanf( "%20s", address );<br /><br />    如果输入流的内容多于 20 个字符，则下次 scanf() 从此次停止处开始读入。 若达到最大域宽前已遇到空白符，则对该域的读立即停止；此时，scanf() 跳到下一个域。<br /><br />    虽然空格、制表符和新行符都用做域分割符号，但读单字符操作中却按一般字符处理。例如，对输入流 "x y" 调用：<br />    scanf( "%c%c%c", &amp;a, &amp;b, &amp;c );<br />返回后，x 在变量 a 中，空格在变量 b 中，y 在变量 c 中。<br /><br />    注意，控制串中的其它字符，包括空格、制表符和新行符，都用于从输入流中匹配并放弃字符，被匹配的字符都放弃。例如，给定输入流 "10t20"，调用：<br />    scanf( "%dt%d", &amp;x, &amp;y );<br />将把 10 和 20 分别放到 x 和 y 中，t 被放弃，因为 t 在控制串中。<br /><br /> 
  ANSI C 标准向 scanf() 增加了一种新特性，称为扫描集(scanset)。 扫描集定义一个字符集合，可由 scanf()
读入其中允许的字符并赋给对应字符数组。 扫描集合由一对方括号中的一串字符定义，左方括号前必须缀以百分号。 例如，以下的扫描集使 scanf()
读入字符 A、B 和 C：<br />    %[ABC]<br /><br />    使用扫描集时，scanf() 连续吃进集合中的字符并放入对应的字符数组，直到发现不在集合中的字符为止(即扫描集仅读匹配的字符)。返回时，数组中放置以 null 结尾、由读入字符组成的字符串。<br /><br />    用字符 ^ 可以说明补集。把 ^ 字符放为扫描集的第一字符时，构成其它字符组成的命令的补集合，指示 scanf() 只接受未说明的其它字符。<br />    对于许多实现来说，用连字符可以说明一个范围。 例如，以下扫描集使 scanf() 接受字母 A 到 Z：<br />    %[A-Z]<br />    重要的是要注意扫描集是区分大小写的。因此，希望扫描大、小写字符时，应该分别说明大、小写字母。<br />    scanf() 返回等于成功赋值的域数的值，但由于星号修饰符而读入未赋值的域不计算在内。给第一个域赋值前已出错时，返回 EOF。<br /><br /> 
  C99 为 scanf() 增加了几个格式修饰符：hh、ll、j、z 和 t。hh 修饰符可用于 d、i、o、u、x、X 或
n。它说明相应的变元是 signed 或 unsigned char 值，或用于 n 时， 相应的变元是指向 long char
型变量的指针。ll 修饰符也可用于 d、i、o、u、x、X 或 n。它说明相应的变元是 signed 或者 unsigned long
long int 值。<br />    j 格式修饰符应用于 d、i、o、u、x、X 或 n，说明匹配的变元是类型 intmax_t 或 uintmax_t。这些类型在 &lt;stdint.h&gt;; 中声明，并说明最大宽度的整数。<br />    z 格式修饰符应用于 d、i、o、u、x、X 或 n，说明匹配的变元是指向 size_t 类型对象的指针。该类型在 &lt;stddef.h&gt;; 中声明，并说明 sizeof 的结构。<br />    t 格式修饰符应用于 d、i、o、u、x、X 或 n，说明匹配的变元是指向 ptrdiff_t  类型对象的指针。该类型在 &lt;stddef.h&gt;; 中声明，并说明两个指针之间的差别。<br /><br /><br />例子：<br /><br /># include &lt;stdio.h&gt;;<br /><br />int main( void )<br />{<br />    char str[80], str2[80];<br />    int i;<br /><br />    /* read a string and a integer */<br />    scanf( "%s%d", str, &amp;i );<br /><br />    /* read up to 79 chars into str */<br />    scanf( "%79s", str );<br /><br />    /* skip the integer between the two strings */<br />    scanf( "%s%*d%s", str, str2 );<br /><br />    return 0;<br />}<br /><br /><br />相关函数：<br />printf() 及 fscanf()。<img src ="http://www.cppblog.com/mydriverc/aggbug/34815.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-22 01:24 <a href="http://www.cppblog.com/mydriverc/articles/34815.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>scanf</title><link>http://www.cppblog.com/mydriverc/articles/34814.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 21 Oct 2007 17:22:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/34814.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/34814.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/34814.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/34814.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/34814.html</trackback:ping><description><![CDATA[   scanf("%d,%d",&amp;i,&amp;j);<br />   printf("%d,%d",i,j);<br />如果输入 1 2回车<br />则返回1，随机数<br /><br />   scanf("%d,%d\n",&amp;i,&amp;j);<br />   printf("%d,%d",i,j);<br />最后按回车，直道随便输入个东西<br /><br /><br /><img src ="http://www.cppblog.com/mydriverc/aggbug/34814.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-22 01:22 <a href="http://www.cppblog.com/mydriverc/articles/34814.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>scanf 空格</title><link>http://www.cppblog.com/mydriverc/articles/34813.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 21 Oct 2007 17:10:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/34813.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/34813.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/34813.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/34813.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/34813.html</trackback:ping><description><![CDATA[由于scanf函数在接收数据时，是通过空格来区分数据项的.   <br />   如果你：   <br />   char   c[20];   <br />   scanf("%s",c);   <br />   输入:this   is   a   c   program!   <br />   它接收到this后遇到空格，认为对应%s的数据项已结束，后面的（包含空格）不能输入。   <br />   你想输入带空格的字符串，只有使用gets(c);   <br />   但遗憾的是用gets()函数一次只能输入一个字符串。<img src ="http://www.cppblog.com/mydriverc/aggbug/34813.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-22 01:10 <a href="http://www.cppblog.com/mydriverc/articles/34813.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用指针返回动态内存</title><link>http://www.cppblog.com/mydriverc/articles/34812.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 21 Oct 2007 17:09:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/34812.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/34812.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/34812.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/34812.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/34812.html</trackback:ping><description><![CDATA[void GetMemory2(char **p, int num)<br />{<br />*p = (char *)malloc(sizeof(char) * num);<br />}<br />void Test2(void)<br />{<br />char *str = NULL;<br />GetMemory2(&amp;str, 100); // 注意参数是 &amp;str，而不是str<br />strcpy(str, "hello");<br />cout&lt;&lt; str &lt;&lt; endl;<br />free(str);<br />}<br /><br /><br /><br />char *GetMemory3(int num)<br />{<br />char *p = (char *)malloc(sizeof(char) * num);<br />return p;<br />}<br />void Test3(void)<br />{<br />char *str = NULL;<br />str = GetMemory3(100);<br />strcpy(str, "hello");<br />cout&lt;&lt; str &lt;&lt; endl;<br />free(str);<br />}<br /><img src ="http://www.cppblog.com/mydriverc/aggbug/34812.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-22 01:09 <a href="http://www.cppblog.com/mydriverc/articles/34812.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>const char *</title><link>http://www.cppblog.com/mydriverc/articles/34811.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 21 Oct 2007 17:06:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/34811.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/34811.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/34811.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/34811.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/34811.html</trackback:ping><description><![CDATA[#include &lt;stdio.h&gt;<br />void foo(const char *p)<br />{<br />  p="world";<br />}<br /><br />int main()<br />{<br />   const char* q="Hello";<br />   foo(q);<br />   printf("%s\n",q);<br />   q="world";<br />   printf("%s\n",q);<br />}<br />Hello<br />world<br /><img src ="http://www.cppblog.com/mydriverc/aggbug/34811.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-22 01:06 <a href="http://www.cppblog.com/mydriverc/articles/34811.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>联发笔试  一个数组的使用</title><link>http://www.cppblog.com/mydriverc/articles/34810.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 21 Oct 2007 16:45:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/34810.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/34810.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/34810.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/34810.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/34810.html</trackback:ping><description><![CDATA[#include &lt;stdio.h&gt;<br />void foo(int b[][3])<br />{<br />  b++;<br />  b[1][1]=9;<br />}<br />int main()<br />{<br />    int a[][3]={{1,2,3},{4,5,6},{7,8,9}};<br />    foo(a);<br />    printf("%d,%d\n",a[1][2],a[2][1]);<br />}<br />6，9<br /><img src ="http://www.cppblog.com/mydriverc/aggbug/34810.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-22 00:45 <a href="http://www.cppblog.com/mydriverc/articles/34810.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>memmove</title><link>http://www.cppblog.com/mydriverc/articles/34809.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 21 Oct 2007 16:37:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/34809.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/34809.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/34809.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/34809.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/34809.html</trackback:ping><description><![CDATA[贴个VC下的源码看看：<br />void * __cdecl memmove ( void * dst, const void * src, size_t count  )<br />{<br />        void * ret = dst;<br /><br />        if (dst &lt;= src || (char *)dst &gt;= ((char *)src + count)) {<br />                /*<br />                 * Non-Overlapping Buffers<br />                 * copy from lower addresses to higher addresses<br />                 */<br />                while (count--) {<br />                        *(char *)dst = *(char *)src;<br />                        dst = (char *)dst + 1;<br />                        src = (char *)src + 1;<br />                }<br />        }<br />        else {<br />                /*<br />                 * Overlapping Buffers<br />                 * copy from higher addresses to lower addresses<br />                 */<br />                dst = (char *)dst + count - 1;<br />                src = (char *)src + count - 1;<br /><br />                while (count--) {<br />                        *(char *)dst = *(char *)src;<br />                        dst = (char *)dst - 1;<br />                        src = (char *)src - 1;<br />                }<br />        }<br /><br />        return(ret);<br />}<br /><br />void * memmove(void * dest,const void *src,size_t count)<br />{<br />       char *tmp, *s;<br /><br />        if (dest &lt;= src) {<br />                tmp = (char *) dest;<br />               s = (char *) src;<br />                while (count--)<br />                        *tmp++ = *s++;<br />                }<br />         else {<br />                 tmp = (char *) dest + count;<br />                s = (char *) src + count;<br />                 while (count--)<br />                         *--tmp = *--s;<br />                }<br /><br />        return dest;<br /> }<br /><br /><img src ="http://www.cppblog.com/mydriverc/aggbug/34809.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-22 00:37 <a href="http://www.cppblog.com/mydriverc/articles/34809.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>++i不产生临时变量，i++产生临时变量</title><link>http://www.cppblog.com/mydriverc/articles/34808.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 21 Oct 2007 16:36:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/34808.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/34808.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/34808.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/34808.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/34808.html</trackback:ping><description><![CDATA[++i:   {*this   +=   1;   return   *this}   <br />   i++:   {tmpobj   =   *this;   ++(*this);   return   tmpobj;}<img src ="http://www.cppblog.com/mydriverc/aggbug/34808.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-22 00:36 <a href="http://www.cppblog.com/mydriverc/articles/34808.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>strcat</title><link>http://www.cppblog.com/mydriverc/articles/34807.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Sun, 21 Oct 2007 16:34:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/34807.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/34807.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/34807.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/34807.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/34807.html</trackback:ping><description><![CDATA[strcat的实现  <br />  char   *   strcat(char   *   dest,   const   char   *   src)  <br />  {  <br />  char   *tmp   =   dest;  <br />   <br />  while   (*dest)  <br />  dest++;  <br />  while   ((*dest++   =   *src++)   !=   '\0')  <br />  ;  <br />   <br />  return   tmp;  <br />  }<br />strcat(char   *dest,   const   *src),其中，src是以'\0'结尾的字符串，通过遍历src把它的每个字符放到dest字符串里面，当遍历src遇到'\0'时结束。使用 strcat要防止src的长度大于dest的长度，不然数组越界。<br /><br />以下为摘自:C:\Program   Files\Microsoft   Visual   Studio\VC98\CRT\SRC\strcat.c：  <br />   <br />  char   *   __cdecl   strcat   (  <br />                  char   *   dst,  <br />                  const   char   *   src  <br />                  )  <br />  {  <br />                  char   *   cp   =   dst;  <br />   <br />                  while(   *cp   )  <br />                                  cp++;                                       /*   find   end   of   dst   */  <br />   <br />                  while(   *cp++   =   *src++   )   ;               /*   Copy   src   to   end   of   dst   */  <br />   <br />                  return(   dst   );                                     /*   return   dst   */  <br />   <br />  } <br /><img src ="http://www.cppblog.com/mydriverc/aggbug/34807.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-22 00:34 <a href="http://www.cppblog.com/mydriverc/articles/34807.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>含有中文字符串的截取问题！</title><link>http://www.cppblog.com/mydriverc/articles/33995.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Thu, 11 Oct 2007 18:08:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/33995.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/33995.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/33995.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/33995.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/33995.html</trackback:ping><description><![CDATA[
		问题：<br />   
字符串：music&lt;&lt;美丽的草原我的家&gt;&gt;。该字符串的长度即str.length()为：17，而目前需要存入数据库对应的
字段长度为：16。所以必须对字符串进行截取。而前16个字节中，“原”字只有半个。这样存入数据库确对会出现“？”。所以必须判断是否是半个汉字，即只
能存入“music&lt;&lt;美丽的草”。<br /><br />分析：<br />    汉字是双字节编码，它为了能够与英文字符分开，每个字节的最高位一定为1。如果是汉字，那么这个字节就是小于0的。这个函数就是通过这一原理实现的。所以要通过getBytes()转化为byte型，再比较与零的大小。  <br />getBytes()是把一个字符串转成一个byte数组，因为计算机的数据都是基于字符的，也就是说一个字符串实际上就是一个字符流，因此可以转为字符数组。<br /><br />程序：<br />    public  static  String  getStr(String  src,  int  len)  {  <br />       if  (src  ==  null)              return  null;  <br />       if  (src.getBytes().length  &lt;=  len)    return  src;  <br /> <br />       byte[]  s  =  src.getBytes();  <br />       int  flag  =  0;  <br />       for(int  i=0;i&lt;len;++i){  <br />         if(s[i]  &lt;  0)  flag++;    <br />       }  <br />       if(flag%2!=0)  len--;          <br /> <br />       byte[]  d  =  new  byte[len];  <br />       System.arraycopy(s,  0,  d,  0,  len);  <br />       return  new  String(d);  <br />   }  <img src ="http://www.cppblog.com/mydriverc/aggbug/33995.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-12 02:08 <a href="http://www.cppblog.com/mydriverc/articles/33995.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ascii 字符  整数</title><link>http://www.cppblog.com/mydriverc/articles/33994.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Thu, 11 Oct 2007 17:55:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/33994.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/33994.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/33994.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/33994.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/33994.html</trackback:ping><description><![CDATA[int main()<br />{<br />   char b='0';<br />   printf("%d\n",b);<br />   printf("%c\n",b);<br /><br />   int i=48;<br />   printf("%d\n",i);<br />   printf("%c\n",i);<br />   return 1;<br />}<br />48<br />0<br />48<br />0<br /><br />表现形式不同。<br /><img src ="http://www.cppblog.com/mydriverc/aggbug/33994.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-12 01:55 <a href="http://www.cppblog.com/mydriverc/articles/33994.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>美国标准信息交换标准码 (ASCII)</title><link>http://www.cppblog.com/mydriverc/articles/33993.html</link><dc:creator>旅途</dc:creator><author>旅途</author><pubDate>Thu, 11 Oct 2007 17:49:00 GMT</pubDate><guid>http://www.cppblog.com/mydriverc/articles/33993.html</guid><wfw:comment>http://www.cppblog.com/mydriverc/comments/33993.html</wfw:comment><comments>http://www.cppblog.com/mydriverc/articles/33993.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mydriverc/comments/commentRss/33993.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mydriverc/services/trackbacks/33993.html</trackback:ping><description><![CDATA[   美国标准信息交换代码( American Standard Code for Information Interchange,
ASCII )是由美国国家标准学会(American National Standard Institute , ANSI
)制定的，标准的单字节字符<a target="_blank" href="http://baike.baidu.com/view/237708.htm">编码</a>方案，用于基于文本的数据。起始于50年代后期，在1967年定案。它最初是美国国家标准，供不同计算机在相互通信时用作共同遵守的西文字符编码标准，后被ISO及CCITT等国际组织采用。<br /><br />
       ASCII 码使用指定的 7 位或 8 位二进制数组合来表示 128 或 256 种可能的字符。标准 ASCII 码使用 7 位二进制数来表示所有的大写和小写字母，数字 0 到 9、标点符号，以及在美式英语中使用的特殊控制字符。目前许多基于<a target="_blank" href="http://baike.baidu.com/view/339142.htm">x86</a>的系统都支持使用扩展（或“高”）ASCII。扩展 ASCII 码允许将每个字符的第 8 位用于确定附加的 128 个特殊符号字符、<a target="_blank" href="http://baike.baidu.com/view/137180.htm">外来语</a>字母和图形符号。<br /><br />
       值 8、9、10 和 13 分别转换为退格、制表、换行和<a target="_blank" href="http://baike.baidu.com/view/377583.htm">回车</a>字符。它们并没有特定的图形显示，但会依不同的应用程序，而对文本显示有不同的影响<br /><br />
控制字符<br />
二进制          十进制 十六进制 缩写    解释 <br />
0000 0000    0          00            NUL    空字符(Null) <br />
0000 0001    1          01            SOH    标题开始 <br />
0000 0010    2          02            STX    正文开始 <br />
0000 0011    3          03            ETX    正文结束 <br />
0000 0100    4          04            EOT    传输结束 <br />
0000 0101    5          05            ENQ    请求 <br />
0000 0110    6          06            ACK    收到通知 <br />
0000 0111    7          07            BEL    响铃 <br />
0000 1000    8          08            BS      退格 <br />
0000 1001    9          09            HT      水平制表符 <br />
0000 1010    10        0A            LF      换行键 <br />
0000 1011    11        0B            VT      垂直制表符 <br />
0000 1100    12        0C            FF      换页键 <br />
0000 1101    13        0D            CR      回车键 <br />
0000 1110    14        0E            SO      不用切换 <br />
0000 1111    15        0F            SI        启用切换 <br />
0001 0000    16        10            DLE    数据链路转义 <br />
0001 0001    17        11            DC1    设备控制1 <br />
0001 0010    18        12            DC2    设备控制2 <br />
0001 0011    19        13            DC3    设备控制3 <br />
0001 0100    20        14            DC4    设备控制4 <br />
0001 0101    21        15            NAK    拒绝接收 <br />
0001 0110    22        16            SYN    同步空闲 <br />
0001 0111    23        17            ETB    传输块结束 <br />
0001 1000    24        18            CAN    取消 <br />
0001 1001    25        19            EM      介质中断 <br />
0001 1010    26        1A            SUB    替补 <br />
0001 1011    27        1B            ESC    溢出 <br />
0001 1100    28        1C            FS      文件分割符 <br />
0001 1101    29        1D            GS      分组符 <br />
0001 1110    30        1E            RS      记录分离符 <br />
0001 1111    31        1F            US      单元分隔符 <br />
0111 1111    127      7F            DEL      删除 <br /><br />
可显示字符<br />
二进制          十进制 十六进制 字符 <br />
0010 0000    32        20            空格 <br />
0010 0001    33        21            ! <br />
0010 0010    34        22            " <br />
0010 0011    35        23            # <br />
0010 0100    36        24            $ <br />
0010 0101    37        25            % <br />
0010 0110    38        26            &amp;amp; <br />
0010 0111    39        27            ' <br />
0010 1000    40        28            ( <br />
0010 1001    41        29            ) <br />
0010 1010    42        2A            * <br />
0010 1011    43        2B            + <br />
0010 1100    44        2C            , <br />
0010 1101    45        2D            - <br />
0010 1110    46        2E            . <br />
0010 1111    47        2F            / <br />
0011 0000    48        30            0 <br />
0011 0001    49        31            1 <br />
0011 0010    50        32            2 <br />
0011 0011    51        33            3 <br />
0011 0100    52        34            4 <br />
0011 0101    53        35            5 <br />
0011 0110    54        36            6 <br />
0011 0111    55        37            7 <br />
0011 1000    56        38            8 <br />
0011 1001    57        39            9 <br />
0011 1010    58        3A            : <br />
0011 1011    59        3B            ; <br />
0011 1100    60        3C            &amp;lt; <br />
0011 1101    61        3D            = <br />
0011 1110    62        3E            &amp;gt; <br />
0011 1111    63        3F            ? <br />
0100 0000    64        40            @ <br /><br />
可显示字符<br />
二进制          十进制 十六进制 字符 <br />
0100 0001    65        41            A <br />
0100 0010    66        42            B <br />
0100 0011    67        43            C <br />
0100 0100    68        44            D <br />
0100 0101    69        45            E <br />
0100 0110    70        46            F <br />
0100 0111    71        47            G <br />
0100 1000    72        48            H <br />
0100 1001    73        49            I <br />
0100 1010    74        4A            J <br />
0100 1011    75        4B            K <br />
0100 1100    76        4C            L <br />
0100 1101    77        4D            M <br />
0100 1110    78        4E            N <br />
0100 1111    79        4F            O <br />
0101 0000    80        50            P <br />
0101 0001    81        51            Q <br />
0101 0010    82        52            R <br />
0101 0011    83        53            S <br />
0101 0100    84        54            T <br />
0101 0101    85        55            U <br />
0101 0110    86        56            V <br />
0101 0111    87        57            W <br />
0101 1000    88        58            X <br />
0101 1001    89        59            Y <br />
0101 1010    90        5A            Z <br />
0101 1011    91        5B            [ <br />
0101 1100    92        5C            \ <br />
0101 1101    93        5D            ] <br />
0101 1110    94        5E            ^ <br />
0101 1111    95        5F            _ <br />
0110 0000    96        60            ` <br /><br />
可显示字符<br />
二进制          十进制 十六进制 字符<br />
0110 0001    97        61            a <br />
0110 0010    98        62            b <br />
0110 0011    99        63            c <br />
0110 0100    100      64            d <br />
0110 0101    101      65            e <br />
0110 0110    102      66            f <br />
0110 0111    103      67            g <br />
0110 1000    104      68            h <br />
0110 1001    105      69            i <br />
0110 1010    106      6A            j <br />
0110 1011    107      6B            k <br />
0110 1100    108      6C            l <br />
0110 1101    109      6D            m <br />
0110 1110    110      6E            n <br />
0110 1111    111      6F            o <br />
0111 0000    112      70            p <br />
0111 0001    113      71            q <br />
0111 0010    114      72            r <br />
0111 0011    115      73            s <br />
0111 0100    116      74            t <br />
0111 0101    117      75            u <br />
0111 0110    118      76            v <br />
0111 0111    119      77            w <br />
0111 1000    120      78            x <br />
0111 1001    121      79            y <br />
0111 1010    122      7A            z <br />
0111 1011    123      7B            { <br />
0111 1100    124      7C            | <br />
0111 1101    125      7D            } <br />
0111 1110    126      7E            ~ <img src ="http://www.cppblog.com/mydriverc/aggbug/33993.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mydriverc/" target="_blank">旅途</a> 2007-10-12 01:49 <a href="http://www.cppblog.com/mydriverc/articles/33993.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>