﻿<?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++博客-Oo缘来是你oO-随笔分类-【01】C++</title><link>http://www.cppblog.com/majianan/category/2285.html</link><description>&lt;br&gt;
&lt;br&gt;
人本是人，不必刻意去做人；世本是世，无须精心去处世；自然的才是快乐的。
&lt;br&gt;&lt;br&gt;
</description><language>zh-cn</language><lastBuildDate>Mon, 02 Feb 2009 03:44:49 GMT</lastBuildDate><pubDate>Mon, 02 Feb 2009 03:44:49 GMT</pubDate><ttl>60</ttl><item><title>用指针调用函数的不同形式</title><link>http://www.cppblog.com/majianan/archive/2006/09/14/12436.html</link><dc:creator>马嘉楠</dc:creator><author>马嘉楠</author><pubDate>Thu, 14 Sep 2006 02:08:00 GMT</pubDate><guid>http://www.cppblog.com/majianan/archive/2006/09/14/12436.html</guid><wfw:comment>http://www.cppblog.com/majianan/comments/12436.html</wfw:comment><comments>http://www.cppblog.com/majianan/archive/2006/09/14/12436.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/majianan/comments/commentRss/12436.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/majianan/services/trackbacks/12436.html</trackback:ping><description><![CDATA[
		<table class="description" cellspacing="0" cellpadding="0" align="center" border="0">
				<tbody>
						<tr>
								<td align="middle">
										<div class="sysBr500 text" id="articleText476cd87801000279" align="left">
												<p align="center">
														<font face="Verdana" color="#0000ff" size="2">
																<strong>
																		<a href="http://blog.sina.com.cn/pic/476cd87802000114" target="_blank">
																				<img src="http://blog.sina.com.cn/pic/476cd87802000114" border="0" &#111;nload="resizeImg(this,500)" />
																		</a>
																</strong>
														</font>
												</p>
												<div align="center">
														<font color="#0000ff">
																<font size="2">
																		<font face="Verdana">
																				<strong>用指针调用函数的不同形式</strong>
																		</font>
																</font>
														</font>
												</div>
												<div align="center">
														<strong>
																<font face="Verdana" color="#0000ff" size="2">
																</font>
														</strong> </div>
												<div align="center">
														<strong>
																<font face="Verdana" color="#0000ff" size="2">Ma Jia nan </font>
														</strong>
												</div>
												<div align="center">
														<strong>
																<font size="2">
																		<font face="Verdana">
																				<font color="#0000ff">2006-1-16</font>
																		</font>
																</font>
														</strong>
												</div>
												<div align="center">
														<strong>
																<font face="Verdana" color="#0000ff" size="2">
																</font>
														</strong> </div>
												<div>
														<font face="Verdana" size="2">    最初一个函数指针必须用*操作符（和一对括号）“转换为”一个“真正的”函数才能调用，如下所示： </font>
												</div>
												<div>
														<font face="Verdana" size="2">
														</font> </div>
												<div>
														<font face="Verdana" size="2">    int r, func(), (*pf)() = func; //函数指针的初始化<br />    r = (*pf)();  //函数的指针调用形式1，等价于 r = func(); </font>
												</div>
												<div>
														<font face="Verdana" size="2">
														</font> </div>
												<div>
														<font face="Verdana" size="2">    函数总是通过指针进行调用的，所有“真正的”函数名总是隐式的退化为指向该函数的指针， 正如在对函数指针pf初始化做的那样： </font>
												</div>
												<div>
														<font face="Verdana" size="2">
														</font> </div>
												<div>
														<font face="Verdana" size="2">    int func();<br />    int (*pf)() = func; </font>
												</div>
												<div>
														<font face="Verdana" size="2">
														</font> </div>
												<div>
														<font face="Verdana" size="2">    这有点类似数组名的行为（不带下标操作符的数组名会被解释成指向数组首元素的指针）。 </font>
												</div>
												<div>
														<br />
														<font face="Verdana" size="2">    以上结论表明，下面的语句也是正确的。 </font>
												</div>
												<div>
														<font face="Verdana" size="2">
														</font>
												</div>
												<font face="Verdana" size="2"> </font>
										</div>
										<div>
												<font face="Verdana" size="2">    r = pf();     //函数的指针调用形式2 </font>
										</div>
										<div>
												<font face="Verdana" size="2">
												</font> </div>
										<div>
												<font face="Verdana" size="2">    ANSI C 标准实际上接受形式2，这意味着不再需要*操作符，但形式1依然允许。两种形式产生相同的结果，但是形式1让读者更清楚该调用是通过函数指针执行的。 </font>
										</div>
										<div>
												<font face="Verdana" size="2">
												</font> </div>
										<div>
												<font face="Verdana" size="2">
												</font> </div>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.cppblog.com/majianan/aggbug/12436.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/majianan/" target="_blank">马嘉楠</a> 2006-09-14 10:08 <a href="http://www.cppblog.com/majianan/archive/2006/09/14/12436.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>顺序容器操作</title><link>http://www.cppblog.com/majianan/archive/2006/09/14/12435.html</link><dc:creator>马嘉楠</dc:creator><author>马嘉楠</author><pubDate>Thu, 14 Sep 2006 02:07:00 GMT</pubDate><guid>http://www.cppblog.com/majianan/archive/2006/09/14/12435.html</guid><wfw:comment>http://www.cppblog.com/majianan/comments/12435.html</wfw:comment><comments>http://www.cppblog.com/majianan/archive/2006/09/14/12435.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/majianan/comments/commentRss/12435.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/majianan/services/trackbacks/12435.html</trackback:ping><description><![CDATA[
		<table class="description" cellspacing="0" cellpadding="0" align="center" border="0">
				<tbody>
						<tr>
								<td align="middle">
										<div class="sysBr500 text" id="articleText476cd87801000236" align="left">
												<p align="center">
														<font color="#0000ff">
																<strong>
																		<a href="http://blog.sina.com.cn/pic/476cd878020000zs" target="_blank">
																				<font face="Verdana" size="2">
																						<img src="http://blog.sina.com.cn/pic/476cd878020000zs" border="0" &#111;nload="resizeImg(this,500)" />
																				</font>
																		</a>
																		<font face="Verdana" size="2">    </font>
																</strong>
														</font>
														<font color="#0000ff">
																<strong>
																		<font face="Verdana" size="2">C++ Primer 学习札记   </font>
																		<a href="http://blog.sina.com.cn/pic/476cd878020000zt" target="_blank">
																				<font face="Verdana" size="2">
																						<img src="http://blog.sina.com.cn/pic/476cd878020000zt" border="0" &#111;nload="resizeImg(this,500)" />
																				</font>
																		</a>
																</strong>
														</font>
												</p>
												<p align="center">
														<font color="#0000ff">
																<font size="2">
																		<font face="Verdana">
																				<strong>Ma Jia nan</strong>
																		</font>
																</font>
														</font>
												</p>
												<p>
														<font face="Verdana" size="2">
														</font>
												</p>
												<font face="Verdana" size="2">
														<hr id="null" />
												</font>
												<p>
												</p>
												<div>
														<font color="#0000ff">
																<font size="2">
																		<font face="Verdana">
																				<strong>一 顺序容器操作之插入（insert）</strong>
																		</font>
																</font>
														</font>
												</div>
												<div>
														<font face="Verdana" size="2">
														</font> </div>
												<div>
														<font face="Verdana" size="2">向容器中插入元素有以下几种形式： </font>
												</div>
												<div>
														<font face="Verdana" size="2">
														</font> </div>
												<div>
														<font face="Verdana" size="2">1） 最一般的形式： </font>
														<table style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 80%; BORDER-BOTTOM: #999 1px solid" align="center">
																<tbody>
																		<tr>
																				<td>
																						<p>
																								<font face="Verdana" size="2">   </font>
																								<font face="Verdana" size="2">vector&lt;string&gt; svec;<br />   list&lt;string&gt; slist; </font>
																						</p>
																						<p>
																								<font face="Verdana" size="2">   string s( "MaJianan" );<br />   slist.insert( slist.begin(), s );<br />   svec.insert( svec.begin(), s ); </font>
																						</p>
																				</td>
																		</tr>
																</tbody>
														</table>
												</div>
												<p>
														<font face="Verdana" size="2">insert()将第二个参数（要被插入的值）插入到第一个参数（指向容器中某个位置的iterator）指向的位置的前面。 </font>
												</p>
												<p>
														<font face="Verdana" size="2">更为随机的插入操作可以如下实现： </font>
												</p>
												<p>
														<font face="Verdana" size="2">
														</font>
												</p>
												<table style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 79.57%; BORDER-BOTTOM: #999 1px solid; HEIGHT: 117px" align="center">
														<tbody>
																<tr>
																		<td>
																				<p>
																						<font face="Verdana" size="2">   string s1( "yuanlaishini" );<br />   list&lt;string&gt;::iterator iter; </font>
																				</p>
																				<p>
																						<font face="Verdana" size="2">   iter = find( slist.begin(), slist.end(), s1 );<br />   slist.insert( iter, s1 ); </font>
																				</p>
																		</td>
																</tr>
														</tbody>
												</table>
												<p>
														<font face="Verdana" size="2">find()返回被查找元素在容器中的位置，如果查找失败，返回end()iterator.<br />   <br />//slist.push_back( value )等价于    <br />slist.insert( slist.end(), value ); </font>
												</p>
												<p>
														<font face="Verdana" size="2">
														</font> </p>
												<p>
														<font face="Verdana" size="2">2） 在某个位置插入指定数量的元素.<br />   例如，在vector的开始处插入10个MaJianan： </font>
												</p>
												<p>
														<font face="Verdana" size="2">
														</font>
												</p>
												<table style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 80%; BORDER-BOTTOM: #999 1px solid" align="center">
														<tbody>
																<tr>
																		<td>
																				<p>
																						<font face="Verdana" size="2">   </font>
																						<font face="Verdana" size="2">vector&lt;string&gt; svec;<br />   string mjn( "MaJianan" ); </font>
																				</p>
																				<p>
																						<font face="Verdana" size="2">   svec.insert( svec.begin(), 10, mjn ); </font>
																				</p>
																		</td>
																</tr>
														</tbody>
												</table>
												<p>
														<font face="Verdana" size="2">
														</font> </p>
												<p>
														<font face="Verdana" size="2">3）向容器插入一段范围内的元素： </font>
												</p>
												<p>
														<font face="Verdana" size="2">
														</font>
												</p>
												<table style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 80%; BORDER-BOTTOM: #999 1px solid" align="center">
														<tbody>
																<tr>
																		<td>
																				<p>
																						<font face="Verdana" size="2"> string sa[3] = { "MaJianan", "yuanlaishini", "blog.sina.com.cn"}; </font>
																				</p>
																				<p>
																						<font face="Verdana" size="2">   //插入数组中的全部元素<br />   svec.insert( svec.begin(), sa, sa+3 ); </font>
																				</p>
																				<p>
																						<font face="Verdana" size="2">   //插入数组中的部分元素<br />   svec.insert( svec.begin() + svec.size()/2, sa+1, sa+3 );   </font>
																				</p>
																		</td>
																</tr>
														</tbody>
												</table>
												<p>
														<font face="Verdana" size="2">
														</font> </p>
												<p>
														<font face="Verdana" size="2">4）通过一对iterator来标记带插入值的范围，可以是另一个vector </font>
												</p>
												<p>
														<font face="Verdana" size="2">
														</font>
												</p>
												<table style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 87.04%; BORDER-BOTTOM: #999 1px solid; HEIGHT: 228px" align="center">
														<tbody>
																<tr>
																		<td>
																				<p>
																						<font face="Verdana" size="2">例一：<br />   //插入svec中含有的元素，从svec2中间开始<br />   svec2.insert( svec2.begin() + svec2.size()/2, svec.begin(), svec.end() ); </font>
																				</p>
																				<p>
																						<font face="Verdana" size="2">   例二：<br />   //把sevc中的元素插入到slist中sValue的前面<br />   list&lt;string&gt; slist;<br />   list&lt;string&gt;::iterator iter = find( slist.begin(), slist.end(), sValue );<br />   slist.insert( iter, svec.begin(), svec.end() ); </font>
																				</p>
																		</td>
																</tr>
														</tbody>
												</table>
												<p>
														<font face="Verdana" size="2">
														</font>
												</p>
												<font face="Verdana" size="2">
														<hr id="null" />
												</font>
												<p>
												</p>
												<p>
														<font color="#0000ff">
																<font size="2">
																		<font face="Verdana">
																				<strong>二 顺序容器操作之删除（erase）</strong>
																		</font>
																</font>
														</font>
												</p>
												<p>
														<font face="Verdana" size="2">1） 删除单个元素 </font>
												</p>
												<table style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 80%; BORDER-BOTTOM: #999 1px solid" align="center">
														<tbody>
																<tr>
																		<td>
																				<p>
																						<font face="Verdana" size="2">list&lt;string&gt; slist;<br />... ...<br />sting sValue( "yuanlaishini" );<br />list&lt;string&gt;::iterator iter=find( slist.begin(), slist.end(), sValue );<br />if( iter!=slist.end() )<br />       slist.erase( iter ); </font>
																				</p>
																		</td>
																</tr>
														</tbody>
												</table>
												<p>
														<font face="Verdana" size="2">
														</font> </p>
												<p>
														<font face="Verdana" size="2">2） 删除有一对iterator标记的一段范围内的元素 </font>
												</p>
												<p>
														<font face="Verdana" size="2">
														</font>
												</p>
												<table style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 80%; BORDER-BOTTOM: #999 1px solid; HEIGHT: 316px" align="center">
														<tbody>
																<tr>
																		<td>
																				<p>
																						<font face="Verdana" size="2">//删除所有元素<br />slist.erase( slist.begin(), slist.end() ); </font>
																				</p>
																				<p>
																						<font face="Verdana" size="2">//删除部分元素<br />例一：<br />slist.erase( slist.begin()+slist.size()/2, slist.end() ); </font>
																				</p>
																				<p>
																						<font face="Verdana" size="2">例二：<br />list&lt;string&gt;::iterator first, last;<br />first=find( slist.begin(), slist.end(). value1);<br />last=find( slist.begin(), slist.end(). value2);<br />//检验first和last的有效性<br />slist.erase( first, last ); </font>
																				</p>
																		</td>
																</tr>
														</tbody>
												</table>
												<p>
														<br />
														<font face="Verdana" size="2">3） 与push_back()相对应，pop_back()删除容器的末尾元素。 </font>
												</p>
												<p>
														<font face="Verdana" size="2">
														</font>
												</p>
												<font face="Verdana" size="2">
														<hr id="null" />
												</font>
												<p>
												</p>
												<p>
														<font color="#0000ff">
																<font size="2">
																		<font face="Verdana">
																				<strong>三 顺序容器操作之赋值(=)和对换(swap)</strong>
																		</font>
																</font>
														</font>
												</p>
												<p>
														<font face="Verdana" size="2">//slist1含有8个元素<br />//slist2含有16个元素<br />1)如果 </font>
														<font face="Verdana" size="2">slist1 = slist2;<br /> <br />  slist1拥有与被拷贝容器相同的元素数目---16.slist2有16个元素，没有变化。<br />  slist1中原来的8个元素被删除(调用string的析构函数) </font>
												</p>
												<p>
														<font face="Verdana" size="2">2)如果 slist1.swap( slist2 );<br />  <br />  slist1现在有16个元素，而slist2函数slist1中原有的8个元素的拷贝<br />  如果两个容器长度不同，则重置容器的长度  <br /></font>
												</p>
												<font face="Verdana" size="2">
														<hr id="null" />
												</font>
												<p>
												</p>
												<p>
														<font face="Verdana" size="2">
														</font> </p>
												<p align="center">
														<a href="http://blog.sina.com.cn/pic/476cd878020000zu" target="_blank">
																<font face="Verdana" size="2">
																		<img src="http://blog.sina.com.cn/pic/476cd878020000zu" border="0" &#111;nload="resizeImg(this,500)" />
																</font>
														</a>
												</p>
												<p align="center">
														<font face="Verdana" size="2">
														</font> </p>
										</div>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.cppblog.com/majianan/aggbug/12435.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/majianan/" target="_blank">马嘉楠</a> 2006-09-14 10:07 <a href="http://www.cppblog.com/majianan/archive/2006/09/14/12435.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>确定基类有虚析购函数</title><link>http://www.cppblog.com/majianan/archive/2006/09/14/12434.html</link><dc:creator>马嘉楠</dc:creator><author>马嘉楠</author><pubDate>Thu, 14 Sep 2006 02:05:00 GMT</pubDate><guid>http://www.cppblog.com/majianan/archive/2006/09/14/12434.html</guid><wfw:comment>http://www.cppblog.com/majianan/comments/12434.html</wfw:comment><comments>http://www.cppblog.com/majianan/archive/2006/09/14/12434.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/majianan/comments/commentRss/12434.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/majianan/services/trackbacks/12434.html</trackback:ping><description><![CDATA[
		<div>
				<font face="Verdana" size="2">当通过基类的指针去删除派生类的对象，而基类有没有虚析购函数的时候，结果将是不可确定的。（实际运行时常发生的情况是，派生类的析购函数永远不会被调用） </font>
		</div>
		<div>
				<font face="Verdana" size="2">
				</font> </div>
		<div>
				<font face="Verdana" size="2">虚函数的目的是让派生类去制定自己的行为，所以几乎所有的基类都有虚函数。 </font>
		</div>
		<div>
				<font face="Verdana" size="2">
				</font> </div>
		<div>
				<font face="Verdana" size="2">如果某个类不包含虚函数，那一般是表示他将不作为基类来使用，当一个类不准备做基类使用的时候，使析购函数为虚一般是个错误的选择。 </font>
		</div>
