﻿<?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++博客-爱生活 爱技术</title><link>http://www.cppblog.com/hktk/</link><description /><language>zh-cn</language><lastBuildDate>Tue, 14 Apr 2026 23:10:00 GMT</lastBuildDate><pubDate>Tue, 14 Apr 2026 23:10:00 GMT</pubDate><ttl>60</ttl><item><title>常见的网络资源</title><link>http://www.cppblog.com/hktk/archive/2009/10/06/97954.html</link><dc:creator>海 阔 天 空</dc:creator><author>海 阔 天 空</author><pubDate>Tue, 06 Oct 2009 09:23:00 GMT</pubDate><guid>http://www.cppblog.com/hktk/archive/2009/10/06/97954.html</guid><description><![CDATA[<p dragover="true"><strong>常见的网络资源<br></strong>这些资源的合理使用可丰富您的博客功能，给您的使用和体验带来便利。<br>留言板：<a href="http://www.cbox.ws/" target=_blank><font color=#419639><u>Cbox</u></font></a><br>在线播放器：<a href="http://www.91china.com/" target=_blank><font color=#419639><u>91china</u></font></a>、<a href="http://www.8box.cn/" target=_blank><font color=#419639><u>音乐八宝盒</u></font></a>、<a href="http://wobox.blogworld.com.cn/" target=_blank><font color=#419639><u>部落窝</u></font></a><br>RSS合烧统计：<a href="http://www.feedsky.com/" target=_blank><font color=#419639><u>FeedSky</u></font></a>、<a href="http://www.feedburner.com/" target=_blank><font color=#419639><u>FeedBurner</u></font></a><br>RSS在线阅读：<a href="http://www.google.com/reader/" target=_blank><font color=#419639><u>Google Reader</u></font></a>、<a href="http://www.zhuaxia.com/" target=_blank><font color=#419639 dragover="true"><u>抓虾</u></font></a>、<a href="http://www.xianguo.com/" target=_blank><font color=#419639><u>鲜果</u></font></a><br>第三方统计服务：<a href="https://www.google.com/analytics/home/?hl=zh-CN" target=_blank><font color=#419639 dragover="true"><u>Google分析</u></font></a>、<a href="http://tongji.cn.yahoo.com/" target=_blank><font color=#419639><u>雅虎统计</u></font></a>、<a href="http://www.51.la/" target=_blank><font color=#419639><u>我要啦</u></font></a>、<a href="http://www.nasboq.com/" target=_blank><font color=#419639><u>纳斯博客</u></font></a><br>网络相册（允许外链）：<a href="http://www.yupoo.com/" target=_blank><font color=#419639><u>Yupoo</u></font></a>、<a href="http://www.bababian.com/" target=_blank><font color=#419639><u>巴巴变</u></font></a>、<a href="http://photo.mofile.com/" target=_blank><font color=#419639><u>Mofile</u></font></a>、<a href="http://footbig.com/" target=_blank><font color=#419639><u>大脚社区</u></font></a>、<a href="http://picasaweb.google.com/" target=_blank><font color=#419639><u>Google Picasa</u></font></a>、<a href="http://www.flickr.com/" target=_blank><font color=#419639><u>Flickr</u></font></a>、<a href="http://photobucket.com/" target=_blank><font color=#419639><u>Photobucket</u></font></a><br>Flash相册：<a href="http://www.slide.com/" target=_blank><font color=#419639 dragover="true"><u>Slide</u></font></a><br>网络硬盘：<a href="http://file.mofile.com/" target=_blank><font color=#419639><u>Mofile</u></font></a>、<a href="http://www.800disk.com/" target=_blank><font color=#419639><u>800Disk</u></font></a>、<a href="http://www.ys168.com/" target=_blank><font color=#419639><u>永硕E盘</u></font></a>、<a href="http://www.box.net/" target=_blank><font color=#419639><u>Box</u></font></a>、<a href="http://www.mybloop.com/" target=_blank><font color=#419639><u>My Bloop</u></font></a>、<a href="http://www.live-share.com/" target=_blank><font color=#419639><u>Live-Share</u></font></a><br>视频网站：<a href="http://www.tudou.com/" target=_blank><font color=#419639><u>土豆网</u></font></a>、<a href="http://www.youku.com/" target=_blank><font color=#419639><u>优酷网</u></font></a>、<a href="http://6.cn/" target=_blank><font color=#419639><u>六间房</u></font></a>、<a href="http://www.youtube.com/" target=_blank><font color=#419639><u>YouTube</u></font></a><br>代码高亮：<a href="http://www.fayaa.com/code" target=_blank><font color=#419639><u>代码发芽网</u></font></a></p>
<img src ="http://www.cppblog.com/hktk/aggbug/97954.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hktk/" target="_blank">海 阔 天 空</a> 2009-10-06 17:23 <a href="http://www.cppblog.com/hktk/archive/2009/10/06/97954.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++运算符优先级</title><link>http://www.cppblog.com/hktk/archive/2009/09/25/97190.html</link><dc:creator>海 阔 天 空</dc:creator><author>海 阔 天 空</author><pubDate>Thu, 24 Sep 2009 18:30:00 GMT</pubDate><guid>http://www.cppblog.com/hktk/archive/2009/09/25/97190.html</guid><description><![CDATA[<p>&nbsp;</p>
<table style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; FONT-SIZE: 10pt; BORDER-LEFT: black 1px solid; COLOR: #4b4b4b; BORDER-BOTTOM: black 1px solid; BORDER-COLLAPSE: collapse" borderColor=black cellSpacing=1 cellPadding=1 border=1>
    <tbody>
        <tr class=row0>
            <th class="col0 centeralign">Precedence </th>
            <th class="col1 centeralign">Operator </th>
            <th class="col2 centeralign">Description </th>
            <th class="col3 centeralign">Example </th>
            <th class="col4 centeralign">Overloadable </th>
            <th class="col5 centeralign">Associativity </th>
        </tr>
        <tr class=row1>
            <td class=col0>1</td>
            <td class=col1><code>::</code></td>
            <td class=col2>Scope resolution operator</td>
            <td class=col3>Class::age = 2;</td>
            <td class=col4>no</td>
            <td class=col5>none</td>
        </tr>
        <tr class=row2>
            <td class=col0>2</td>
            <td class=col1><code>()</code><br><code>()</code><br><code>[]</code><br><code>-&gt;</code><br><code>.</code><br><code>++</code><br><code>--</code><br><code>const_cast</code><br><code>dynamic_cast</code><br><code>static_cast</code><br><code>reinterpret_cast</code><br><code>typeid</code></td>
            <td class=col2>Function call<br>Member initalization <br>Array access<br>Member access from a pointer<br>Member access from an object<br>Post-increment<br>Post-decrement<br>Special cast<br>Special cast<br>Special cast<br>Special cast<br>Runtime type information</td>
            <td class=col3>isdigit('1')<br>c_tor(int x, int y) : _x(x), _y(y*10){};<br>array[4] = 2;<br>ptr-&gt;age = 34;<br>obj.age = 34;<br>for( int i = 0; i &lt; 10; i++ ) cout &lt;&lt; i;<br>for( int i = 10; i &gt; 0; i-- ) cout &lt;&lt; i;<br>const_cast&lt;type_to&gt;(type_from);<br>dynamic_cast&lt;type_to&gt;(type_from);<br>static_cast&lt;type_to&gt;(type_from);<br>reinterpret_cast&lt;type_to&gt;(type_from);<br>cout &#171; typeid(type).name();</td>
            <td class=col4>yes<br>yes<br>yes<br>yes<br>no<br>yes<br>yes<br>no<br>no<br>no<br>no<br>no</td>
            <td class=col5>left to right</td>
        </tr>
        <tr class=row3>
            <td class=col0>3</td>
            <td class=col1><code>!</code><br><code>not</code><br><code>~</code><br><code>compl</code><br><code>++</code><br><code>--</code><br><code>-</code><br><code>+</code><br><code>*</code><br><code>&amp;</code><br><code>new</code><br><code>new []</code><br><code>delete</code><br><code>delete []</code><br><code>(type)</code><br><code>sizeof</code></td>
            <td class=col2>Logical negation<br>Alternate spelling for ! <br>Bitwise complement<br>Alternate spelling for ~ <br>Pre-increment<br>Pre-decrement<br>Unary minus<br>Unary plus<br>Dereference<br>Address of<br>Dynamic memory allocation<br>Dynamic memory allocation of array<br>Deallocating the memory<br>Deallocating the memory of array<br>Cast to a given type<br>Return size of an object or type</td>
            <td class=col3>if( !done ) &#8230;<br><br>flags = ~flags;<br><br>for( i = 0; i &lt; 10; ++i ) cout &lt;&lt; i;<br>for( i = 10; i &gt; 0; --i ) cout &lt;&lt; i;<br>int i = -1;<br>int i = +1;<br>int data = *intPtr;<br>int *intPtr = &amp;data;<br>long *pVar = new long; <br>MyClass *ptr = new MyClass(args);<br>delete pVar;<br>delete [] array;<br>int i = (int) floatNum;\\int size = sizeof(float);</td>
            <td class=col4>yes<br><br>yes<br><br>yes<br>yes<br>yes<br>yes<br>yes<br>yes<br>yes<br>yes<br>yes<br>yes<br>yes<br>no</td>
            <td class=col5>right to left</td>
        </tr>
        <tr class=row4>
            <td class=col0>4</td>
            <td class=col1><code>-&gt;*</code><br><code>.*</code></td>
            <td class=col2>Member pointer selector<br>Member object selector</td>
            <td class=col3>ptr-&gt;*var = 24;<br>obj.*var = 24;</td>
            <td class=col4>yes<br>no</td>
            <td class=col5>left to right</td>
        </tr>
        <tr class=row5>
            <td class=col0>5</td>
            <td class=col1><code>*</code><br><code>/</code><br><code>%</code></td>
            <td class=col2>Multiplication<br>Division<br>Modulus</td>
            <td class=col3>int i = 2 * 4;<br>float f = 10.0 / 3.0;<br>int rem = 4 % 3;</td>
            <td class=col4>yes<br>yes<br>yes</td>
            <td class=col5>left to right</td>
        </tr>
        <tr class=row6>
            <td class=col0>6</td>
            <td class=col1><code>+</code><br><code>-</code></td>
            <td class=col2>Addition<br>Subtraction</td>
            <td class=col3>int i = 2 + 3;<br>int i = 5 - 1;</td>
            <td class=col4>yes<br>yes</td>
            <td class=col5>left to right</td>
        </tr>
        <tr class=row7>
            <td class=col0>7</td>
            <td class=col1><code>&lt;&lt;</code><br><code>&gt;&gt;</code></td>
            <td class=col2>Bitwise shift left<br>Bitwise shift right</td>
            <td class=col3>int flags = 33 &lt;&lt; 1;<br>int flags = 33 &gt;&gt; 1;</td>
            <td class=col4>yes<br>yes</td>
            <td class=col5>left to right</td>
        </tr>
        <tr class=row8>
            <td class=col0>8</td>
            <td class=col1><code>&lt;</code><br><code>&lt;=</code><br><code>&gt;</code><br><code>&gt;=</code></td>
            <td class=col2>Comparison less-than<br>Comparison less-than-or-equal-to<br>Comparison greater-than<br>Comparison greater-than-or-equal-to</td>
            <td class=col3>if( i &lt; 42 ) &#8230;<br>if( i &lt;= 42 ) ...<br>if( i &gt; 42 ) &#8230;<br>if( i &gt;= 42 ) ...</td>
            <td class=col4>yes<br>yes<br>yes<br>yes</td>
            <td class=col5>left to right</td>
        </tr>
        <tr class=row9>
            <td class=col0>9</td>
            <td class=col1><code>==</code><br><code>eq</code><br><code>!=</code><br><code>not_eq</code></td>
            <td class=col2>Comparison equal-to<br>Alternate spelling for == <br>Comparison not-equal-to<br>Alternate spelling for != </td>
            <td class=col3>if( i == 42 ) ...<br><br>if( i != 42 ) &#8230;<br></td>
            <td class=col4>yes<br>-<br>yes<br></td>
            <td class=col5>left to right</td>
        </tr>
        <tr class=row10>
            <td class=col0>10</td>
            <td class=col1><code>&amp;</code><br><code>bitand</code></td>
            <td class=col2>Bitwise AND<br>Alternate spelling for &amp; </td>
            <td class=col3>flags = flags &amp; 42;<br></td>
            <td class=col4>yes<br></td>
            <td class=col5>left to right</td>
        </tr>
        <tr class=row11>
            <td class=col0>11</td>
            <td class=col1><code>^</code><br><code>xor</code></td>
            <td class=col2>Bitwise exclusive OR (XOR)<br>Alternate spelling for ^ </td>
            <td class=col3>flags = flags ^ 42;<br></td>
            <td class=col4>yes<br></td>
            <td class=col5>left to right</td>
        </tr>
        <tr class=row12>
            <td class=col0>12</td>
            <td class=col1><code>|</code><br><code>bitor</code></td>
            <td class=col2>Bitwise inclusive (normal) OR<br>Alternate spelling for |</td>
            <td class=col3>flags = flags | 42;<br></td>
            <td class=col4>yes<br></td>
            <td class=col5>left to right</td>
        </tr>
        <tr class=row13>
            <td class=col0>13</td>
            <td class=col1><code>&amp;&amp;</code><br><code>and</code></td>
            <td class=col2>Logical AND<br>Alternate spelling for &amp;&amp; </td>
            <td class=col3>if( conditionA &amp;&amp; conditionB ) &#8230;<br></td>
            <td class=col4>yes<br></td>
            <td class=col5>left to right</td>
        </tr>
        <tr class=row14>
            <td class=col0>14</td>
            <td class=col1><code>||</code><br><code>or</code></td>
            <td class=col2>Logical OR<br>Alternate spelling for ||</td>
            <td class=col3>if( conditionA || conditionB ) ...<br></td>
            <td class=col4>yes<br></td>
            <td class=col5>left to right</td>
        </tr>
        <tr class=row15>
            <td class=col0>15</td>
            <td class=col1><code>? :</code></td>
            <td class=col2>Ternary conditional (if-then-else)</td>
            <td class=col3>int i = (a &gt; b) ? a : b;</td>
            <td class=col4>no</td>
            <td class=col5>right to left</td>
        </tr>
        <tr class=row16>
            <td class=col0>16</td>
            <td class=col1><code>=</code><br><code>+=</code><br><code>-=</code><br><code>*=</code><br><code>/=</code><br><code>%=</code><br><code>&amp;=</code><br><code>and_eq</code><br><code>^=</code><br><code>xor_eq</code><br><code>|=</code><br><code>or_eq</code><br><code>&lt;&lt;=</code><br><code>&gt;&gt;=</code></td>
            <td class=col2>Assignment operator<br>Increment and assign<br>Decrement and assign<br>Multiply and assign<br>Divide and assign<br>Modulo and assign<br>Bitwise AND and assign<br>Alternate spelling for &amp;= <br>Bitwise exclusive or (XOR) and assign<br>Alternate spelling for ^= <br>Bitwise normal OR and assign<br>Alternate spelling for |=<br>Bitwise shift left and assign<br>Bitwise shift right and assign</td>
            <td class=col3>int a = b;<br>a += 3;<br>b -= 4;<br>a *= 5;<br>a /= 2;<br>a %= 3;<br>flags &amp;= new_flags;<br><br>flags ^= new_flags;<br><br>flags |= new_flags;<br><br>flags &lt;&lt;= 2;<br>flags &gt;&gt;= 2;</td>
            <td class=col4>yes<br>yes<br>yes<br>yes<br>yes<br>yes<br>yes<br><br>yes<br><br>yes<br><br>yes<br>yes</td>
            <td class=col5>right to left</td>
        </tr>
        <tr class=row17>
            <td class=col0>17</td>
            <td class=col1><code>throw</code></td>
            <td class=col2>throw exception</td>
            <td class=col3>throw EClass(&#8220;Message&#8221;);</td>
            <td class=col4 colSpan=3>no</td>
        </tr>
        <tr class=row18>
            <td class=col0>18</td>
            <td class=col1><code>,</code></td>
            <td class=col2>Sequential evaluation operator</td>
            <td class=col3>for( i = 0, j = 0; i &lt; 10; i++, j++ ) &#8230;</td>
            <td class=col4>yes</td>
            <td class=col5>left to right</td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/hktk/aggbug/97190.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hktk/" target="_blank">海 阔 天 空</a> 2009-09-25 02:30 <a href="http://www.cppblog.com/hktk/archive/2009/09/25/97190.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HTML表格线</title><link>http://www.cppblog.com/hktk/archive/2009/09/25/97189.html</link><dc:creator>海 阔 天 空</dc:creator><author>海 阔 天 空</author><pubDate>Thu, 24 Sep 2009 18:25:00 GMT</pubDate><guid>http://www.cppblog.com/hktk/archive/2009/09/25/97189.html</guid><description><![CDATA[<table style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; FONT-SIZE: 10pt; BORDER-LEFT: black 1px solid; COLOR: black; BORDER-BOTTOM: black 1px solid; BORDER-COLLAPSE: collapse" borderColor=black cellSpacing=1 cellPadding=1 border=1>
    <tbody>
        <tr>
            <td>测试1</td>
            <td>测试2</td>
            <td>测试3</td>
        </tr>
        <tr>
            <td>测试4</td>
            <td>测试5</td>
            <td>测试6</td>
        </tr>
    </tbody>
</table>
&lt;TABLE border=1 cellpadding=1 cellspacing=1 bordercolor="black" style="border:1px solid black; border-collapse:collapse; color:black; font-size:10pt;"&gt;<br>&lt;TR&gt;<br>&nbsp;&lt;TD&gt;测试1&lt;/TD&gt;<br>&nbsp;&lt;TD&gt;测试2&lt;/TD&gt;<br>&nbsp;&lt;TD&gt;测试3&lt;/TD&gt;<br>&lt;/TR&gt;<br>&lt;TR&gt;<br>&nbsp;&lt;TD&gt;测试4&lt;/TD&gt;<br>&nbsp;&lt;TD&gt;测试5&lt;/TD&gt;<br>&nbsp;&lt;TD&gt;测试6&lt;/TD&gt;<br>&lt;/TR&gt;<br>&lt;/TABLE&gt;<br><br>border=1 cellpadding=1 cellspacing=1 bordercolor="black" style="border:1px solid black; border-collapse:collapse; color:black; font-size:10pt;"<br>border=1 cellpadding=1 cellspacing=1 bordercolor="black" style="border:1px solid black; border-collapse:collapse; color:color:#4B4B4B; font-size:10pt;"<br><br>
<img src ="http://www.cppblog.com/hktk/aggbug/97189.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hktk/" target="_blank">海 阔 天 空</a> 2009-09-25 02:25 <a href="http://www.cppblog.com/hktk/archive/2009/09/25/97189.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SuperPi的幕后细节</title><link>http://www.cppblog.com/hktk/archive/2009/09/24/97148.html</link><dc:creator>海 阔 天 空</dc:creator><author>海 阔 天 空</author><pubDate>Thu, 24 Sep 2009 10:12:00 GMT</pubDate><guid>http://www.cppblog.com/hktk/archive/2009/09/24/97148.html</guid><description><![CDATA[&nbsp;不可否认，SuperPi历史非常悠久，用的人之多，其他同类软件难以匹敌。但是对其有更多了解的人却很少，下面这些细节你可能都不知道：<br><br><font color=blue>1.SuperPi发布日期是平成７年（1996年）</font><br><br><font size=1>2.[もとのプログラムはFORTRANで書かれていますが、それをC言語に書き直しました。</font><br><font color=blue>原计划使用Fortran编写，最后使用C语言编写</font><br><br><font size=1>3.ガウス・ルジャンドルのアルゴリズムを採用しています</font><br><font color=blue>采用Gauss-Legendre算法</font><br><br><font color=blue>4.创造纪录使用的大型机器是HITAC&nbsp;S-3800/480(95年的配置啊，当时看来可是绝对地强悍啊):<br>　主記憶容量　　　&nbsp;：1792.75&nbsp;MB&nbsp;（主内存)<br>　拡張記憶容量　　&nbsp;：25120&nbsp;MB&nbsp;&nbsp;（扩展内存）</font><br><font color=red>アルゴリズム　　&nbsp;：ボールウェインの&nbsp;4&nbsp;次の収束アルゴリズム</font><br>使用算法：Borwein四次迭代算法<br><br><font color=red>注意!和SuperPi所用的算法并不相同！！<br>许多人都知道，开发SuperPi的作者用大型机跑出了42亿位的纪录，且都认为使用是和SuperPI一样的算法，但是事实并非如此！大家都是在以讹传讹！</font><br><br><font color=blue>6.Pentium&nbsp;66MHz计算104万位需要</font>&nbsp;<font color=maroon>1小时13分22秒</font><br><font color=blue>HITAC&nbsp;S-3800/480计算104万位大约只需要</font><font color=red>5秒</font>!<br><font color=blue>Pentium&nbsp;66MHz计算3355万位需要</font>&nbsp;<font color=maroon>105小时35分17秒</font><br><font color=blue>HITAC&nbsp;S-3800/480计算3355万位大约只需要</font><font color=red>4分钟</font>!<br><br>注意：由于使用算法和软件环境不同，大型机和PC没有绝对地可比性，况且还是95年的大型机，但是其性能优异在一定程度上是可以肯定的。<br>硬件和软件的发展都是很惊人的，1986年9月，创造42亿位纪录者之一的金田用HITAC&nbsp;S-810/20计算了3355万Pi值，这在当时就是一个世界记录了！但同年10月他们就把记录提高一倍到6千7百万位。<br>我用QPI使用SuperPi的AGM算法计算3355万位，花了3分47秒就完成了，就算是体验到当年大型机的速度了吧<img src="http://www1.pconline.com.cn/itbbs/080506/old/emot//em301.gif"><br><br><br><font color=blue>7.关于Gauss-Legendre算法和Borwein四次迭代算法,SuperPI也给出了详细的介绍：</font><br><br>SuperPI所采用的Gauss-Legendre算法：（PS:又叫做AGM算法（Arithmetic-Geometric&nbsp;Mean））<br>１．初值确定<br>　　&nbsp;a&nbsp;=&nbsp;1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b&nbsp;=&nbsp;1&nbsp;/&nbsp;sqrt(&nbsp;2&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t&nbsp;=&nbsp;1&nbsp;/&nbsp;4<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;=&nbsp;1<br><br>２．&nbsp;a与b都取同样的精度，反复迭代计算下式：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y&nbsp;=&nbsp;a<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a&nbsp;=&nbsp;(&nbsp;a&nbsp;＋&nbsp;b&nbsp;)&nbsp;/&nbsp;2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b&nbsp;=&nbsp;sqrt(&nbsp;b&nbsp;･&nbsp;y&nbsp;)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t&nbsp;=&nbsp;t&nbsp;－&nbsp;x&nbsp;･&nbsp;(&nbsp;y&nbsp;－&nbsp;a&nbsp;)^2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;=&nbsp;2&nbsp;･&nbsp;x<br><br>３．a和b迭代到足够精度后，根据下式可以计算出PI值<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Pi&nbsp;=&nbsp;(&nbsp;a&nbsp;＋&nbsp;b&nbsp;)^2&nbsp;/&nbsp;(&nbsp;4&nbsp;･&nbsp;t&nbsp;)<br><br><font color=red>这个公式的特点是每迭代一次将得到比前一次迭代高一倍的精度，所以要计算104万位(2的22次方)，迭代19次就够了，这就是为什么SuperPi的计算为数都是以2的倍数递增，且计算时会出现一条条的纪录，这就是每一次迭代所花费的时间！理论上每次花费的时间都应该是完全相同的。比较可笑的是 SuperPi&nbsp;MOD版本的汉化翻译，把19次迭代翻译成需要重复计算19次，明显存在着理解上的错误。</font><br><br>计算42亿位的巨型机所使用的Borwein四次迭代式：<br>１．初值确定：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a[0]&nbsp;=&nbsp;6&nbsp;－&nbsp;4&nbsp;･&nbsp;sqrt(&nbsp;2&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y[0]&nbsp;=&nbsp;sqrt(&nbsp;2&nbsp;)&nbsp;－&nbsp;1<br>&nbsp;&nbsp;&nbsp;<br>２．&nbsp;反复计算下式，提高精度<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y[k+1]&nbsp;=&nbsp;{&nbsp;1-(1-y[k]^4&nbsp;)^(1/4)&nbsp;}&nbsp;/&nbsp;{&nbsp;1+(1-y[k]^4)^(1/4)&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a[k+1]&nbsp;=&nbsp;a[k]･(1+y[k+1])^4&nbsp;-&nbsp;2^(2･k＋3)･y[k+1]･(1+y[k+1]+y[k+1]^2)<br>&nbsp;&nbsp;<br>３．当a[n]和b[n]达到足够精度后，可以确定Pi值<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Pi&nbsp;=&nbsp;1&nbsp;/&nbsp;a[n]<br>所以可以看出，该公式首先算出其实是Pi的倒数，算出a[n]后，要做一个&#8220;巨型&#8221;的除法才能得到真正的Pi值<br><br>另一方面必须要认识到，SuperPi的编写年代久远，现在看来实现的效率非常低。Qpi即使用完全同样的算法，在我的E6300机器上只需3.37秒就完成了104万位的计算的19次迭代！<br>计算过程(QPI4.5版&nbsp;使用-agm3参数，<font color=red>和SuperPi完全相同算法</font>&nbsp;E6300未超频&nbsp;Vista环境&nbsp;)：<br>Starting&nbsp;1st&nbsp;&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.13<br>Starting&nbsp;2nd&nbsp;&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.19<br>Starting&nbsp;3rd&nbsp;&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.17<br>Starting&nbsp;4th&nbsp;&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.19<br>Starting&nbsp;5th&nbsp;&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.19<br>Starting&nbsp;6th&nbsp;&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.19<br>Starting&nbsp;7th&nbsp;&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.17<br>Starting&nbsp;8th&nbsp;&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.19<br>Starting&nbsp;9th&nbsp;&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.17<br>Starting&nbsp;10th&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.19<br>Starting&nbsp;11th&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.17<br>Starting&nbsp;12th&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.19<br>Starting&nbsp;13th&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.19<br>Starting&nbsp;14th&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.17<br>Starting&nbsp;15th&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.19<br>Starting&nbsp;16th&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.19<br>Starting&nbsp;17th&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.17<br>Starting&nbsp;18th&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.17<br>Starting&nbsp;19th&nbsp;iteration,&nbsp;time&nbsp;:&nbsp;0.17<br><br>Total&nbsp;iteration&nbsp;time&nbsp;:&nbsp;3.37<br>Computing&nbsp;final&nbsp;value,&nbsp;time&nbsp;:&nbsp;0.14<br><br><font color=red>Total&nbsp;time&nbsp;:&nbsp;3.56&nbsp;seconds</font><br>Total&nbsp;memory&nbsp;used&nbsp;:&nbsp;12,003,171&nbsp;(11.45&nbsp;MB)<br><br>Processor&nbsp;utilization&nbsp;:&nbsp;128.98%<br><br>CPU 利用率达到了128.98%说明其利用了第二个核心的28.98%的效率，发挥了了一定的双核优势，但即使是完全单核执行应该也不会慢到哪里去，比起 SuperPi漫长的30秒计算几乎达到了10倍速，而这个成绩也比超频榜上的那些个发烫的成绩要快得多了，如果使用最快的chudnovsky算法，只要1.5秒便结束了104万的战斗....如果换成超频榜上的那些牛机，只需零点几秒便解决了！<br><br>不知道用SuperPi的人中有几个人知道Pifast，有几个知道Qpi，还有几个人两个都知道的<br><br>SuperPi在历史舞台上的地位是永远存在的，但是考验CPU速度，还是换更先进的算法和程序感觉会更好，更能体验飞速的感觉！看着SuperPi的排行榜，我仿佛看到了喷火的跑车发动机装在了拖拉机上...<br><br>你真的老了SuperPi...<br>别了SuperPi.... 
<img src ="http://www.cppblog.com/hktk/aggbug/97148.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hktk/" target="_blank">海 阔 天 空</a> 2009-09-24 18:12 <a href="http://www.cppblog.com/hktk/archive/2009/09/24/97148.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++宏定义</title><link>http://www.cppblog.com/hktk/archive/2009/09/21/96874.html</link><dc:creator>海 阔 天 空</dc:creator><author>海 阔 天 空</author><pubDate>Mon, 21 Sep 2009 11:06:00 GMT</pubDate><guid>http://www.cppblog.com/hktk/archive/2009/09/21/96874.html</guid><description><![CDATA[C++提供的编译预处理功能主要有以下三种：<br>
<div class=spctrl></div>
　　（一） 宏定义<br>
<div class=spctrl></div>
　　（二） 文件包含<br>
<div class=spctrl></div>
　　（三） 条件编译<br>
<div class=spctrl></div>
　　在C++中，我们一般用const定义符号常量。很显然，用const定义常量比用define定义常量更好。<br>
<div class=spctrl></div>
　　在使用宏定义时应注意的是：<br>
<div class=spctrl></div>
　　（a） 在书写#define 命令时，注意&lt;宏名&gt;和&lt;字符串&gt;之间用空格分开，而不是用等号连接。<br>
<div class=spctrl></div>
　　（b） 使用#define定义的标识符不是变量，它只用作宏替换，因此不占有内存。<br>
<div class=spctrl></div>
　　（c） 习惯上用大写字母表示&lt;宏名&gt;，这只是一种习惯的约定，其目的是为了与变量名区分，因为变量名<br>
<div class=spctrl></div>
　　通常用小写字母。<br>
<div class=spctrl></div>
　　如果某一个标识符被定义为宏名后，在取消该宏定义之前，不允许重新对它进行宏定义。取消宏定义使用如下命令：<br>
<div class=spctrl></div>
　　#undef&lt;标识符&gt;<br>
<div class=spctrl></div>
　　其中，undef是关键字。该命令的功能是取消对&lt;标识符&gt;已有的宏定义。被取消了宏定义的标识符，可以对它重新进行定义。<br>
<div class=spctrl></div>
　　宏定义可以嵌套，已被定义的标识符可以用来定义新的标识符。例如：<br>
<div class=spctrl></div>
　　#define PI 3.14159265<br>
<div class=spctrl></div>
　　#define R 10<br>
<div class=spctrl></div>
　　#define AREA (PI*R*R)<br>
<div class=spctrl></div>
　　单的宏定义将一个标识符定义为一个字符串，源程序中的该标识符均以指定的字符串来代替。前面已经说过，预处理命令不同于一般C++语句。因此预处理命令后通常不加分号。这并不是说所有的预处理命令后都不能有分号出现。由于宏定义只是用宏名对一个字符串进行简单的替换，因此如果在宏定义命令后加了分号，将会连同分号一起进行置换。<br>
<div class=spctrl></div>
　　带参数的宏定义<br>
<div class=spctrl></div>
　　带参数的宏定义的一般形式如下：<br>
<div class=spctrl></div>
　　#define &lt;宏名&gt;（&lt;参数表&gt;） &lt;宏体&gt;<br>
<div class=spctrl></div>
　　其中， &lt;宏名&gt;是一个标识符，&lt;参数表&gt;中的参数可以是一个，也可以是多个，视具体情况而定，当有多个参数的时候，每个参数之间用逗号分隔。&lt;宏体&gt;是被替换用的字符串，宏体中的字符串是由参数表中的各个参数组成的表达式。例如：<br>
<div class=spctrl></div>
　　#define SUB(a,b) a-b<br>
<div class=spctrl></div>
　　如果在程序中出现如下语句：<br>
<div class=spctrl></div>
　　result=SUB(2, 3)<br>
<div class=spctrl></div>
　　则被替换为：<br>
<div class=spctrl></div>
　　result=2-3；<br>
<div class=spctrl></div>
　　如果程序中出现如下语句：<br>
<div class=spctrl></div>
　　result= SUB（x+1, y+2）;<br>
<div class=spctrl></div>
　　则被替换为：<br>
<div class=spctrl></div>
　　result=x+1-y+2;<br>
<div class=spctrl></div>
　　在这样的宏替换过程中，其实只是将参数表中的参数代入到宏体的表达式中去，上述例子中，即是将表达式中的a和b分别用2和3代入。<br>
<div class=spctrl></div>
　　我们可以发现：带参的宏定义与函数类似。如果我们把宏定义时出现的参数视为形参，而在程序中引用宏定义时出现的参数视为实参。那么上例中的a和b就是形参，而2和3以及x+1和y+2都为实参。在宏替换时，就是用实参来替换&lt;宏体&gt;中的形参。<br>
<div class=spctrl></div>
　　在使用带参数的宏定义时需要注意的是：<br>
<div class=spctrl></div>
　　（1）带参数的宏定义的&lt;宏体&gt;应写在一行上，如果需要写在多行上时，在每行结束时，使用续行符 "\"结<br>
<div class=spctrl></div>
　　束，并在该符号后按下回车键，最后一行除外。<br>
<div class=spctrl></div>
　　（2）在书写带参数的宏定义时，&lt;宏名&gt;与左括号之间不能出现空格，否则空格右边的部分都作为宏体。<br>
<div class=spctrl></div>
　　例如：<br>
<div class=spctrl></div>
　　#define ADD (x,y) x+y<br>
<div class=spctrl></div>
　　将会把"（x,y）x+y"的一个整体作为被定义的字符串。<br>
<div class=spctrl></div>
　　（3）定义带参数的宏时，宏体中与参数名相同的字符串适当地加上圆括号是十分重要的，这样能够避免<br>
<div class=spctrl></div>
　　可能产生的错误。例如,对于宏定义：<br>
<div class=spctrl></div>
　　#define SQ(x) x*x<br>
<div class=spctrl></div>
　　当程序中出现下列语句：<br>
<div class=spctrl></div>
　　m=SQ(a+b);<br>
<div class=spctrl></div>
　　替换结果为：<br>
<div class=spctrl></div>
　　m=a+b*a+b;<br>
<div class=spctrl></div>
　　这可能不是我们期望的结果，如果需要下面的替换结果：<br>
<div class=spctrl></div>
　　m=(a+b)*(a+b);<br>
<div class=spctrl></div>
　　应将宏定义修改为：<br>
<div class=spctrl></div>
　　#define SQ(x) (x)*(x) <br>
<div class=spctrl></div>
　　对于带参的宏定义展开置换的方法是：在程序中如果有带实参的宏（如"SUB（2,3）"），则按"#define"命令行中指定的字符串从左到右进行置换。如果串中包含宏中的形参（如a、b），则将程序语句中相应的实参（可以是常量、变量或者表达式）代替形参，如果宏定义中的字符串中的字符不是参数字符（如a-b中的-号），则保留。这样就形成了置换的字符串。
<img src ="http://www.cppblog.com/hktk/aggbug/96874.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hktk/" target="_blank">海 阔 天 空</a> 2009-09-21 19:06 <a href="http://www.cppblog.com/hktk/archive/2009/09/21/96874.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何理解C和C++的复杂类型声明</title><link>http://www.cppblog.com/hktk/archive/2009/09/21/96873.html</link><dc:creator>海 阔 天 空</dc:creator><author>海 阔 天 空</author><pubDate>Mon, 21 Sep 2009 11:04:00 GMT</pubDate><guid>http://www.cppblog.com/hktk/archive/2009/09/21/96873.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 曾经碰到过让你迷惑不解、类似于int * (* (*fp1) (int) ) [10];这样的变量声明吗？本文将由易到难，一步一步教会你如何理解这种复杂的C/C++声明。 　　我们将从每天都能碰到的较简单的声明入手，然后逐步加入const修饰符和typedef，还有函数指针，最后介绍一个能够让你准确地理解任何C/C++声明的&#8220;右左法则&#8221;。 　　需要强调一下的是，复杂的C/C...&nbsp;&nbsp;<a href='http://www.cppblog.com/hktk/archive/2009/09/21/96873.html'>阅读全文</a><img src ="http://www.cppblog.com/hktk/aggbug/96873.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hktk/" target="_blank">海 阔 天 空</a> 2009-09-21 19:04 <a href="http://www.cppblog.com/hktk/archive/2009/09/21/96873.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sizeof 操作符详解</title><link>http://www.cppblog.com/hktk/archive/2009/09/21/96872.html</link><dc:creator>海 阔 天 空</dc:creator><author>海 阔 天 空</author><pubDate>Mon, 21 Sep 2009 11:01:00 GMT</pubDate><guid>http://www.cppblog.com/hktk/archive/2009/09/21/96872.html</guid><description><![CDATA[<p><strong>1. 定义：</strong> <br><strong>sizeof是何方神圣？</strong> <br>sizeof 乃 C/C++ 中的一个操作符（operator）是也。简单说其作用就是返回一个对象或者类型所占的内存字节数。 <br>MSDN上的解释为： <br>The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type (including aggregate types).This keyword returns a value of type size_t. <br>其返回值类型为size_t，在头文件stddef.h中定义。这是一个依赖于编译系统的值，一般定义为 <br>typedef unsigned int size_t; <br>世上编译器林林总总，但作为一个规范，它们都会保证char、signed char和unsigned char的sizeof值为1，毕竟char是我们编程能用的最小数据类型。</p>
<p><br><strong>2. 语法：</strong> <br>sizeof有三种语法形式，如下： <br>1) sizeof( object ); // sizeof( 对象 ); <br>2) sizeof( type_name ); // sizeof( 类型 ); <br>3) sizeof object; // sizeof 对象; <br>所以， <br>int i; <br>sizeof( i ); // ok <br>sizeof i; // ok <br>sizeof( int ); // ok <br>sizeof int; // error <br>既然写法2可以用写法1代替，为求形式统一以及减少我们大脑的负担，第2种写法，忘掉它吧！ <br>实际上，sizeof计算对象的大小也是转换成对对象类型的计算。也就是说，同种类型的不同对象其sizeof值都是一致的。 <br>这里，对象可以进一步延伸至表达式，即sizeof可以对一个表达式求值。编译器<strong>根据表达式的最终结果类型来确定大小</strong>，一般不会对表达式进行计算。 <br>例如： <br>sizeof( 2 ); // 2的类型为int，所以等价于 sizeof( int ); <br>sizeof( 2 + 3.14 ); // 3.14的类型为double，2也会被提升成double类型，所以等价于 sizeof( double ); <br>sizeof也可以对一个函数调用求值，其结果是函数返回类型的大小，函数并不会被调用。我们来看一个完整的例子： <br>********************************************************* <br>char foo() <br>{ <br>printf("foo() has been called.\n"); <br>return 'a'; <br>} <br>int main() <br>{ <br>size_t sz = sizeof( foo() ); // foo() 的返回值类型为char，所以sz = sizeof(char)，但函数foo()并不会被调用 <br>printf("sizeof( foo() ) = %d\n", sz); <br>} <br>********************************************************* <br>C99标准规定，函数、不能确定类型的表达式以及位域（bit-field）成员不能被计算sizeof值，即下面这些写法都是错误的： <br>sizeof( foo ); // error <br>void foo2() { } <br>sizeof( foo2() ); // error <br>struct S <br>{ <br>unsigned int f1 : 1; <br>unsigned int f2 : 5; <br>unsigned int f3 : 12; <br>}; <br>sizeof( S.f1 ); // error</p>
<p><br><strong>3. sizeof的常量性</strong> <br>sizeof的计算发生在编译时刻，所以它可以被当作常量表达式使用。如： <br>char ary[ sizeof( int ) * 10 ]; // ok <br>最新的C99标准规定sizeof也可以在运行时刻进行计算。如下面的程序在Dev-C++中可以正确执行： <br>int n; <br>n = 10; // n动态赋值 <br>char ary[n]; // C99也支持数组的动态定义 <br>printf("%d\n", sizeof(ary)); // ok. 输出10 <br>但在没有完全实现C99标准的编译器中就行不通了，上面的代码在VC6中就通不过编译。所以我们最好还是认为sizeof是在编译期执行的，这样不会带来错误，让程序的可移植性强些。</p>
<p><br><strong>4. 基本数据类型的sizeof</strong> <br>这里的基本数据类型指short、int、long、float、double这样的简单内置数据类型。由于它们都是和系统相关的，所以在不同的系统下取值可能不同。这务必引起我们的注意，尽量不要在这方面给自己程序的移植造成麻烦。 <br>一般的，在32位编译环境中，sizeof(int)的取值为4。</p>
<p><br><strong>5. 指针变量的sizeof</strong> <br>学过数据结构的你应该知道指针是一个很重要的概念，它记录了另一个对象的地址。既然是来存放地址的，那么它当然等于计算机内部地址总线的宽度。所以在32 位计算机中，一个指针变量的返回值必定是4（注意结果是以字节为单位）。可以预计，在将来的64位系统中指针变量的sizeof结果为8。 <br>********************************************************* <br>char* pc = "abc"; <br>int* pi; <br>string* ps; <br>char** ppc = &amp;pc; <br>void (*pf)(); // 函数指针 <br>sizeof( pc ); // 结果为4 <br>sizeof( pi ); // 结果为4 <br>sizeof( ps ); // 结果为4 <br>sizeof( ppc );// 结果为4 <br>sizeof( pf ); // 结果为4 <br>********************************************************* <br>指针变量的sizeof值与指针所指的对象没有任何关系，正是由于所有的指针变量所占内存大小相等，所以MFC消息处理函数使用两个参数WPARAM、LPARAM就能传递各种复杂的消息结构（使用指向结构体的指针）。</p>
<p><br><strong>6. 数组的sizeof</strong> <br>数组的sizeof值等于数组所占用的内存字节数，如： <br>char a1[] = "abc"; <br>int a2[3]; <br>sizeof( a1 ); // 结果为4，字符 末尾还存在一个NULL终止符 <br>sizeof( a2 ); // 结果为3*4=12（依赖于int） <br>一些朋友刚开始时把sizeof当作了求数组元素的个数，现在，你应该知道这是不对的。那么应该怎么求数组元素的个数呢？ <br>Easy，通常有下面两种写法： <br>int c1 = sizeof( a1 ) / sizeof( char ); // 总长度/单个元素的长度 <br>int c2 = sizeof( a1 ) / sizeof( a1[0]); // 总长度/第一个元素的长度 <br>写到这里，提一问，下面的c3，c4值应该是多少呢？ <br>********************************************************* <br>void foo3(char a3[3]) <br>{ <br>int c3 = sizeof( a3 ); // c3 == <br>} <br>void foo4(char a4[]) <br>{ <br>int c4 = sizeof( a4 ); // c4 == <br>} <br>********************************************************* <br>也许当你试图回答c4的值时已经意识到c3答错了，是的，c3!=3。 <br>这里函数参数a3已不再是数组类型，而是蜕变成指针。相当于char* a3，为什么仔细想想就不难明白。 <br>我们调用函数foo1时，程序会在栈上分配一个大小为3的数组吗？不会！ <br>数组是&#8220;传址&#8221;的，调用者只需将实参的地址传递过去，所以a3自然为指针类型（char*），c3的值也就为4。</p>
<p><br><strong>7. 结构体的sizeof</strong> <br>这是初学者问得最多的一个问题，所以这里有必要多费点笔墨。让我们先看一个结构体： <br>struct S1 <br>{ <br>char c; <br>int i; <br>}; <br>问sizeof(s1)等于多少？ <br>聪明的你开始思考了，char占1个字节，int占4个字节，那么加起来就应该是5。 <br>是这样吗？ <br>你在你机器上试过了吗？ <br>也许你是对的，但很可能你是错的！ <br>VC6中按默认设置得到的结果为8。 <br>Why？为什么受伤的总是我？ <br>请不要沮丧，我们来好好琢磨一下sizeof的定义 —— sizeof的结果等于对象或者类型所占的内存字节数。好吧，那就让我们来看看S1的内存分配情况： <br>S1 s1 = { 'a', 0xFFFFFFFF }; <br>定义上面的变量后，加上断点，运行程序，观察s1所在的内存，你发现了什么？ <br>以我的VC6.0为例，s1的地址为0x0012FF78，其数据内容如下： <br>0012FF78: 61 CC CC CC FF FF FF FF <br>发现了什么？怎么中间夹杂了3个字节的CC？ <br>看看MSDN上的说明： <br>When applied to a structure type or variable, sizeof returns the actual size, which may include padding bytes inserted for alignment. <br>原来如此，这就是传说中的字节对齐啊！一个重要的话题出现了。 <br>为什么需要字节对齐？ <br>计算机组成原理教导我们，这样有助于加快计算机的取数速度，否则就得多花指令周期了。 <br>为此，编译器默认会对结构体进行处理（实际上其它地方的数据变量也是如此），让宽度为2的基本数据类型（short等）都位于能被2整除的地址上，让宽度为4的基本数据类型（int等）都位于能被4整除的地址上。以此类推，这样，两个数中间就可能需要加入填充字节，所以整个结构体的sizeof值就增长了。 <br>让我们交换一下S1中char与int的位置： <br>struct S2 <br>{ <br>int i; <br>char c; <br>}; <br>看看sizeof(S2)的结果为多少？怎么还是8。 <br>再看看内存，原来成员c后面仍然有3个填充字节。 <br>这又是为什么啊？别着急，下面总结规律。</p>
<p><br><strong>字节对齐的细节和编译器实现相关，但一般而言，满足三个准则：</strong> <br>1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除； <br>2) 结构体每个成员相对于结构体首地址的偏移量（offset）都是成员大小的整数倍，如有需要编译器会在成员之间加上填充字节（internal adding）； <br>3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍，如有需要编译器会在最末一个成员之后加上填充字节（trailing padding）。</p>
<p><br>对于上面的准则，有几点需要说明： <br>1) 前面不是说结构体成员的地址是其大小的整数倍，怎么又说到偏移量了呢？ <br>因为有了第1点存在，所以我们就可以只考虑成员的偏移量，这样思考起来简单。想想为什么。 <br>结构体某个成员相对于结构体首地址的偏移量可以通过宏offsetof()来获得，这个宏也在stddef.h中定义，如下：<br>#define offsetof(s,m) (size_t)&amp;(((s *)0)-&gt;m) <br>例如，想要获得S2中c的偏移量，方法为 <br>size_t pos = offsetof(S2, c);// pos等于4</p>
<p><br>2) 基本类型是指前面提到的像char、short、int、float、double这样的内置数据类型。这里所说的&#8220;数据宽度&#8221;就是指其sizeof的大小。由于结构体的成员可以是复合类型，比如另外一个结构体，所以在寻找最宽基本类型成员时，应当包括复合类型成员的子成员，而不是把复合成员看成是一个整体。但在确定复合类型成员的偏移位置时则是将复合类型作为整体看待。 <br>这里叙述起来有点拗口，思考起来也有点挠头，还是让我们看看例子吧（具体数值仍以VC6为例，以后不再说明）： <br>struct S3 <br>{ <br>char c1; <br>S1 s; <br>char c2; <br>}; <br>S1的最宽简单成员的类型为int，S3在考虑最宽简单类型成员时是将S1&#8220;打散&#8221;看的，所以S3的最宽简单类型为int。这样，通过S3定义的变量，其存储空间首地址需要被4整除，整个sizeof(S3)的值也应该被4整除。 <br>c1的偏移量为0，s的偏移量呢？这时s是一个整体，它作为结构体变量也满足前面三个准则，所以其大小为8，偏移量为4，c1与s之间便需要3个填充字节，而c2与s之间就不需要了，所以c2的偏移量为12，算上c2的大小为13，13是不能被4整除的，这样末尾还得补上3个填充字节。最后得到 sizeof(S3)的值为16。</p>
<p>通过上面的叙述，我们可以得到一个公式： <br><strong>结构体的大小等于最后一个成员的偏移量加上其大小再加上末尾的填充字节数目，</strong>即： <br>sizeof( struct ) = offsetof( last item ) + sizeof( last item ) + sizeof( trailing padding )</p>
<p><br><strong>8.类的sizeof</strong> <br><br>类的sizeof值等于类中成员变量所占用的内存字节数。如： <br>**************************************************************** <br><br>class A <br>{ <br>public: <br>int b; <br>float c; <br>char d; <br>}; <br>int main(void) <br>{ <br>A object; <br>cout &lt;&lt;"sizeof(object) is "&lt; return 0 ; <br>} <br><br>*************************************************************** <br><br><br>输出结果为12（我的机器上sizeof(float)值为4，字节对其前面已经讲过）。 <br><br>不过需要注意的是，如果类中存在静态成员变量，结果又会是什么样子呢？ <br><br>*************************************************************** <br>class A <br>{ <br>public: <br>static int a; <br>int b; <br>float c; <br>char d; <br>}; <br>int main() <br>{ <br>A object; <br>cout &lt;&lt;"sizeof(object) is "&lt; return 0 ; <br>} <br><br>************************************************************** <br><br><br>16？不对。结果仍然是12. <br>因为在程序编译期间，就已经为static变量在静态存储区域分配了内存空间，并且这块内存在程序的整个运行期间都存在。 <br>而每次声明了类A的一个对象的时候，为该对象在堆上，根据对象的大小分配内存。 <br><br>如果类A中包含成员函数，那么又会是怎样的情况呢？看下面的例子 <br><br>************************************************************* <br>class A <br>{ <br>public: <br>static int a; <br>int b; <br>float c; <br>char d; <br>int add(int x,int y) <br>{ <br>return x+y; <br>} <br>}; <br>int main() <br>{ <br>A object; <br>cout &lt;&lt;"sizeof(object) is "&lt; b = object.add(3,4); <br>cout &lt;&lt;"sizeof(object) is "&lt; return 0 ; <br>} <br><br>*************************************************************** <br><br>结果仍为12。 <br><br>因为只有非静态类成员变量在新生成一个object的时候才需要自己的副本。 <br>所以每个非静态成员变量在生成新object需要内存，而function是不需要的。 <br><br>注：C++中的多态和虚继承也是非常重要的东西，不过比较复杂，编译器不同，细节也有所不同。 </p>
<img src ="http://www.cppblog.com/hktk/aggbug/96872.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hktk/" target="_blank">海 阔 天 空</a> 2009-09-21 19:01 <a href="http://www.cppblog.com/hktk/archive/2009/09/21/96872.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 文件操作详解</title><link>http://www.cppblog.com/hktk/archive/2009/09/21/96871.html</link><dc:creator>海 阔 天 空</dc:creator><author>海 阔 天 空</author><pubDate>Mon, 21 Sep 2009 10:59:00 GMT</pubDate><guid>http://www.cppblog.com/hktk/archive/2009/09/21/96871.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: C++ 通过以下几个类支持文件的输入输出：    ofstream: 写操作（输出）的文件类 (由ostream引申而来)     ifstream: 读操作（输入）的文件类(由istream引申而来)     fstream: 可同时读写操作的文件类 (由iostream引申而来) &nbsp;打开文件(Open a file)对这些类的一个对象所做的第一个操作通...&nbsp;&nbsp;<a href='http://www.cppblog.com/hktk/archive/2009/09/21/96871.html'>阅读全文</a><img src ="http://www.cppblog.com/hktk/aggbug/96871.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hktk/" target="_blank">海 阔 天 空</a> 2009-09-21 18:59 <a href="http://www.cppblog.com/hktk/archive/2009/09/21/96871.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ *p++,*++p,++*p</title><link>http://www.cppblog.com/hktk/archive/2009/09/21/96870.html</link><dc:creator>海 阔 天 空</dc:creator><author>海 阔 天 空</author><pubDate>Mon, 21 Sep 2009 10:56:00 GMT</pubDate><guid>http://www.cppblog.com/hktk/archive/2009/09/21/96870.html</guid><description><![CDATA[<p>#include &lt;iostream.h&gt;<br>int main(){<br>&nbsp;char s[] = "012345678", *p = s;</p>
<p>&nbsp;cout &lt;&lt; *p++ &lt;&lt; *(p++) &lt;&lt; (*p)++ &lt;&lt; *++p &lt;&lt; *(++p) &lt;&lt;++*p &lt;&lt; ++(*p) &lt;&lt; endl;<br>&nbsp;<br>&nbsp;p = s;<br>&nbsp;cout &lt;&lt; *p++ &lt;&lt; endl;<br>&nbsp;cout &lt;&lt; *(p++) &lt;&lt; endl;<br>&nbsp;cout &lt;&lt; (*p)++ &lt;&lt; endl;<br>&nbsp;cout &lt;&lt; * ++p &lt;&lt; endl;<br>&nbsp;cout &lt;&lt; *(++p) &lt;&lt;endl;<br>&nbsp;cout &lt;&lt; ++*p &lt;&lt; endl;<br>&nbsp;cout &lt;&lt; ++( *p) &lt;&lt;endl;<br>&nbsp;return 0;<br>}<br><br>VC++6 DEBUG下分析：cout的运算是从右向左进行的，但最后输出还是从左到右。<br>所以cout &lt;&lt; *p++ &lt;&lt; *(p++) &lt;&lt; (*p)++ &lt;&lt; *++p &lt;&lt; *(++p) &lt;&lt;++*p &lt;&lt; ++(*p) &lt;&lt; endl;<br>依次++(*p),++*p,*(++p),*++p,(*p)++,*(p++), *p++ ,最后再反着输出。<br>1.++*p:P指向S[0]，并把S[0]加1做为表达式的值，所以输出为1，此时S[0]=='1'<br>2.++(*p):P还指向S[0]（S[0]现在的值为1），并把S[0]加1做为表达式的值，所以输出为2，此时S[0]=='2'<br>3.*(++p):p指向S[1]，然后取S[1]的值作为表达式的值，输出'1'<br>4.*++p ：P指向S[2]，然后取S[2]的值作为表达式的值，输出'2'<br>5.(*p)++：P还是指向S[2]，取S[2]的值作为表达式的值，所以输出'2'，然后S[2]的值加1，S[2]==3<br>6.*(p++)：P还是指向S[2]（现值为3），取S[2]的值作为表达式的值，所以输出'3'，然后P指向S[3]<br>7.*p++ ：P指向S[3]，取S[3]的值作为表达式的值，所以输出'3'，然后P指向S[4]；<br>最后反着输出为3322121<br>此数组S的值为"213345678".所以后面的输出就是这些值了。</p>
<img src ="http://www.cppblog.com/hktk/aggbug/96870.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hktk/" target="_blank">海 阔 天 空</a> 2009-09-21 18:56 <a href="http://www.cppblog.com/hktk/archive/2009/09/21/96870.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ int * 和 int (*)[]</title><link>http://www.cppblog.com/hktk/archive/2009/09/21/96869.html</link><dc:creator>海 阔 天 空</dc:creator><author>海 阔 天 空</author><pubDate>Mon, 21 Sep 2009 10:54:00 GMT</pubDate><guid>http://www.cppblog.com/hktk/archive/2009/09/21/96869.html</guid><description><![CDATA[#include &lt;iostream&gt;<br>using namespace std; <br>int main()<br>{<br>&nbsp;int a[5] = {1,2,3,4,5};<br>&nbsp;int *ptr = (int *) (&amp;a+1); <br>&nbsp;cout &lt;&lt; *(a+1) &lt;&lt; endl;<br>&nbsp;cout &lt;&lt; *(ptr-1) &lt;&lt; endl; <br>&nbsp;return 0;<br>}<br><br>(&amp;a+1)中&amp;a 是表示数组的地址，进行+1，相当于地址+1*(sizeof(a))，即指向数组末的尾地址（可理解为下个数组的首地址^-^） <br>(int *)(&amp;a+1) 是将int(*)[5]强转成int *,好赋给int * ptr（ptr是个指向普通整型变量的指针） <br>(ptr-1) ptr是一个指向整型的普通指针，所以-1操作相当于地址-1*(sizeof(int)) <br>a+1 a是数组的首元素的地址，+1相当于a[1]的地址 <br>&nbsp; <br>SO:*(a+1) :&nbsp;&nbsp;&nbsp;&nbsp; 2 <br>&nbsp;&nbsp; *(ptr-1):&nbsp;&nbsp;&nbsp; 5 
<img src ="http://www.cppblog.com/hktk/aggbug/96869.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hktk/" target="_blank">海 阔 天 空</a> 2009-09-21 18:54 <a href="http://www.cppblog.com/hktk/archive/2009/09/21/96869.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>