<img src ="http://www.cppblog.com/majianan/aggbug/12434.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/majianan/" target="_blank">马嘉楠</a> 2006-09-14 10:05 <a href="http://www.cppblog.com/majianan/archive/2006/09/14/12434.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>iostream 和 iostream.h 的区别 </title><link>http://www.cppblog.com/majianan/archive/2006/08/26/11727.html</link><dc:creator>马嘉楠</dc:creator><author>马嘉楠</author><pubDate>Sat, 26 Aug 2006 01:49:00 GMT</pubDate><guid>http://www.cppblog.com/majianan/archive/2006/08/26/11727.html</guid><wfw:comment>http://www.cppblog.com/majianan/comments/11727.html</wfw:comment><comments>http://www.cppblog.com/majianan/archive/2006/08/26/11727.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/majianan/comments/commentRss/11727.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/majianan/services/trackbacks/11727.html</trackback:ping><description><![CDATA[<div align=left><font face=Verdana size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color=#0000ff> &lt; iostream &gt; 和 &lt; iostream.h &gt; 的区别</font><br><br>关键词：&lt; iostream &gt; 和 &lt; iostream.h &gt; </font></div>
<div><font face=Verdana size=2></font>&nbsp;</div>
<div><font face=Verdana size=2>你写程序的时候，用&lt; iostream &gt;还是&lt; iostream.h &gt;？ </font></div>
<div><font face=Verdana size=2>你知道它们有什么区别么？还是认为他们根本就是一样的？ </font></div>
<div><font face=Verdana size=2>下面听我给你吹（文中纯属个人言论，不涉及国家机密，请放心阅读，若转载请注明出处作者^-^） </font></div>
<div><font face=Verdana size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---majianan </font></div>
<div><font face=Verdana size=2></font>&nbsp;</div>
<div><font face=Verdana size=2></font>&nbsp;</div>
<div><font face=Verdana size=2>其实没有&lt; iostream.h &gt;这样的东西 --- 标准化委员会在简化非C标准头文件时用&lt; iostream &gt; 取代了它。但又没有完全取消&lt; iostream.h &gt;的使用，并且很多编译器都同时支持&lt; iostream &gt;和&lt; iostream.h &gt;，造成现在的局面，老大（标准化委员会）确实有不得已的苦衷。 </font></div>
<div><font face=Verdana size=2></font>&nbsp;</div>
<div><font face=Verdana size=2>话说当年，在标准化委员会动手重建新的标准库的时候，遇到了问题。为了避免类名函数名的冲突问题，引入了名字空间std，但无数现有的C++代码都依赖于使用了多年的伪标准库中的功能，例如，声明在&lt; iostream.h &gt;和&lt; complex.h &gt;等头文件中的功能。现有软件没有针对使用名字空间而进行相应的设计或者升级，如果用std来包装标准库导致现有代码不能使用，那手底下的小弟（程序员）是不会同意的。 </font></div>
<div><font face=Verdana size=2></font>&nbsp;</div>
<div><font face=Verdana size=2>标准化委员会为了拉拢人心，吸引更多的人入会，决定为包装了std的那部分标准库构建新的头文件名。将现有C++头文件名中的.h去掉，所以就出现了&lt; iostream.h&gt;和&lt; iostream &gt;等很多双胞胎。对于C头文件，采用同样方法但在每个名字前还要添加一个C，所以C的&lt;string.h&gt;变成了&lt;cstring&gt;。 </font></div>
<div><font face=Verdana size=2></font>&nbsp;</div>
<div><font face=Verdana size=2>旧的C++头文件是官方明确反对使用的，但旧的C头文件则没有（以保持对C的兼容性）。其实编译器制造商不会停止对客户现有软件提供支持，所以在可以预计的将来，旧的C++头文件还会嚣张一段时间。 </font></div>
<div><font face=Verdana size=2></font>&nbsp;</div>
<div><font face=Verdana size=2>如果能明白字符串头文件的使用，举一反三，其他的也差不多会用了。 </font></div>
<div><font face=Verdana size=2></font>&nbsp;</div>
<div><font face=Verdana size=2>&lt;string.h&gt;是旧的C头文件，对应的是基于char*的字符串处理函数； </font></div>
<div><font face=Verdana size=2>&lt;string&gt;是包装了std的C++头文件，对应的是新的strng类； </font></div>
<div><font face=Verdana size=2>&lt;cstring&gt;是对应旧的C头文件的std版本。 </font></div>
<div><font face=Verdana size=2></font>&nbsp;</div>
<div><font face=Verdana size=2>好像跑远了，言归正传。如果你的编译器都同时支持&lt; iostream &gt;和&lt; iostream.h &gt;，那使用#include &lt; iostream &gt;，得到的是置于名字空间std下的iostream库的元素；如果使用#include &lt; iostream.h &gt;，得到的是置于全局空间的同样的元素。在全局空间获取元素会导致名字冲突，而设计名字空间的初衷正是用来避免这种名字冲突的发生。还有，打字时&lt; iostream &gt;比&lt; iostream.h &gt;少两个字，所以我会使用&lt; iostream &gt; ^-^ </font></div>
<div><font face=Verdana size=2></font>&nbsp;</div>
<div><font face=Verdana size=2>困了，睡了。 </font></div>
<div><font face=Verdana size=2></font>&nbsp;</div>
<div><font face=Verdana size=2></font>&nbsp;</div>
<div><font face=Verdana size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 马嘉楠 </font></div>
<div><font face=Verdana size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2005-12-26 午夜 </font></div>
<img src ="http://www.cppblog.com/majianan/aggbug/11727.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/majianan/" target="_blank">马嘉楠</a> 2006-08-26 09:49 <a href="http://www.cppblog.com/majianan/archive/2006/08/26/11727.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于 sizeof() 的一些思考 </title><link>http://www.cppblog.com/majianan/archive/2006/08/25/11682.html</link><dc:creator>马嘉楠</dc:creator><author>马嘉楠</author><pubDate>Fri, 25 Aug 2006 01:25:00 GMT</pubDate><guid>http://www.cppblog.com/majianan/archive/2006/08/25/11682.html</guid><wfw:comment>http://www.cppblog.com/majianan/comments/11682.html</wfw:comment><comments>http://www.cppblog.com/majianan/archive/2006/08/25/11682.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/majianan/comments/commentRss/11682.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/majianan/services/trackbacks/11682.html</trackback:ping><description><![CDATA[
		<div>
				<p>
						<font size="2">
								<font face="Verdana">
										<font color="#000000">
												<font color="#0000ff" size="3">                                       关于 sizeof() 的一些思考</font> <br />                                                         马嘉楠<br /><br /></font>
										<font color="#000080">关键词：</font>
										<font color="#0000ff">sizeof </font>
								</font>
						</font>
				</p>
				<p>
						<font size="2">
								<font face="Verdana">
										<font color="#000000">这是网上的一个帖子，最初来自那里已经记不得了，不过我觉得很不错。</font>
								</font>
						</font>
				</p>
				<p>
						<font face="Verdana" size="2">我对原文做了一些修改，并添加了一些内容。如果有什么错误的地方，请大家指正，谢谢~~ </font>
				</p>
				<p>
						<font face="Verdana" size="2">                       --- majianan 2005-12-19 </font>
				</p>
				<p>
						<strong>
								<font face="Verdana" color="#0000ff" size="2">
								</font>
						</strong> </p>
				<p>
						<font size="2">
								<font face="Verdana">
										<strong>
												<font color="#0000ff">0.关键字</font>
										</strong>：sizeof，字节对齐，类型大小 </font>
						</font>
				</p>
				<p>
						<font size="2">
								<font face="Verdana">
										<strong>
												<font color="#0000ff">前向声明：</font>
										</strong>
										<br />    sizeof，一个其貌不扬的家伙，引无数菜鸟竟折腰. </font>
						</font>
				</p>
				<p>
						<font face="Verdana" size="2">    小虾我当初也没少犯迷糊，秉着“辛苦我一个，幸福千万人”的伟大思想,我决定将其尽可能详细的总结一下。 </font>
				</p>
				<p>
						<br />
						<font face="Verdana" size="2">    但当我总结的时候才发现，这个问题既可以简单，又可以复杂。所以本文有的地方并不适合初学者，甚至都没有必要大作文章。但如果你想“知其然，更知其所以然”的话，那么这篇文章对你或许有所帮助。<br />    </font>
				</p>
				<p>
						<font face="Verdana" size="2">    菜鸟我对C++的掌握尚未深入，其中不乏错误，欢迎各位指正啊 </font>
				</p>
				<p>
						<font size="2">
								<font face="Verdana">
										<strong>
												<font color="#0000ff">1. 定义：<br /></font>
										</strong>    sizeof是何方神圣？ </font>
						</font>
				</p>
				<p>
						<font face="Verdana" size="2">    sizeof 乃 C/C++ 中的一个操作符（operator）是也。简单说其作用就是返回一个对象或者类型所占的内存字节数。<br /><br />MSDN上的解释为： </font>
				</p>
				<p>
						<font face="Verdana" size="2">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. </font>
				</p>
				<p>
						<font face="Verdana" size="2">    其返回值类型为size_t，在头文件stddef.h中定义。这是一个依赖于编译系统的值，一般定义为 </font>
				</p>
				<p>
						<font face="Verdana" size="2">typedef unsigned int size_t; </font>
				</p>
				<p>
						<font face="Verdana" size="2">    世上编译器林林总总，但作为一个规范，它们都会保证char、signed char和unsigned char的sizeof值为1，毕竟char是我们编程能用的最小数据类型。<br /><br /><strong><font color="#0000ff">2. 语法：</font></strong><br />    sizeof有三种语法形式，如下：<br />    1) sizeof( object );    // sizeof( 对象 );<br />    2) sizeof( type_name ); // sizeof( 类型 );<br />    3) sizeof object;       // sizeof 对象; </font>
				</p>
				<p>
						<font face="Verdana" size="2">所以，<br />int i;<br />sizeof( i );     // ok<br />sizeof i;        // ok<br />sizeof( int );   // ok<br />sizeof int;      // error </font>
				</p>
				<p>
						<font face="Verdana" size="2">既然写法2可以用写法1代替，为求形式统一以及减少我们大脑的负担，第2种写法，忘掉它吧！ </font>
				</p>
				<p>
						<font face="Verdana" size="2">实际上，sizeof计算对象的大小也是转换成对对象类型的计算。也就是说，同种类型的不同对象其sizeof值都是一致的。 </font>
				</p>
				<p>
						<font face="Verdana" size="2">这里，对象可以进一步延伸至表达式，即sizeof可以对一个表达式求值。编译器<strong>根据表达式的最终结果类型来确定大小</strong>，一般不会对表达式进行计算。 </font>
				</p>
				<p>
						<font face="Verdana" size="2">例如： </font>
				</p>
				<p>
						<font face="Verdana" size="2">sizeof( 2 );        // 2的类型为int，所以等价于 sizeof( int );<br />sizeof( 2 + 3.14 ); // 3.14的类型为double，2也会被提升成double类型，所以等价于 sizeof( double );<br /><br />    sizeof也可以对一个函数调用求值，其<font color="#0000ff">结果是函数返回类型的大小，函数并不会被调用。</font>我们来看一个完整的例子： </font>
				</p>
				<p>
						<font size="2">
								<font face="Verdana">
										<font color="#0000ff">*********************************************************</font>
								</font>
						</font>
				</p>
				<p>
						<font face="Verdana" size="2">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 />} </font>
				</p>
				<p>
						<font size="2">
								<font face="Verdana">
										<font color="#0000ff">*********************************************************</font>
								</font>
						</font>
				</p>
				<p>
						<font face="Verdana" size="2">C99标准规定，函数、不能确定类型的表达式以及位域（bit-field）成员不能被计算sizeof值，即下面这些写法都是错误的： </font>
				</p>
				<p>
						<font face="Verdana" size="2">    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 </font>
				</p>
				<p>
						<br />
						<strong>
								<font size="2">
										<font face="Verdana">
												<font color="#0000ff">3. sizeof的常量性</font>
										</font>
								</font>
						</strong>
				</p>
				<strong>
						<font color="#0000ff">
						</font>
				</strong>
				<p>
						<br />
						<font face="Verdana" size="2">    sizeof的计算发生在编译时刻，所以它可以被当作常量表达式使用。如： </font>
				</p>
				<p>
						<font face="Verdana" size="2">char ary[ sizeof( int ) * 10 ];   // ok </font>
				</p>
				<p>
						<font face="Verdana" size="2">最新的C99标准规定sizeof也可以在运行时刻进行计算。如下面的程序在Dev-C++中可以正确执行： </font>
				</p>
				<p>
						<font face="Verdana" size="2">int n;<br />n = 10;        // n动态赋值<br />char ary[n];   // C99也支持数组的动态定义<br />printf("%d\n", sizeof(ary)); // ok. 输出10 </font>
				</p>
				<p>
						<font face="Verdana" size="2">但在没有完全实现C99标准的编译器中就行不通了，上面的代码在VC6中就通不过编译。所以我们<font color="#0000ff">最好还是认为sizeof是在编译期执行的</font>，这样不会带来错误，让程序的可移植性强些。 </font>
				</p>
				<p>
						<br />
						<strong>
								<font size="2">
										<font face="Verdana">
												<font color="#0000ff">4. 基本数据类型的sizeof</font>
										</font>
								</font>
						</strong>
				</p>
				<p>
						<font face="Verdana" size="2">这里的基本数据类型指short、int、long、float、double这样的简单内置数据类型。由于它们都是和系统相关的，所以在不同的系统下取值可能不同。这务必引起我们的注意，尽量不要在这方面给自己程序的移植造成麻烦。 </font>
				</p>
				<p>
						<font face="Verdana" size="2">一般的，在32位编译环境中，sizeof(int)的取值为4。 </font>
				</p>
				<p>
						<br />
						<strong>
								<font size="2">
										<font face="Verdana">
												<font color="#0000ff">5. 指针变量的sizeof</font>
										</font>
								</font>
						</strong>
				</p>
				<p>
						<font face="Verdana" size="2">学过数据结构的你应该知道指针是一个很重要的概念，它记录了另一个对象的地址。<font color="#0000ff">既然是来存放地址的，那么它当然等于计算机内部地址总线的宽度。</font>所以在32位计算机中，一个指针变量的返回值必定是4（注意结果是以字节为单位）。可以预计，在将来的64位系统中指针变量的sizeof结果为8。 </font>
				</p>
				<p>
						<font size="2">
								<font face="Verdana">
										<font color="#0000ff">*********************************************************</font>
								</font>
						</font>
				</p>
				<p>
						<font face="Verdana" size="2">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 </font>
				</p>
				<p>
						<font size="2">
								<font face="Verdana">
										<font color="#0000ff">*********************************************************</font>
								</font>
						</font>
				</p>
				<p>
						<font face="Verdana" size="2">指针变量的sizeof值与指针所指的对象没有任何关系，正是由于所有的指针变量所占内存大小相等，所以MFC消息处理函数使用两个参数WPARAM、LPARAM就能传递各种复杂的消息结构（使用指向结构体的指针）。 </font>
				</p>
				<p>
						<br />
						<strong>
								<font size="2">
										<font face="Verdana">
												<font color="#0000ff">6. 数组的sizeof</font>
										</font>
								</font>
						</strong>
				</p>
				<p>
						<font size="2">
								<font face="Verdana">
										<font color="#0000ff">数组的sizeof值等于数组所占用的内存字节数</font>，如： </font>
						</font>
				</p>
				<p>
						<font face="Verdana" size="2">char a1[] = "abc";<br />int a2[3];<br />sizeof( a1 ); // 结果为4，字符 末尾还存在一个NULL终止符<br />sizeof( a2 ); // 结果为3*4=12（依赖于int） </font>
				</p>
				<p>
						<font face="Verdana" size="2">一些朋友刚开始时把sizeof当作了求数组元素的个数，现在，你应该知道这是不对的。那么应该怎么求数组元素的个数呢？ </font>
				</p>
				<p>
						<font face="Verdana" size="2">Easy，通常有下面两种写法： </font>
				</p>
				<p>
						<font face="Verdana" size="2">int c1 = sizeof( a1 ) / sizeof( char );    // 总长度/单个元素的长度<br />int c2 = sizeof( a1 ) / sizeof( a1[0]);    // 总长度/第一个元素的长度 </font>
				</p>
				<p>
						<br />
						<font face="Verdana" size="2">写到这里，提一问，下面的c3，c4值应该是多少呢？ </font>
				</p>
				<p>
						<font size="2">
								<font face="Verdana">
										<font color="#0000ff">*********************************************************</font>
								</font>
						</font>
				</p>
				<p>
						<font face="Verdana" size="2">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 />} </font>
				</p>
				<p>
						<font size="2">
								<font face="Verdana">
										<font color="#0000ff">*********************************************************</font>
								</font>
						</font>
				</p>
				<p>
						<font face="Verdana" size="2">也许当你试图回答c4的值时已经意识到c3答错了，是的，c3!=3。 </font>
				</p>
				<p>
						<font face="Verdana" size="2">这里函数参数<font color="#0000ff">a3已不再是数组类型，而是蜕变成指针。</font>相当于char* a3，为什么仔细想想就不难明白。 </font>
				</p>
				<p>
						<font face="Verdana" size="2">我们调用函数foo1时，程序会在栈上分配一个大小为3的数组吗？不会！ </font>
				</p>
				<p>
						<font face="Verdana" size="2">数组是“传址”的，调用者只需将实参的地址传递过去，所以a3自然为指针类型（char*），c3的值也就为4。 </font>
				</p>
				<p>
						<br />
						<font size="2">
								<font face="Verdana">
										<strong>
												<font color="#0000ff">7.string的sizeof</font>
										</strong>
										<br />
										<font color="#0000ff">一个string的大小与它所指向的字符串的长度无关</font>。<br /><br /><font color="#0000ff">*********************************************************</font><br />string st1("blog.sina.com.cn");<br />string st2("majianan");<br />string st3;<br />string *ps = &amp;st1;<br />cout &lt;&lt; "st1: " &lt;&lt; sizeof(st1) &lt;&lt; endl;<br />cout &lt;&lt; "st2: " &lt;&lt; sizeof(st2) &lt;&lt; endl;<br />cout &lt;&lt; "st3: " &lt;&lt; sizeof(st3) &lt;&lt; endl;<br />cout &lt;&lt; "ps: " &lt;&lt; sizeof(ps) &lt;&lt; endl;<br />cout &lt;&lt; "*ps: " &lt;&lt; sizeof(*ps) &lt;&lt; endl;<br /><font color="#0000ff">*********************************************************</font><br /><br />输出结果为：<br />st1： 28<br />st2： 28<br />st3： 28<br />ps： 4<br />*ps： 28<br /></font>
						</font>
						<font size="2">
								<font face="Verdana">
										<font color="#0000ff">*********************************************************<br /></font>对于不同的STL，String类的结构定义会有所不同<br />所以不同的工具，例如VC++，和.NET，结果会有所不同，<br />在VC++6.0中（我的机器）结果是16<br />在.NET2003中结果是28<br />但是对于同一个编译器，那么它的结果都是一定的<br /><br /><br /><font color="#0000ff"><strong>8.引用的sizeof</strong></font><br /><br /></font>
						</font>
						<font size="2">
								<font face="Verdana">
										<font style="BACKGROUND-COLOR: #ffffff" color="#0000ff">sizeof操作符应用在引用类型上的时候，返回的是包含被引用对象所需的内存长度（即被引用对象的大小）<br /></font>
										<br />
										<font color="#0000ff">*********************************************************</font>
										<br />cout &lt;&lt; "short:\t" &lt;&lt; sizeof(short) &lt;&lt; endl;<br />cout &lt;&lt; "short*:\t" &lt;&lt; sizeof(short*) &lt;&lt; endl; <br />cout &lt;&lt; "short&amp;:\t" &lt;&lt; sizeof(short&amp;) &lt;&lt; endl;<br />cout &lt;&lt; "short[4]:\t" &lt;&lt; sizeof(short[4]) &lt;&lt; endl;<br />cout &lt;&lt; "int&amp;:\t" &lt;&lt; sizeof(int&amp;) &lt;&lt; endl;<br /></font>
						</font>
						<font size="2">
								<font face="Verdana">
										<font color="#0000ff">*********************************************************<br /></font>
										<br />输出结果为：<br />short： 2<br />short*： 4<br />short&amp;： 2<br />short[4]： 8<br />int&amp;： 4<br /><br /><br /><strong><font color="#0000ff">9. 结构体的sizeof</font></strong></font>
						</font>
				</p>
				<p>
						<font face="Verdana" size="2">这是初学者问得最多的一个问题，所以这里有必要多费点笔墨。让我们先看一个结构体： </font>
				</p>
				<p>
						<font face="Verdana" size="2">struct S1<br />{<br />    char c;<br />    int i;<br />}; </font>
				</p>
				<p>
						<font face="Verdana" size="2">问sizeof(s1)等于多少？ </font>
				</p>
				<p>
						<font face="Verdana" size="2">聪明的你开始思考了，char占1个字节，int占4个字节，那么加起来就应该是5。 </font>
				</p>
				<p>
						<font face="Verdana" size="2">是这样吗？ </font>
				</p>
				<p>
						<font face="Verdana" size="2">你在你机器上试过了吗？ </font>
				</p>
				<p>
						<font face="Verdana" size="2">也许你是对的，但很可能你是错的！ </font>
				</p>
				<p>
						<font face="Verdana" size="2">VC6中按默认设置得到的结果为8。<br /><br />    Why？为什么受伤的总是我？ </font>
				</p>
				<p>
						<font face="Verdana" size="2">请不要沮丧，我们来好好琢磨一下sizeof的定义 —— sizeof的结果等于对象或者类型所占的内存字节数。好吧，那就让我们来看看S1的内存分配情况： </font>
				</p>
				<p>
						<font face="Verdana" size="2">S1 s1 = { 'a', 0xFFFFFFFF }; </font>
				</p>
				<p>
						<font face="Verdana" size="2">定义上面的变量后，加上断点，运行程序，观察s1所在的内存，你发现了什么？ </font>
				</p>
				<p>
						<font face="Verdana" size="2">以我的VC6.0为例，s1的地址为0x0012FF78，其数据内容如下： </font>
				</p>
				<p>
						<font face="Verdana" size="2">0012FF78: 61 CC CC CC FF FF FF FF<br /><br />发现了什么？怎么中间夹杂了3个字节的CC？ </font>
				</p>
				<p>
						<font face="Verdana" size="2">看看MSDN上的说明： </font>
				</p>
				<p>
						<font face="Verdana" size="2">When applied to a structure type or variable, sizeof returns the actual size, which may include padding bytes inserted for alignment. </font>
				</p>
				<p dir="ltr" style="MARGIN-RIGHT: 0px">
						<font face="Verdana" size="2">原来如此，这就是传说中的字节对齐啊！一个重要的话题出现了。 </font>
				</p>
				<p dir="ltr" style="MARGIN-RIGHT: 0px">
						<font face="Verdana" size="2">为什么需要字节对齐？ </font>
				</p>
				<p dir="ltr" style="MARGIN-RIGHT: 0px">
						<font face="Verdana" size="2">计算机组成原理教导我们，这样有助于加快计算机的取数速度，否则就得多花指令周期了。 </font>
				</p>
				<p dir="ltr" style="MARGIN-RIGHT: 0px">
						<font face="Verdana" size="2">为此，编译器默认会对结构体进行处理（实际上其它地方的数据变量也是如此），<font color="#0000ff">让宽度为2的基本数据类型（short等）都位于能被2整除的地址上，让宽度为4的基本数据类型（int等）都位于能被4整除的地址上。</font>以此类推，这样，两个数中间就可能需要加入填充字节，所以整个结构体的sizeof值就增长了。 </font>
				</p>
				<p dir="ltr" style="MARGIN-RIGHT: 0px">
						<font face="Verdana" size="2">让我们交换一下S1中char与int的位置： </font>
				</p>
				<p dir="ltr" style="MARGIN-RIGHT: 0px">
						<font face="Verdana" size="2">struct S2<br />{<br />    int i;<br />    char c;<br />}; </font>
				</p>
				<p dir="ltr" style="MARGIN-RIGHT: 0px">
						<font face="Verdana" size="2">看看sizeof(S2)的结果为多少？怎么还是8。 </font>
				</p>
				<p dir="ltr" style="MARGIN-RIGHT: 0px">
						<font face="Verdana" size="2">再看看内存，原来成员c后面仍然有3个填充字节。 </font>
				</p>
				<p dir="ltr" style="MARGIN-RIGHT: 0px">
						<font face="Verdana" size="2">这又是为什么啊？别着急，下面总结规律。 </font>
				</p>
				<p>
						<font face="Verdana" size="2">    <strong><font color="#0000ff">字节对齐的细节和编译器实现相关，但一般而言，满足三个准则：</font></strong><br />    1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除；<br />    2) 结构体每个成员相对于结构体首地址的偏移量（offset）都是成员大小的整数倍，如有需要编译器会在成员之间加上填充字节（internal adding）；<br />    3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍，如有需要编译器会在最末一个成员之后加上填充字节（trailing padding）。<br /><br />    对于上面的准则，有几点需要说明：<br />1) 前面不是说结构体成员的地址是其大小的整数倍，怎么又说到偏移量了呢？ </font>
				</p>
				<p>
						<font face="Verdana" size="2">因为有了第1点存在，所以我们就可以只考虑成员的偏移量，这样思考起来简单。想想为什么。 </font>
				</p>
				<p>
						<font face="Verdana" size="2">结构体某个成员相对于结构体首地址的偏移量可以通过宏offsetof()来获得，这个宏也在stddef.h中定义，如下： </font>
				</p>
				<p>
						<font face="Verdana" size="2">#define offsetof(s,m) (size_t)&amp;(((s *)0)-&gt;m) </font>
				</p>
				<p>
						<font face="Verdana" size="2">例如，想要获得S2中c的偏移量，方法为 </font>
				</p>
				<p>
						<font face="Verdana" size="2">size_t pos = offsetof(S2, c);// pos等于4 </font>
				</p>
				<p>
						<br />
						<font face="Verdana" size="2">2) 基本类型是指前面提到的像char、short、int、float、double这样的内置数据类型。这里所说的“数据宽度”就是指其sizeof的大小。由于结构体的成员可以是复合类型，比如另外一个结构体，所以在寻找最宽基本类型成员时，应当包括复合类型成员的子成员，而不是把复合成员看成是一个整体。但在确定复合类型成员的偏移位置时则是将复合类型作为整体看待。 </font>
				</p>
				<p>
						<font face="Verdana" size="2">这里叙述起来有点拗口，思考起来也有点挠头，还是让我们看看例子吧（具体数值仍以VC6为例，以后不再说明）： </font>
				</p>
				<p>
						<font face="Verdana" size="2">struct S3<br />{<br />    char c1;<br />    S1 s;<br />    char c2;<br />}; </font>
				</p>
				<p>
						<font face="Verdana" size="2">S1的最宽简单成员的类型为int，S3在考虑最宽简单类型成员时是将S1“打散”看的，所以S3的最宽简单类型为int。这样，通过S3定义的变量，其存储空间首地址需要被4整除，整个sizeof(S3)的值也应该被4整除。 </font>
				</p>
				<p>
						<font face="Verdana" size="2">c1的偏移量为0，s的偏移量呢？这时s是一个整体，它作为结构体变量也满足前面三个准则，所以其大小为8，偏移量为4，c1与s之间便需要3个填充字节，而c2与s之间就不需要了，所以c2的偏移量为12，算上c2的大小为13，13是不能被4整除的，这样末尾还得补上3个填充字节。最后得到sizeof(S3)的值为16。 </font>
				</p>
				<p>
						<br />
						<font face="Verdana" size="2">    通过上面的叙述，我们可以得到一个公式：<br />    <font color="#0000ff"><strong>结构体的大小等于最后一个成员的偏移量加上其大小再加上末尾的填充字节数目，</strong></font>即： </font>
				</p>
				<p>
						<font face="Verdana" size="2">sizeof( struct ) = offsetof( last item ) + sizeof( last item ) + sizeof( trailing padding ) </font>
				</p>
				<p>
						<font face="Verdana" size="2">
						</font> </p>
				<div>
						<font color="#0000ff">
								<font size="2">
										<font face="Verdana">
												<strong>10.类的sizeof</strong>
										</font>
								</font>
						</font>
				</div>
				<div>
						<font face="Verdana" size="2">
						</font> </div>
				<div>
						<font face="Verdana" size="2">类的sizeof值等于类中成员变量所占用的内存字节数。如：<br /></font>
				</div>
				<div>
						<font size="2">
								<font face="Verdana">
										<font color="#0000ff">****************************************************************</font>
								</font>
						</font>
				</div>
				<div>
						<font face="Verdana" size="2">  </font>
				</div>
				<div>
						<font face="Verdana" size="2">class A<br />{<br /> public:<br />     int b;<br />     float c;<br />     char d;<br />}; </font>
				</div>
				<div>
						<br />
						<font face="Verdana" size="2">int main(void)<br />{<br />  A object;<br />  cout &lt;&lt; "sizeof(object) is " &lt;&lt; sizeof(object) &lt;&lt; endl;<br />  return 0 ;<br />} </font>
				</div>
				<div>
						<font face="Verdana" size="2">
						</font> </div>
				<div>
						<font size="2">
								<font face="Verdana">
										<font color="#0000ff">***************************************************************</font>
								</font>
						</font>
				</div>
		</div>
		<div>
				<font face="Verdana" size="2">
				</font> </div>
		<div>
				<font face="Verdana" size="2">
				</font> </div>
		<div>
				<font face="Verdana" size="2">输出结果为12（我的机器上sizeof(float)值为4，字节对其前面已经讲过）。 </font>
		</div>
		<div>
				<font face="Verdana" size="2">
				</font> </div>
		<div>
				<font face="Verdana" size="2">不过需要注意的是，如果类中存在静态成员变量，结果又会是什么样子呢？ </font>
		</div>
		<div>
				<font face="Verdana" size="2">
				</font> </div>
		<div>
				<font size="2">
						<font face="Verdana">
								<font color="#0000ff">***************************************************************</font>
						</font>
				</font>
		</div>
		<div>
				<br />
				<font face="Verdana" size="2">class A<br />{<br /> public:<br />     static int a;<br />     int b;<br />     float c;<br />     char d;<br />}; </font>
		</div>
		<div>
				<br />
				<font face="Verdana" size="2">int main()<br />{ </font>
		</div>
		<div>
				<font face="Verdana" size="2">  A object;<br />  cout &lt;&lt; "sizeof(object) is " &lt;&lt; sizeof(object) &lt;&lt; endl;<br />  return 0 ;<br />} </font>
		</div>
		<div>
				<font face="Verdana" size="2">
				</font> </div>
		<div>
				<font size="2">
						<font face="Verdana">
								<font color="#0000ff">**************************************************************</font>
						</font>
				</font>
		</div>
		<div>
				<font face="Verdana" size="2">
				</font> </div>
		<div>
				<font face="Verdana" size="2">
				</font> </div>
		<div>
				<font face="Verdana" size="2">16？不对。结果仍然是12. </font>
		</div>
		<div>
				<br />
				<font face="Verdana" size="2">因为在程序编译期间，就已经为static变量在静态存储区域分配了内存空间，并且这块内存在程序的整个运行期间都存在。 </font>
		</div>
		<div>
				<br />
				<font face="Verdana" size="2">而每次声明了类A的一个对象的时候，为该对象在堆上，根据对象的大小分配内存。 </font>
		</div>
		<div>
				<font face="Verdana" size="2">
				</font> </div>
		<div>
				<font face="Verdana" size="2">如果类A中包含成员函数，那么又会是怎样的情况呢？看下面的例子 </font>
		</div>
		<div>
				<font face="Verdana" size="2">
				</font> </div>
		<div>
				<font size="2">
						<font face="Verdana">
								<font color="#0000ff">*************************************************************</font>
						</font>
				</font>
		</div>
		<div>
				<br />
				<font face="Verdana" size="2">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 />}; </font>
		</div>
		<div>
				<br />
				<font face="Verdana" size="2">int main()<br />{<br />  A object;<br />  cout &lt;&lt; "sizeof(object) is " &lt;&lt; sizeof(object) &lt;&lt; endl;<br />  b = object.add(3,4);<br />  cout &lt;&lt; "sizeof(object) is " &lt;&lt; sizeof(object) &lt;&lt; endl;<br />  return 0 ;<br />} </font>
		</div>
		<div>
				<font face="Verdana" size="2">
				</font> </div>
		<div>
				<font size="2">
						<font face="Verdana">
								<font color="#0000ff">***************************************************************</font>
						</font>
				</font>
		</div>
		<div>
				<font face="Verdana" size="2">
				</font> </div>
		<div>
				<font face="Verdana" size="2">结果仍为12。<font color="#0000ff"></font></font>
		</div>
		<div>
				<font face="Verdana" color="#0000ff" size="2">
				</font>
		</div>
		<div dir="ltr" align="left">
				<span class="139102807-09122005">
						<font face="Verdana" size="2">因为只有非静态类成员变量在新生成一个object的时候才需要自己的副本。 </font>
				</span>
		</div>
		<div dir="ltr" align="left">
				<span class="139102807-09122005">
						<font face="Verdana" size="2">所以每个非静态成员变量在生成新object需要内存，而function是不需要的。 </font>
				</span>
		</div>
		<div dir="ltr" align="left">
				<span class="139102807-09122005">
						<font face="Verdana" size="2">
						</font>
				</span> </div>
		<div dir="ltr" align="left">
				<span class="139102807-09122005">
						<font face="Verdana" size="2">
						</font>
				</span> </div>
		<div dir="ltr" align="left">
				<span class="139102807-09122005">
						<font face="Verdana" size="2">注：C++中的多态和虚继承也是非常重要的东西，不过比较复杂，编译器不同，细节也有所不同。（以后慢慢研究，哈哈）<br /></font>
				</span>
		</div>
<img src ="http://www.cppblog.com/majianan/aggbug/11682.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/majianan/" target="_blank">马嘉楠</a> 2006-08-25 09:25 <a href="http://www.cppblog.com/majianan/archive/2006/08/25/11682.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>