﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-季浩的C/C++博客</title><link>http://www.cppblog.com/jht/</link><description /><language>zh-cn</language><lastBuildDate>Wed, 22 Apr 2026 07:35:54 GMT</lastBuildDate><pubDate>Wed, 22 Apr 2026 07:35:54 GMT</pubDate><ttl>60</ttl><item><title>用snprintf 替换 sprintf </title><link>http://www.cppblog.com/jht/archive/2008/09/03/60805.html</link><dc:creator>季浩</dc:creator><author>季浩</author><pubDate>Wed, 03 Sep 2008 05:43:00 GMT</pubDate><guid>http://www.cppblog.com/jht/archive/2008/09/03/60805.html</guid><wfw:comment>http://www.cppblog.com/jht/comments/60805.html</wfw:comment><comments>http://www.cppblog.com/jht/archive/2008/09/03/60805.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jht/comments/commentRss/60805.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jht/services/trackbacks/60805.html</trackback:ping><description><![CDATA[
		<p style="MARGIN: 0cm 0cm 0pt">
				<span>
						<font face="Times New Roman">int snprintf(char *restrict buf, size_t n, const char * restrict<span>  </span>format, ...);</font>
				</span>
		</p>
		<p style="MARGIN: 0cm 0cm 0pt">
				<span>函数说明:最多从源串中拷贝</span>
				<span>
						<font face="Times New Roman">n</font>
				</span>
				<span>－</span>
				<span>
						<font face="Times New Roman">1</font>
				</span>
				<span>个字符到目标串中，然后再在后面加一个</span>
				<span>
						<font face="Times New Roman">0</font>
				</span>
				<span>。所以如果目标串的大小为</span>
				<span>
						<font face="Times New Roman">n</font>
				</span>
				<span>
				</span>
		</p>
		<p style="MARGIN: 0cm 0cm 0pt">
				<span>                 的话，将不会溢出。</span>
		</p>
		<p style="MARGIN: 0cm 0cm 0pt">
				<span>函数返回值:若成功则返回欲写入的字符串长度，若出错则返回负值。<br /><br />Note:<br />   gcc下安全, VC下仍要注意<br /><br />References:<br /><a href="http://blog.csdn.net/fibbery/archive/2007/11/13/1881587.aspx">平台间函数差异与系统移植：snprintf/_snprintf</a><br /><a class="singleposttitle" id="viewpost1_TitleUrl" href="/sandy/archive/2006/09/29/13133.html">谈谈snprintf</a><br /><a id="AjaxHolder_ctl01_TitleUrl" href="http://www.cnblogs.com/Macros/articles/797378.html">strncpy, strncat和snprintf的区别</a></span>
		</p>
<img src ="http://www.cppblog.com/jht/aggbug/60805.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jht/" target="_blank">季浩</a> 2008-09-03 13:43 <a href="http://www.cppblog.com/jht/archive/2008/09/03/60805.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Eclipse+MinGW+devkitpro搭建Windows上的PSP开发环境</title><link>http://www.cppblog.com/jht/archive/2008/06/14/53257.html</link><dc:creator>季浩</dc:creator><author>季浩</author><pubDate>Sat, 14 Jun 2008 10:02:00 GMT</pubDate><guid>http://www.cppblog.com/jht/archive/2008/06/14/53257.html</guid><wfw:comment>http://www.cppblog.com/jht/comments/53257.html</wfw:comment><comments>http://www.cppblog.com/jht/archive/2008/06/14/53257.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/jht/comments/commentRss/53257.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jht/services/trackbacks/53257.html</trackback:ping><description><![CDATA[
		<font color="#000000" size="3">
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<a href="/jht/archive/2008/06/14/53257.html">
								<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">使用</span>Eclipse+MinGW+devkitpro<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">搭建</span>Windows<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上的</span>PSP<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发环境</span></a>
				</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">PSP<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">入手大概一个月了，玩了几个比较经典的游戏，这两天就想自己写个程序放到</span>PSP<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上跑着玩，兴趣爱好就是倒腾自己时间的玩意</span><br /><br /><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">言归正传，说说这个开发环境</span><br /><br /><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当然这一切都是建立在</span><span lang="ZH-CN"></span><a href="http://ps2dev.org/">PS2DEV<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">社区</span><span lang="ZH-CN"></span></a> <span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">通过反向工程弄出来的</span>ToolChain<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span>SDK<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">基础之上的，</span>PSP SDK<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在开发时的一个目标就是完全合法化。这意味着没有一行代码是从泄露的商业</span>SDK<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中拿来的。</span>PSP SDK<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的任何内容都是通过反向工程</span>firmware<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和已经发布的游戏得来的。</span><br /><br /><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">看来网上不少关于搭建开发环境的文章，总结了如下几点，</span><br /><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">大部分文章都介绍了下面两种</span>Windows<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下的</span>PSP<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发环境，</span><br /><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一、</span>Cygwin+Toolchain <a href="http://bbs.pspchina.net/viewthread.php?tid=22615" target="_blank"><font color="#6fbc4c"><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">简述建立</span>Cygwin<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">环境下的</span>PSP<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发环境</span><span lang="ZH-CN"></span></font></a><br /><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">二、</span>devkitPro   <a href="http://bbs.pspchina.net/viewthread.php?tid=32263" target="_blank"><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">简述安装</span>devkitPSP<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发环境</span>, <span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">完全免用</span>Cygwin </a><br /><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在这基础之上，还有如何配置</span>VC6.0 <span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或者</span> VS.NET 200* <span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">等的文章</span><span lang="ZH-CN"></span><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如：</span><span lang="ZH-CN"></span><a href="http://www.cngba.com/thread-17124347-1-1.html">Visual Studio 2005<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下配置开发</span>psp<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">软件的环境</span><span lang="ZH-CN"></span></a><br /><br /><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">学习完这些文章之后，我决定使用</span>Eclipse (C/C++) + MinGW + devkitpro<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的组合搭建我的</span>PSP<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发环境</span><br /><br /><br /><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第一步：下载安装</span>MinGW</p>
				<p style="FONT-SIZE: 14pt">
				</p>
				<table class="MsoNormalTable" style="mso-cellspacing: 0cm; mso-padding-alt: 0cm 0cm 0cm 0cm" cellspacing="0" cellpadding="0" border="0">
						<thead>
								<tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes">
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">Package </p>
										</td>
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">Release </p>
										</td>
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">Date </p>
										</td>
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">Notes / Monitor </p>
										</td>
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">Downloads </p>
										</td>
								</tr>
						</thead>
						<tbody>
								<tr style="mso-yfti-irow: 1">
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> </p>
										</td>
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
														<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?>
														<o:p> </o:p>
												</p>
										</td>
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
														<o:p> </o:p>
												</p>
										</td>
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
														<o:p> </o:p>
												</p>
										</td>
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
														<o:p> </o:p>
												</p>
										</td>
								</tr>
								<tr style="mso-yfti-irow: 2; mso-yfti-lastrow: yes">
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
														<a href="http://sourceforge.net/project/showfiles.php?group_id=2435&amp;package_id=240780">
																<font color="#6fbc4c">Automated MinGW Installer </font>
														</a>
												</p>
										</td>
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
														<a href="http://sourceforge.net/project/showfiles.php?group_id=2435&amp;package_id=240780&amp;release_id=595197">
																<font color="#6fbc4c">MinGW 5.1.4 </font>
														</a>
												</p>
										</td>
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">April 26, 2008 </p>
										</td>
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> </p>
										</td>
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"> </p>
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
														<a href="http://sourceforge.net/project/showfiles.php?group_id=2435&amp;package_id=240780&amp;release_id=595197">
														</a>
												</p>
										</td>
								</tr>
						</tbody>
				</table>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<br />
						<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第二步：下载</span>Eclipse</p>
				<p style="FONT-SIZE: 14pt">
				</p>
				<table class="MsoNormalTable" style="WIDTH: 100%; mso-cellspacing: 0cm; mso-padding-alt: 0cm 0cm 0cm 0cm" cellspacing="0" cellpadding="0" width="100%" border="0">
						<tbody>
								<tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes">
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 45pt; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" valign="top" width="60">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
														<a href="http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/europa/winter/eclipse-cpp-europa-winter-win32.zip">
														</a>
														<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /?>
														<v:shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600">
																<v:stroke joinstyle="miter">
																</v:stroke>
																<v:formulas>
																		<v:f eqn="if lineDrawn pixelLineWidth 0">
																		</v:f>
																		<v:f eqn="sum @0 1 0">
																		</v:f>
																		<v:f eqn="sum 0 0 @1">
																		</v:f>
																		<v:f eqn="prod @2 1 2">
																		</v:f>
																		<v:f eqn="prod @3 21600 pixelWidth">
																		</v:f>
																		<v:f eqn="prod @3 21600 pixelHeight">
																		</v:f>
																		<v:f eqn="sum @0 0 1">
																		</v:f>
																		<v:f eqn="prod @6 1 2">
																		</v:f>
																		<v:f eqn="prod @7 21600 pixelWidth">
																		</v:f>
																		<v:f eqn="sum @8 21600 0">
																		</v:f>
																		<v:f eqn="prod @7 21600 pixelHeight">
																		</v:f>
																		<v:f eqn="sum @10 21600 0">
																		</v:f>
																</v:formulas>
																<v:path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f">
																</v:path>
																<o:lock aspectratio="t" v:ext="edit">
																</o:lock>
														</v:shapetype>
														<v:shape id="_x0000_s1026" style="MARGIN-TOP: -238.15pt; Z-INDEX: 1; MARGIN-LEFT: -90pt; WIDTH: 36pt; POSITION: absolute; HEIGHT: 36pt; mso-wrap-distance-left: 0; mso-wrap-distance-top: 0; mso-wrap-distance-right: 0; mso-wrap-distance-bottom: 0; mso-position-horizontal: absolute; mso-position-horizontal-relative: text; mso-position-vertical: absolute; mso-position-vertical-relative: line" o:button="t" o:allowoverlap="f" href="http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/europa/winter/eclipse-cpp-europa-winter-win32.zip" alt="" type="#_x0000_t75">
																<v:imagedata o:title="c" src="file:///C:\DOCUME~1\ehaojii\LOCALS~1\Temp\msohtml1\01\clip_image001.jpg">
																</v:imagedata>
																<?xml:namespace prefix = w ns = "urn:schemas-microsoft-com:office:word" /?>
																<w:wrap type="square">
																</w:wrap>
														</v:shape>
														<span class="MsoHyperlink">
																<a href="http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/europa/winter/eclipse-cpp-europa-winter-win32.zip">
																</a>
														</span>
												</p>
										</td>
										<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 0cm; BORDER-TOP: #d4d0c8; PADDING-LEFT: 0cm; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; PADDING-TOP: 0cm; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" valign="top">
												<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
														<a href="http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/europa/winter/eclipse-cpp-europa-winter-win32.zip">Eclipse IDE for C/C++ Developers </a>- Windows (60 MB)<br />An IDE for C/C++ developers. <a href="http://www.eclipse.org/downloads/moreinfo/c.php"><font color="#6fbc4c">Find out more... </font></a></p>
										</td>
								</tr>
						</tbody>
				</table>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
						<br />
						<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下载完之后，解压到某个目录，启动</span>Eclipse<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，它能检测到系统安装的</span>MinGW<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的相关东西，</span>g++<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</span>gcc<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编译器什么的都配置好了</span><br /><br /><br /><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第三步：下载安装</span><span lang="ZH-CN"></span><a href="http://www.devkitpro.org/downloads/devkitpro-windows-installer/">devkitPro Windows Installer  </a><br />    <span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以看这篇文章：</span><span lang="ZH-CN"></span><a href="http://bbs.pspchina.net/viewthread.php?tid=32263"><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">简述安装</span>devkitPSP<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">开发环境</span>, <span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">完全免用</span>Cygwin(5<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">月</span>24<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">日</span>:devkitPSP<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">新版於</span>120<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">楼</span>) </a><br /><br /><br /><br /><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">我安装在</span>c:\devkitpro<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">目录下，一些安装时下载的文件没有删除，此外我还创建一个</span>eclipse-workspace</p>
				<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">C:\devkitpro&gt;ls<br />PATH.txt                        doc                          msys-1.0.11-RC2.exe<br />Programmers Notepad         eclipse-workspace            pn2.0.8.718.zip<br />devkitPSP                   env.bat                      pspsdk-doc-20051113.tar.bz2<br />devkitPSP_r11-win32.exe     insight                      pspsdk.url<br />devkitPro.url               insight-6.8.50-20080425.exe  uninst.exe<br />devkitProUpdate.ini         installed.ini<br />devkitProUpdater-1.4.7.exe  msys</p>
				<p style="FONT-SIZE: 14pt">
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">
								<br />BTW</span>
						<span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">：我的系统</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">PATH</span>
						<span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">变量里新加入了下面三个路径</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">
								<br />   C:\devkitPro\msys\bin;<br />   C:\mingw\bin;<br />   C:\devkitPro\devkitPSP\bin;<br /><br /><br /></span>
						<span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">第四步：新建</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">Eclipse</span>
						<span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">工程，做一点配置，然后可以开发我们的程序</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">
								<br />
								<br />4.1 </span>
						<span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">创建</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">pspdemo</span>
						<span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">工程，选择</span>
						<span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">Makefile project </span>
						<span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">工程类型，然后一直下一步结束</span>
				</p>
		</font>
		<font color="#000000">
				<br />
				<img height="537" src="http://www.cppblog.com/images/cppblog_com/jht/step1.png" width="496" border="0" />
				<br />
				<br />
				<span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">4.2 </span>
				<span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">把默认生成的两个文件删除</span>
				<br />
				<br /> <img src="http://www.cppblog.com/images/cppblog_com/jht/step2.png" border="0" /><br /><br /><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">4.3 </span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">在工程目录上右键，选择属性，定位到如下选项卡上，选择创建或者链接目录，</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><br />      </span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">我们选择链接一个</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">psp sdk sample </span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">目录，完成</span><br /><img height="538" alt="" src="http://www.cppblog.com/images/cppblog_com/jht/step3.png" width="753" border="0" /><br /><br /><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">4.4 </span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">点击</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"> OK </span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">确认<br /></span><br /><img height="616" alt="" src="http://www.cppblog.com/images/cppblog_com/jht/step4.png" width="934" border="0" /><br /><br /><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">4.5 </span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">看到</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">beginobject </span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">这个目录已经进来了，</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">Makefile</span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">是</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"> sample</span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">自带的，右键选择</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">Makefile</span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">，然后选择</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">"Create a new Make target"</span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">，如下图</span><br /><br /><img height="474" alt="" src="http://www.cppblog.com/images/cppblog_com/jht/step5.png" width="452" border="0" /><br /><br /><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">4.6 </span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">上一步完成之后，我们双击右边</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"> make target</span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">视图中的</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">make all</span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">，就会编译这个</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">psp</span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">程序，如果不出意外，你应该能看到如图的</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">Console</span><span lang="ZH-CN" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-bidi-font-family: 'Times New Roman'">输出的</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><br style="mso-special-character: line-break" /></span><br /><img alt="" src="http://www.cppblog.com/images/cppblog_com/jht/step6.png" border="0" /><br />    <br /><br /><br /><br /><br /><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><font size="3">——————————————————————————————————————————————————————————<br /><br />OK<span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</span><span lang="ZH-CN"></span><span lang="ZH-CN" style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这样环境就搞定了</span></font></p><p style="FONT-SIZE: 14pt"><br /><br /></p></font>
<img src ="http://www.cppblog.com/jht/aggbug/53257.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jht/" target="_blank">季浩</a> 2008-06-14 18:02 <a href="http://www.cppblog.com/jht/archive/2008/06/14/53257.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载-sprintf你知道多少 </title><link>http://www.cppblog.com/jht/archive/2007/11/12/36444.html</link><dc:creator>季浩</dc:creator><author>季浩</author><pubDate>Mon, 12 Nov 2007 07:28:00 GMT</pubDate><guid>http://www.cppblog.com/jht/archive/2007/11/12/36444.html</guid><wfw:comment>http://www.cppblog.com/jht/comments/36444.html</wfw:comment><comments>http://www.cppblog.com/jht/archive/2007/11/12/36444.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jht/comments/commentRss/36444.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jht/services/trackbacks/36444.html</trackback:ping><description><![CDATA[<strong><font size="1">选自《CSDN 社区电子杂志——C/C++杂志》</font></strong><span id="ctl00_MainContentPlaceholder_ctl01_ctl00_lblEntry">
<p>
</p>
<p><strong></strong>
</p>
<p>在将各种类型的数据构造成字符串时，sprintf 的强大功能很少会让你失望。由于sprintf 跟printf 在用法上几乎一样，只是打印的目的地不同而已，前者打印到字符串中，后者则直接在命令行上输出。这也导致sprintf 比printf 有用得多。
</p>
<p>sprintf 是个变参函数，定义如下：<br><font color="#0000ff">int sprintf( char *buffer, const char *format [, argument] ... );</font><br>除了前两个参数类型固定外，后面可以接任意多个参数。而它的精华，显然就在第二个参数：<br>格式化字符串上。
</p>
<p><br>printf 和sprintf
都使用格式化字符串来指定串的格式，在格式串内部使用一些以&#8220;%&#8221;开头的格式说明符（format
specifications）来占据一个位置，在后边的变参列表中提供相应的变量，最终函数就会用相应位置的变量来替代那个说明符，产生一个调用者想要
的字符串。<br>
</p>
<p><strong>格式化数字字符串<br></strong>sprintf 最常见的应用之一莫过于把整数打印到字符串中，所以，spritnf 在大多数场合可以替代<br>itoa。
</p>
<p>如：<br><font color="#ff0000">//把整数123 打印成一个字符串保存在s 中。<br>sprintf(s, "%d", 123); //产生"123"<br>可以指定宽度，不足的左边补空格：<br>sprintf(s, "%8d%8d", 123, 4567); //产生：" 123 4567"<br>当然也可以左对齐：<br>sprintf(s, "%-8d%8d", 123, 4567); //产生："123 4567"<br>也可以按照16 进制打印：<br>sprintf(s, "%8x", 4567); //小写16 进制，宽度占8 个位置，右对齐<br>sprintf(s, "%-8X", 4568); //大写16 进制，宽度占8 个位置，左对齐</font>
</p>
<p><font color="#ff0000">这样，一个整数的16 进制字符串就很容易得到，但我们在打印16 进制内容时，通常想要一种左边补0 的等宽格式，那该怎么做呢？很简单，在表示宽度的数字前面加个0 就可以了。<br>sprintf(s, "%08X", 4567); //产生："000011D7"<br>上面以&#8221;%d&#8221;进行的10 进制打印同样也可以使用这种左边补0 的方式。</font>
</p>
<p><br>这里要注意一个符号扩展的问题：比如，假如我们想打印短整数（short）-1 的内存16 进制表示形式，在Win32 平台上，一个short 型占2 个字节，所以我们自然希望用4 个16 进制数字来打印它：<br>short si = -1;<br>sprintf(s, "%04X", si);<br>产
生&#8220;FFFFFFFF&#8221;，怎么回事？因为spritnf
是个变参函数，除了前面两个参数之外，后面的参数都不是类型安全的，函数更没有办法仅仅通过一个&#8220;%X&#8221;就能得知当初函数调用前参数压栈时被压进来的到底
是个4 字节的整数还是个2 字节的短整数，所以采取了统一4 字节的处理方式，导致参数压栈时做了符号扩展，扩展成了32 位的整数-1，打印时4
个位置不够了，就把32 位整数-1 的8 位16 进制都打印出来了。
</p>
<p>如果你想看si 的本来面目，那么就应该让编译器做0 扩展而不是符号扩展（扩展时二进制左边补0 而不是补符号位）：<br>sprintf(s, "%04X", (unsigned short)si);<br>就可以了。或者：<br>unsigned short si = -1;<br>sprintf(s, "%04X", si);
</p>
<p><br>sprintf 和printf 还可以按8 进制打印整数字符串，使用&#8221;%o&#8221;。注意8 进制和16 进制都不会打<br>印出负数，都是无符号的，实际上也就是变量的内部编码的直接的16 进制或8 进制表示。<br>
</p>
<p><strong>控制浮点数打印格式<br></strong>浮点数的打印和格式控制是sprintf 的又一大常用功能，浮点数使用格式符&#8221;%f&#8221;控制，默认保<br>留小数点后6 位数字，比如：<br>sprintf(s, "%f", 3.1415926); //产生"3.141593"<br>但有时我们希望自己控制打印的宽度和小数位数，这时就应该使用：&#8221;%m.nf&#8221;格式，其中m 表<br>示打印的宽度，n 表示小数点后的位数。比如：<br>sprintf(s, "%10.3f", 3.1415626); //产生：" 3.142"<br>sprintf(s, "%-10.3f", 3.1415626); //产生："3.142 "<br>sprintf(s, "%.3f", 3.1415626); //不指定总宽度，产生："3.142"<br>
</p>
<p>注意一个问题，你猜<br>int i = 100;<br>sprintf(s, "%.2f", i);<br>会打出什么东东来？&#8220;100.00&#8221;？对吗？自己试试就知道了，同时也试试下面这个：<br>sprintf(s, "%.2f", (double)i);<br>第
一个打出来的肯定不是正确结果，原因跟前面提到的一样，参数压栈时调用者并不知道跟i相对应的格式控制符是个&#8221;%f&#8221;。而函数执行时函数本身则并不知道当
年被压入栈里的是个整数，于是可怜的保存整数i 的那4
个字节就被不由分说地强行作为浮点数格式来解释了，整个乱套了。不过，如果有人有兴趣使用手工编码一个浮点数，那么倒可以使用这种方法来检验一下你手工编
排的结果是否正确。<br>
</p>
<p><strong>字符/Ascii 码对照<br></strong>我们知道，在C/C++语言中，char 也是一种普通的scalable 类型，除了字长之外，它与short，<br>int，long 这些类型没有本质区别，只不过被大家习惯用来表示字符和字符串而已。（或许当年该把<br>这
个类型叫做&#8220;byte&#8221;，然后现在就可以根据实际情况，使用byte 或short 来把char 通过typedef
定义出来，这样更合适些）于是，使用&#8221;%d&#8221;或者&#8221;%x&#8221;打印一个字符，便能得出它的10 进制或16 进制的ASCII
码；反过来，使用&#8221;%c&#8221;打印一个整数，便可以看到它所对应的ASCII 字符。以下程序段把所有可见字符的ASCII
码对照表打印到屏幕上（这里采用printf，注意&#8221;#&#8221;与&#8221;%X&#8221;合用时自动为16 进制数增加&#8221;0X&#8221;前缀）：<br>for(int i = 32; i &lt; 127; i++) {<br>printf("[ %c ]: %3d 0x%#04X<br>", i, i, i);<br>}
</p>
<p><br><font color="#ff0000"><strong>连接字符串</strong><br>sprintf 的格式控制串中既然可以插入各种东西，并最终把它们&#8220;连成一串&#8221;，自然也就能够连<br>接字符串，从而在许多场合可以替代strcat，但sprintf 能够一次连接多个字符串（自然也可以同时<br>在它们中间插入别的内容，总之非常灵活）。比如：<br>char* who = "I";<br>char* whom = "CSDN";<br>sprintf(s, "%s love %s.", who, whom); //产生："I love CSDN. "</font><br>strcat
只能连接字符串（一段以&#8217;&#8217;结尾的字符数组或叫做字符缓冲，null-terminated-string），但有时我们有两段字符缓冲区，他们并不是以
&#8217;&#8217;结尾。比如许多从第三方库函数中返回的字符数组，从硬件或者网络传输中读进来的字符流，它们未必每一段字符序列后面都有个相应的&#8217;&#8217;来结尾。如果直接
连接，不管是sprintf 还是strcat 肯定会导致非法内存操作，而strncat
也至少要求第一个参数是个null-terminated-string，那该怎么办呢？我们自然会想起前面介绍打印整数和浮点数时可以指定宽度，字符串
也一样的。比如：<br>char a1[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};<br>char a2[] = {'H', 'I', 'J', 'K', 'L', 'M', 'N'};<br>如果：<br>sprintf(s, "%s%s", a1, a2); //Don't do that!<br>十有八九要出问题了。是否可以改成：<br>sprintf(s, "%7s%7s", a1, a2);<br>也没好到哪儿去，正确的应该是：<br>sprintf(s, "%.7s%.7s", a1, a2);//产生："ABCDEFGHIJKLMN"<br>这
可以类比打印浮点数的&#8221;%m.nf&#8221;，在&#8221;%m.ns&#8221;中，m 表示占用宽度（字符串长度不足时补空格，超出了则按照实际宽度打印），n
才表示从相应的字符串中最多取用的字符数。通常在打印字符串时m 没什么大用，还是点号后面的n 用的多。自然，也可以前后都只取部分字符：<br>sprintf(s, "%.6s%.5s", a1, a2);//产生："ABCDEFHIJKL"<br><font color="#ff0000">在
许多时候，我们或许还希望这些格式控制符中用以指定长度信息的数字是动态的，而不是静态指定的，因为许多时候，程序要到运行时才会清楚到底需要取字符数组
中的几个字符，这种动态的宽度/精度设置功能在sprintf 的实现中也被考虑到了，sprintf
采用&#8221;*&#8221;来占用一个本来需要一个指定宽度或精度的常数数字的位置，同样，而实际的宽度或精度就可以和其它被打印的变量一样被提供出来，于是，上面的例子
可以变成：<br>sprintf(s, "%.*s%.*s", 7, a1, 7, a2);<br>或者：<br>sprintf(s, "%.*s%.*s", sizeof(a1), a1, sizeof(a2), a2);<br>实际上，前面介绍的打印字符、整数、浮点数等都可以动态指定那些常量值，比如：<br>sprintf(s, "%-*d", 4, 'A'); //产生"65 "<br>sprintf(s, "%#0*X", 8, 128); //产生"0X000080"，"#"产生0X<br>sprintf(s, "%*.*f", 10, 2, 3.1415926); //产生" 3.14"</font>
</p>
<p><br><strong>打印地址信息<br></strong>有时调试程序时，我们可能想查看某些变量或者成员的地址，由于地址或者指针也不过是个32 位的数，你完全可以使用打印无符号整数的&#8221;%u&#8221;把他们打印出来：<br>sprintf(s, "%u", &amp;i);<br>不过通常人们还是喜欢使用16 进制而不是10 进制来显示一个地址：<br>sprintf(s, "%08X", &amp;i);<br>然而，这些都是间接的方法，对于地址打印，sprintf 提供了专门的&#8221;%p&#8221;：<br>sprintf(s, "%p", &amp;i);<br>我觉得它实际上就相当于：<br>sprintf(s, "%0*x", 2 * sizeof(void *), &amp;i);<br>利用sprintf 的返回值<br>较少有人注意printf/sprintf 函数的返回值，但有时它却是有用的，spritnf 返回了本次函数调用<br>最终打印到字符缓冲区中的字符数目。也就是说每当一次sprinf 调用结束以后，你无须再调用一次<br>strlen 便已经知道了结果字符串的长度。如：<br>int len = sprintf(s, "%d", i);<br>对于正整数来说，len 便等于整数i 的10 进制位数。<br>下面的是个完整的例子，产生10 个[0, 100)之间的随机数，并将他们打印到一个字符数组s 中，<br>以逗号分隔开。<br>#include <br>#include <br>#include <br>int main() {<br>srand(time(0));<br>char s[64];<br>int offset = 0;<br>for(int i = 0; i &lt; 10; i++) {<br>offset += sprintf(s + offset, "%d,", rand() % 100);<br>}<br>s[offset - 1] = '<br>';//将最后一个逗号换成换行符。<br>printf(s);<br>return 0;<br>}<br>设想当你从数据库中取出一条记录，然后希望把他们的各个字段按照某种规则连接成一个字<br>符串时，就可以使用这种方法，从理论上讲，他应该比不断的strcat 效率高，因为strcat 每次调用<br>都需要先找到最后的那个&#8217;&#8217;的位置，而在上面给出的例子中，我们每次都利用sprintf 返回值把这<br>个位置直接记下来了。
</p>
<p><br><strong>使用sprintf 的常见问题</strong><br>sprintf 是个变参函数，使用时经常出问题，而且只要出问题通常就是能导致程序崩溃的内存访<br>问错误，但好在由sprintf 误用导致的问题虽然严重，却很容易找出，无非就是那么几种情况，通<br>常用眼睛再把出错的代码多看几眼就看出来了。
</p>
<p><br>?? 缓冲区溢出<br>第一个参数的长度太短了，没的说，给个大点的地方吧。当然也可能是后面的参数的问<br>题，建议变参对应一定要细心，而打印字符串时，尽量使用&#8221;%.ns&#8221;的形式指定最大字符数。
</p>
<p><br>?? 忘记了第一个参数<br>低级得不能再低级问题，用printf 用得太惯了。//偶就常犯。：。（
</p>
<p><br>?? 变参对应出问题<br>通常是忘记了提供对应某个格式符的变参，导致以后的参数统统错位，检查检查吧。尤<br>其是对应&#8221;*&#8221;的那些参数，都提供了吗？不要把一个整数对应一个&#8221;%s&#8221;，编译器会觉得你<br>欺她太甚了（编译器是obj 和exe 的妈妈，应该是个女的，:P）。<br>
</p>
<p>strftime<br>sprnitf 还有个不错的表妹：strftime，专门用于格式化时间字符串的，用法跟她表哥很像，也<br>是一大堆格式控制符，只是毕竟小姑娘家心细，她还要调用者指定缓冲区的最大长度，可能是为<br>了在出现问题时可以推卸责任吧。这里举个例子：<br>time_t t = time(0);<br>//产生"YYYY-MM-DD hh:mm:ss"格式的字符串。<br>char s[32];<br>strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", localtime(&amp;t));<br>sprintf 在MFC 中也能找到他的知音：CString::Format，strftime 在MFC 中自然也有她的同道：<br>CTime::Format，这一对由于从面向对象哪里得到了赞助，用以写出的代码更觉优雅。
</p>
<p>&nbsp;
</p>
<p><font color="#ff0000" size="3">C语言标准库函数::strncmp()</font>
</p>
<h2>函数原型</h2>
<pre> int strncmp(char *str1, char *str2, int maxlen);</pre>
<pre>
<h2>函数功能</h2>
<pre> 比较字符串s1和s2的前n个字符。<br> 当s1&lt;s2时，返回值&lt;0<br> 当s1=s2时，返回值=0<br> 当s1&gt;s2时，返回值&gt;0<br>
<h2>声明文件</h2>
<pre> &lt;string.h&gt;</pre>
<pre>
<h2>用法示例</h2>
<pre> #include &lt;stdio.h&gt;<br> #include &lt;string.h&gt;<br><br> int main(void) <br> { <br>   char *buf1 = "aaabbb", *buf2 = "bbbccc", *buf3 = "ccc"; <br>   int ptr; <br>   ptr = strncmp(buf2,buf1,3);<br>   if (ptr &gt; 0) <br>     printf("buffer 2 is greater than buffer 1\n"); <br>   else <br>     printf("buffer 2 is less than buffer 1\n");<br>   ptr = strncmp(buf2,buf3,3);<br>   if (ptr &gt; 0) <br>     printf("buffer 2 is greater than buffer 3\n"); <br>   else <br>     printf("buffer 2 is less than buffer 3\n"); <br>   return(0); <br> }<br></pre>
</pre>
</pre>
</pre>
</span> <img src ="http://www.cppblog.com/jht/aggbug/36444.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jht/" target="_blank">季浩</a> 2007-11-12 15:28 <a href="http://www.cppblog.com/jht/archive/2007/11/12/36444.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>/bin/sh.exe: C:Qt4.2.2 binmoc.exe: command not found</title><link>http://www.cppblog.com/jht/archive/2007/01/30/18165.html</link><dc:creator>季浩</dc:creator><author>季浩</author><pubDate>Tue, 30 Jan 2007 01:35:00 GMT</pubDate><guid>http://www.cppblog.com/jht/archive/2007/01/30/18165.html</guid><wfw:comment>http://www.cppblog.com/jht/comments/18165.html</wfw:comment><comments>http://www.cppblog.com/jht/archive/2007/01/30/18165.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jht/comments/commentRss/18165.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jht/services/trackbacks/18165.html</trackback:ping><description><![CDATA[
		<p>环境Windows OS + Eclipse + CDT ＋QTClipse＋MinGW＋MSYS＋QT 编译QT程序，遇到上面的一个问题，感觉怎么像是在linux下编译，想了想现象，觉得应该是MSYS的问题，查了下MSYS\bin\下面的sh.exe，好像是着个引起的，于是把这个sh.exe移到bin外面，就是说sh.exe现在不在我的环境变量PATH里面了，编译了一把，果然成功了<br /><br />然后搜索了一下这个问题，关键词sh.exe QT 搜到这样一篇文章，Solution也差不多<br /><a href="http://lists.trolltech.com/qt-interest/2005-12/thread00777-0.html">http://lists.trolltech.com/qt-interest/2005-12/thread00777-0.html</a><br /></p>
<img src ="http://www.cppblog.com/jht/aggbug/18165.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jht/" target="_blank">季浩</a> 2007-01-30 09:35 <a href="http://www.cppblog.com/jht/archive/2007/01/30/18165.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C语言 文件操作 -转载自编程爱好者论坛</title><link>http://www.cppblog.com/jht/archive/2006/05/31/7933.html</link><dc:creator>季浩</dc:creator><author>季浩</author><pubDate>Wed, 31 May 2006 05:33:00 GMT</pubDate><guid>http://www.cppblog.com/jht/archive/2006/05/31/7933.html</guid><wfw:comment>http://www.cppblog.com/jht/comments/7933.html</wfw:comment><comments>http://www.cppblog.com/jht/archive/2006/05/31/7933.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/jht/comments/commentRss/7933.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jht/services/trackbacks/7933.html</trackback:ping><description><![CDATA[所谓“文件”是指一组相关数据的有序集合。 这个数据集有一个名称，叫做文件名。 实际上在前面的各章中我们已经多次使用了文件，例如源程序文件、目标文件、可执行文件、库文件 (头文件)等。文件通常是驻留在外部介质(如磁盘等)上的， 在使用时才调入内存中来。从不同的角度可对文件作不同的分类。从用户的角度看，文件可分为普通文件和设备文件两种。 <br /><br />　　普通文件是指驻留在磁盘或其它外部介质上的一个有序数据集，可以是源文件、目标文件、可执行程序； 也可以是一组待输入处理的原始数据，或者是一组输出的结果。对于源文件、目标文件、 可执行程序可以称作程序文件，对输入输出数据可称作数据文件。<br /><br />　　设备文件是指与主机相联的各种外部设备，如显示器、打印机、键盘等。在操作系统中，把外部设备也看作是一个文件来进行管理，把它们的输入、输出等同于对磁盘文件的读和写。 通常把显示器定义为标准输出文件， 一般情况下在屏幕上显示有关信息就是向标准输出文件输出。如前面经常使用的printf,putchar 函数就是这类输出。键盘通常被指定标准的输入文件， 从键盘上输入就意味着从标准输入文件上输入数据。scanf,getchar函数就属于这类输入。 <br /><br />　　从文件编码的方式来看，文件可分为ASCII码文件和二进制码文件两种。<br /><br />　　ASCII文件也称为文本文件，这种文件在磁盘中存放时每个字符对应一个字节，用于存放对应的ASCII码。例如，数5678的存储形式为：<br />ASC码： 　00110101 00110110 00110111 00111000<br />　　　　　↓ 　　　　↓　　　　↓ 　　　↓<br />十进制码： 5　　　　　6　　　　7　　　　8 共占用4个字节。ASCII码文件可在屏幕上按字符显示， 例如源程序文件就是ASCII文件，用DOS命令TYPE可显示文件的内容。 由于是按字符显示，因此能读懂文件内容。<br /><br />　　二进制文件是按二进制的编码方式来存放文件的。 例如， 数5678的存储形式为： 00010110 00101110只占二个字节。二进制文件虽然也可在屏幕上显示， 但其内容无法读懂。C系统在处理这些文件时，并不区分类型，都看成是字符流，按字节进行处理。 输入输出字符流的开始和结束只由程序控制而不受物理符号(如回车符)的控制。 因此也把这种文件称作“流式文件”。<br /><br />　　本章讨论流式文件的打开、关闭、读、写、 定位等各种操作。文件指针在C语言中用一个指针变量指向一个文件， 这个指针称为文件指针。通过文件指针就可对它所指的文件进行各种操作。 定义说明文件指针的一般形式为： FILE* 指针变量标识符； 其中FILE应为大写，它实际上是由系统定义的一个结构， 该结构中含有文件名、文件状态和文件当前位置等信息。 在编写源程序时不必关心FILE结构的细节。例如：FILE *fp； 表示fp是指向FILE结构的指针变量，通过fp 即可找存放某个文件信息的结构变量，然后按结构变量提供的信息找到该文件， 实施对文件的操作。习惯上也笼统地把fp称为指向一个文件的指针。文件的打开与关闭文件在进行读写操作之前要先打开，使用完毕要关闭。 所谓打开文件，实际上是建立文件的各种有关信息， 并使文件指针指向该文件，以便进行其它操作。关闭文件则断开指针与文件之间的联系，也就禁止再对该文件进行操作。<br /><br />　　在C语言中，文件操作都是由库函数来完成的。 在本章内将介绍主要的文件操作函数。<br /><br />　　文件打开函数fopen<br /><br />　　fopen函数用来打开一个文件，其调用的一般形式为： 文件指针名=fopen(文件名，使用文件方式) 其中，“文件指针名”必须是被说明为FILE 类型的指针变量，“文件名”是被打开文件的文件名。 “使用文件方式”是指文件的类型和操作要求。“文件名”是字符串常量或字符串数组。例如： <br /><br />FILE *fp；<br />fp=("file a","r"); <br /><br />　　其意义是在当前目录下打开文件file a， 只允许进行“读”操作，并使fp指向该文件。<br /><br />　　又如：<br /><br />FILE *fphzk<br />fphzk=("c:\\hzk16',"rb") <br /><br />　　其意义是打开C驱动器磁盘的根目录下的文件hzk16， 这是一个二进制文件，只允许按二进制方式进行读操作。两个反斜线“\\ ”中的第一个表示转义字符，第二个表示根目录。使用文件的方式共有12种，下面给出了它们的符号和意义。 <br /><br />文件使用方式 　　　　　　　意 义<br />“rt”　　　　　　只读打开一个文本文件，只允许读数据 <br />“wt”　　　　　　只写打开或建立一个文本文件，只允许写数据<br />“at”　　　　　　追加打开一个文本文件，并在文件末尾写数据<br />“rb”　　　　　　只读打开一个二进制文件，只允许读数据<br />“wb”　　　　 　 只写打开或建立一个二进制文件，只允许写数据<br />“ab” 　　　　 　追加打开一个二进制文件，并在文件末尾写数据<br />“rt+”　　　　　 读写打开一个文本文件，允许读和写<br />“wt+”　　　　　 读写打开或建立一个文本文件，允许读写<br />“at+”　　　　　 读写打开一个文本文件，允许读，或在文件末追加数 据<br />“rb+”　　　　　 读写打开一个二进制文件，允许读和写 <br />“wb+”　　　　　 读写打开或建立一个二进制文件，允许读和写<br />“ab+” 　　　　　读写打开一个二进制文件，允许读，或在文件末追加数据<br /><br />　　对于文件使用方式有以下几点说明：<br /><br />　　1. 文件使用方式由r,w,a,t,b，+六个字符拼成，各字符的含义是：<br /><br />　　r(read): 读<br />　　w(write): 写<br />　　a(append): 追加<br />　　t(text): 文本文件，可省略不写<br />　　b(banary): 二进制文件<br />　　+: 读和写<br /><br />　　2. 凡用“r”打开一个文件时，该文件必须已经存在， 且只能从该文件读出。<br /><br />　　3. 用“w”打开的文件只能向该文件写入。 若打开的文件不存在，则以指定的文件名建立该文件，若打开的文件已经存在，则将该文件删去，重建一个新文件。<br /><br />　　4. 若要向一个已存在的文件追加新的信息，只能用“a ”方式打开文件。但此时该文件必须是存在的，否则将会出错。<br /><br />　　5. 在打开一个文件时，如果出错，fopen将返回一个空指针值NULL。在程序中可以用这一信息来判别是否完成打开文件的工作，并作相应的处理。因此常用以下程序段打开文件：<br /><br />if((fp=fopen("c:\\hzk16","rb")==NULL)<br />{<br />printf("\nerror on open c:\\hzk16 file!");<br />getch();<br />exit(1);<br />} <br /><br />　　这段程序的意义是，如果返回的指针为空，表示不能打开C盘根目录下的hzk16文件，则给出提示信息“error on open c:\ hzk16file!”，下一行getch()的功能是从键盘输入一个字符，但不在屏幕上显示。在这里，该行的作用是等待， 只有当用户从键盘敲任一键时，程序才继续执行， 因此用户可利用这个等待时间阅读出错提示。敲键后执行exit(1)退出程序。<br /><br />　　6. 把一个文本文件读入内存时，要将ASCII码转换成二进制码， 而把文件以文本方式写入磁盘时，也要把二进制码转换成ASCII码，因此文本文件的读写要花费较多的转换时间。对二进制文件的读写不存在这种转换。<br /><br />　　7. 标准输入文件(键盘)，标准输出文件(显示器 )，标准出错输出(出错信息)是由系统打开的，可直接使用。文件关闭函数ｆCｌｏｓｅ文件一旦使用完毕，应用关闭文件函数把文件关闭， 以避免文件的数据丢失等错误。<br /><br />　　fclose函数<br /><br />　　调用的一般形式是： fclose(文件指针)； 例如：<br /><br />　　fclose(fp); 正常完成关闭文件操作时，fclose函数返回值为0。如返回非零值则表示有错误发生。文件的读写对文件的读和写是最常用的文件操作。 <br /><br />　　在C语言中提供了多种文件读写的函数： <br /><br />　　·字符读写函数 ：fgetc和fputc<br /><br />　　·字符串读写函数：fgets和fputs<br /><br />　　·数据块读写函数：freed和fwrite<br /><br />　　·格式化读写函数：fscanf和fprinf<br /><br />　　下面分别予以介绍。使用以上函数都要求包含头文件stdio.h。字符读写函数ｆｇｅｔC和ｆｐｕｔC字符读写函数是以字符(字节)为单位的读写函数。 每次可从文件读出或向文件写入一个字符。<br /><br />　　一、读字符函数fgetc<br /><br />　　fgetc函数的功能是从指定的文件中读一个字符，函数调用的形式为： 字符变量=fgetc(文件指针)； 例如：ch=fgetc(fp);其意义是从打开的文件fp中读取一个字符并送入ch中。<br /><br />　　对于fgetc函数的使用有以下几点说明：<br /><br />　　1. 在fgetc函数调用中，读取的文件必须是以读或读写方式打开的。<br /><br />　　2. 读取字符的结果也可以不向字符变量赋值，例如：fgetc(fp);但是读出的字符不能保存。<br /><br />　　3. 在文件内部有一个位置指针。用来指向文件的当前读写字节。在文件打开时，该指针总是指向文件的第一个字节。使用fgetc 函数后， 该位置指针将向后移动一个字节。 因此可连续多次使用fgetc函数，读取多个字符。 应注意文件指针和文件内部的位置指针不是一回事。文件指针是指向整个文件的，须在程序中定义说明，只要不重新赋值，文件指针的值是不变的。文件内部的位置指针用以指示文件内部的当前读写位置，每读写一次，该指针均向后移动，它不需在程序中定义说明，而是由系统自动设置的。<br /><br />　　[例10.1]读入文件e10-1.c，在屏幕上输出。<br /><br />#include&lt;stdio.h&gt;<br />main()<br />{<br />FILE *fp;<br />char ch;<br />if((fp=fopen("e10_1.c","rt"))==NULL)<br />{<br />printf("Cannot open file strike any key exit!");<br />getch();<br />exit(1);<br />}<br />ch=fgetc(fp);<br />while (ch!=EOF)<br />{<br />putchar(ch);<br />ch=fgetc(fp);<br />}<br />fclose(fp);<br />} <br /><br />　　本例程序的功能是从文件中逐个读取字符，在屏幕上显示。 程序定义了文件指针fp,以读文本文件方式打开文件“e10_1.c”， 并使fp指向该文件。如打开文件出错， 给出提示并退出程序。程序第12行先读出一个字符，然后进入循环， 只要读出的字符不是文件结束标志(每个文件末有一结束标志EOF)就把该字符显示在屏幕上，再读入下一字符。每读一次，文件内部的位置指针向后移动一个字符，文件结束时，该指针指向EOF。执行本程序将显示整个文件。<br /><br />　　二、写字符函数fputc<br /><br />　　fputc函数的功能是把一个字符写入指定的文件中，函数调用的 形式为： fputc(字符量，文件指针)； 其中，待写入的字符量可以是字符常量或变量，例如：fputc('a',fp);其意义是把字符a写入fp所指向的文件中。<br /><br />　　对于fputc函数的使用也要说明几点：<br /><br />　　1. 被写入的文件可以用、写、读写，追加方式打开，用写或读写方式打开一个已存在的文件时将清除原有的文件内容，写入字符从文件首开始。如需保留原有文件内容，希望写入的字符以文件末开始存放，必须以追加方式打开文件。被写入的文件若不存在，则创建该文件。<br /><br />　　2. 每写入一个字符，文件内部位置指针向后移动一个字节。<br /><br />　　3. fputc函数有一个返回值，如写入成功则返回写入的字符， 否则返回一个EOF。可用此来判断写入是否成功。<br /><br />　　[例10.2]从键盘输入一行字符，写入一个文件， 再把该文件内容读出显示在屏幕上。<br /><br />#include&lt;stdio.h&gt;<br />main()<br />{<br />FILE *fp;<br />char ch;<br />if((fp=fopen("string","wt+"))==NULL)<br />{<br />printf("Cannot open file strike any key exit!");<br />getch();<br />exit(1);<br />}<br />printf("input a string:\n");<br />ch=getchar();<br />while (ch!='\n')<br />{<br />fputc(ch,fp);<br />ch=getchar();<br />}<br />rewind(fp);<br />ch=fgetc(fp);<br />while(ch!=EOF)<br />{<br />putchar(ch);<br />ch=fgetc(fp);<br />}<br />printf("\n");<br />fclose(fp);<br />} <br /><br />　　程序中第6行以读写文本文件方式打开文件string。程序第13行从键盘读入一个字符后进入循环，当读入字符不为回车符时， 则把该字符写入文件之中，然后继续从键盘读入下一字符。 每输入一个字符，文件内部位置指针向后移动一个字节。写入完毕， 该指针已指向文件末。如要把文件从头读出，须把指针移向文件头， 程序第19行rewind函数用于把fp所指文件的内部位置指针移到文件头。 第20至25行用于读出文件中的一行内容。<br /><br />　　[例10.3]把命令行参数中的前一个文件名标识的文件， 复制到后一个文件名标识的文件中， 如命令行中只有一个文件名则把该文件写到标准输出文件(显示器)中。<br /><br />#include&lt;stdio.h&gt;<br />main(int argc,char *argv[])<br />{<br />FILE *fp1,*fp2;<br />char ch;<br />if(argc==1)<br />{<br />printf("have not enter file name strike any key exit");<br />getch();<br />exit(0);<br />}<br />if((fp1=fopen(argv[1],"rt"))==NULL)<br />{<br />printf("Cannot open %s\n",argv[1]);<br />getch();<br />exit(1);<br />}<br />if(argc==2) fp2=stdout;<br />else if((fp2=fopen(argv[2],"wt+"))==NULL)<br />{<br />printf("Cannot open %s\n",argv[1]);<br />getch();<br />exit(1);<br />}<br />while((ch=fgetc(fp1))!=EOF)<br />fputc(ch,fp2);<br />fclose(fp1);<br />fclose(fp2);<br />} <br /><br />　　本程序为带参的main函数。程序中定义了两个文件指针 fp1 和fp2，分别指向命令行参数中给出的文件。如命令行参数中没有给出文件名，则给出提示信息。程序第18行表示如果只给出一个文件名，则使fp2指向标准输出文件(即显示器)。程序第25行至28行用循环语句逐个读出文件1中的字符再送到文件2中。再次运行时，给出了一个文件名(由例10.2所建立的文件)， 故输出给标准输出文件stdout，即在显示器上显示文件内容。第三次运行，给出了二个文件名，因此把string中的内容读出，写入到OK之中。可用DOS命令type显示OK的内容：<br /><br /><br /><br />********************************************************************************************<br /><br />字符串读写函数fgets和fputs<br /><br />　　一、读字符串函数fgets函数的功能是从指定的文件中读一个字符串到字符数组中，函数调用的形式为： fgets(字符数组名，n，文件指针)； 其中的n是一个正整数。表示从文件中读出的字符串不超过 n-1个字符。在读入的最后一个字符后加上串结束标志'\0'。例如：fgets(str,n,fp);的意义是从fp所指的文件中读出n-1个字符送入字符数组str中。<br /><br />　　[例10.4]从e10_1.c文件中读入一个含10个字符的字符串。<br /><br />#include&lt;stdio.h&gt;<br />main()<br />{<br />FILE *fp;<br />char str[11];<br />if((fp=fopen("e10_1.c","rt"))==NULL)<br />{<br />printf("Cannot open file strike any key exit!");<br />getch();<br />exit(1);<br />}<br />fgets(str,11,fp);<br />printf("%s",str);<br />fclose(fp);<br />} <br /><br />　　本例定义了一个字符数组str共11个字节，在以读文本文件方式打开文件e101.c后，从中读出10个字符送入str数组，在数组最后一个单元内将加上'\0'，然后在屏幕上显示输出str数组。输出的十个字符正是例10.1程序的前十个字符。<br /><br />　　对fgets函数有两点说明：<br /><br />　　1. 在读出n-1个字符之前，如遇到了换行符或EOF，则读出结束。<br /><br />　　2. fgets函数也有返回值，其返回值是字符数组的首地址。<br /><br />　　二、写字符串函数fputs<br /><br />　　fputs函数的功能是向指定的文件写入一个字符串，其调用形式为： fputs(字符串，文件指针) 其中字符串可以是字符串常量，也可以是字符数组名， 或指针 变量，例如：<br /><br />fputs(“abcd“，fp)；<br /><br />　　其意义是把字符串“abcd”写入fp所指的文件之中。[例10.5]在例10.2中建立的文件string中追加一个字符串。<br /><br />#include&lt;stdio.h&gt;<br />main()<br />{<br />FILE *fp;<br />char ch,st[20];<br />if((fp=fopen("string","at+"))==NULL)<br />{<br />printf("Cannot open file strike any key exit!");<br />getch();<br />exit(1);<br />}<br />printf("input a string:\n");<br />scanf("%s",st);<br />fputs(st,fp);<br />rewind(fp);<br />ch=fgetc(fp);<br />while(ch!=EOF)<br />{<br />putchar(ch);<br />ch=fgetc(fp);<br />}<br />printf("\n");<br />fclose(fp);<br />} <br /><br />　　本例要求在string文件末加写字符串，因此，在程序第6行以追加读写文本文件的方式打开文件string 。 然后输入字符串， 并用fputs函数把该串写入文件string。在程序15行用rewind函数把文件内部位置指针移到文件首。 再进入循环逐个显示当前文件中的全部内容。<br /><br /><br />　　数据块读写函数fread和fwrite<br /><br />　　C语言还提供了用于整块数据的读写函数。 可用来读写一组数据，如一个数组元素，一个结构变量的值等。读数据块函数调用的一般形式为： fread(buffer,size,count,fp); 写数据块函数调用的一般形式为： fwrite(buffer,size,count,fp); 其中buffer是一个指针，在fread函数中，它表示存放输入数据的首地址。在fwrite函数中，它表示存放输出数据的首地址。 size 表示数据块的字节数。count 表示要读写的数据块块数。fp 表示文件指针。<br /><br />　　例如：<br /><br />fread(fa,4,5,fp); 其意义是从fp所指的文件中，每次读4个字节(一个实数)送入实数组fa中，连续读5次，即读5个实数到fa中。<br /><br />　　[例10.6]从键盘输入两个学生数据，写入一个文件中， 再读出这两个学生的数据显示在屏幕上。<br /><br />#include&lt;stdio.h&gt;<br />struct stu<br />{<br />char name[10];<br />int num;<br />int age;<br />char addr[15];<br />}boya[2],boyb[2],*pp,*qq;<br />main()<br />{<br />FILE *fp;<br />char ch;<br />int i;<br />pp=boya;<br />qq=boyb;<br />if((fp=fopen("stu_list","wb+"))==NULL)<br />{<br />printf("Cannot open file strike any key exit!");<br />getch();<br />exit(1);<br />}<br />printf("\ninput data\n");<br />for(i=0;i&lt;2;i++,pp++)<br />scanf("%s%d%d%s",pp-&gt;name,&amp;pp-&gt;num,&amp;pp-&gt;age,pp-&gt;addr);<br />pp=boya;<br />fwrite(pp,sizeof(struct stu),2,fp);<br />rewind(fp);<br />fread(qq,sizeof(struct stu),2,fp);<br />printf("\n\nname\tnumber age addr\n");<br />for(i=0;i&lt;2;i++,qq++)<br />printf("%s\t%5d%7d%s\n",qq-&gt;name,qq-&gt;num,qq-&gt;age,qq-&gt;addr);<br />fclose(fp);<br />} <br /><br />　　本例程序定义了一个结构stu,说明了两个结构数组boya和 boyb以及两个结构指针变量pp和qq。pp指向boya,qq指向boyb。程序第16行以读写方式打开二进制文件“stu_list”，输入二个学生数据之后，写入该文件中， 然后把文件内部位置指针移到文件首，读出两块学生数据后，在屏幕上显示。<br /><br />　　格式化读写函数fscanf和fprintf<br /><br />　　fscanf函数，fprintf函数与前面使用的scanf和printf 函数的功能相似，都是格式化读写函数。 两者的区别在于 fscanf 函数和fprintf函数的读写对象不是键盘和显示器，而是磁盘文件。这两个函数的调用格式为： fscanf(文件指针，格式字符串，输入表列)； fprintf(文件指针，格式字符串，输出表列)； 例如：<br /><br />　　fscanf(fp,"%d%s",&amp;i,s);<br />　　fprintf(fp,"%d%c",j,ch); <br /><br />　　用fscanf和fprintf函数也可以完成例10.6的问题。修改后的程序如例10.7所示。<br /><br />　　[例10.7]<br /><br />#include&lt;stdio.h&gt;<br />struct stu<br />{<br />char name[10];<br />int num;<br />int age;<br />char addr[15];<br />}boya[2],boyb[2],*pp,*qq;<br />main()<br />{<br />FILE *fp;<br />char ch;<br />int i;<br />pp=boya;<br />qq=boyb;<br />if((fp=fopen("stu_list","wb+"))==NULL)<br />{<br />printf("Cannot open file strike any key exit!");<br />getch();<br />exit(1);<br />}<br />printf("\ninput data\n");<br />for(i=0;i&lt;2;i++,pp++)<br />scanf("%s%d%d%s",pp-&gt;name,&amp;pp-&gt;num,&amp;pp-&gt;age,pp-&gt;addr);<br />pp=boya;<br />for(i=0;i&lt;2;i++,pp++)<br />fprintf(fp,"%s %d %d %s\n",pp-&gt;name,pp-&gt;num,pp-&gt;age,pp-&gt;<br />addr);<br />rewind(fp);<br />for(i=0;i&lt;2;i++,qq++)<br />fscanf(fp,"%s %d %d %s\n",qq-&gt;name,&amp;qq-&gt;num,&amp;qq-&gt;age,qq-&gt;addr);<br />printf("\n\nname\tnumber age addr\n");<br />qq=boyb;<br />for(i=0;i&lt;2;i++,qq++)<br />printf("%s\t%5d %7d %s\n",qq-&gt;name,qq-&gt;num, qq-&gt;age,<br />qq-&gt;addr);<br />fclose(fp);<br />} <br /><br />　　与例10.6相比，本程序中fscanf和fprintf函数每次只能读写一个结构数组元素，因此采用了循环语句来读写全部数组元素。 还要注意指针变量pp,qq由于循环改变了它们的值，因此在程序的25和32行分别对它们重新赋予了数组的首地址。<br /><br />　　文件的随机读写<br /><br />　　前面介绍的对文件的读写方式都是顺序读写， 即读写文件只能从头开始，顺序读写各个数据。 但在实际问题中常要求只读写文件中某一指定的部分。 为了解决这个问题可移动文件内部的位置指针到需要读写的位置，再进行读写，这种读写称为随机读写。 实现随机读写的关键是要按要求移动位置指针，这称为文件的定位。文件定位移动文件内部位置指针的函数主要有两个， 即 rewind 函数和fseek函数。<br /><br />　　rewind函数前面已多次使用过，其调用形式为： rewind(文件指针)； 它的功能是把文件内部的位置指针移到文件首。 下面主要介绍<br />fseek函数。<br /><br />　　fseek函数用来移动文件内部位置指针，其调用形式为： fseek(文件指针，位移量，起始点)； 其中：“文件指针”指向被移动的文件。 “位移量”表示移动的字节数，要求位移量是long型数据，以便在文件长度大于64KB 时不会出错。当用常量表示位移量时，要求加后缀“L”。“起始点”表示从何处开始计算位移量，规定的起始点有三种：文件首，当前位置和文件尾。<br /><br />　　其表示方法如表10.2。 <br /><br />起始点 　　　表示符号 　　　数字表示<br />──────────────────────────<br />文件首 　　　SEEK—SET　　　　0<br />当前位置 　　SEEK—CUR　　　　1<br />文件末尾 　　SEEK—END 　　　 2<br /><br />　　例如：<br /><br />　　fseek(fp,100L,0);其意义是把位置指针移到离文件首100个字节处。还要说明的是fseek函数一般用于二进制文件。在文本文件中由于要进行转换，故往往计算的位置会出现错误。文件的随机读写在移动位置指针之后， 即可用前面介绍的任一种读写函数进行读写。由于一般是读写一个数据据块，因此常用fread和fwrite函数。下面用例题来说明文件的随机读写。<br /><br />　　[例10.8]在学生文件stu list中读出第二个学生的数据。<br /><br />#include&lt;stdio.h&gt;<br />struct stu<br />{<br />　char name[10];<br />　int num;<br />　int age;<br />　char addr[15];<br />}boy,*qq;<br />main()<br />{<br />　FILE *fp;<br />　char ch;<br />　int i=1;<br />　qq=&amp;boy;<br />　if((fp=fopen("stu_list","rb"))==NULL)<br />　{<br />　　printf("Cannot open file strike any key exit!");<br />　　getch();<br />　　exit(1);<br />　}<br />　rewind(fp);<br />　fseek(fp,i*sizeof(struct stu),0);<br />　fread(qq,sizeof(struct stu),1,fp);<br />　printf("\n\nname\tnumber age addr\n");<br />　printf("%s\t%5d %7d %s\n",qq-&gt;name,qq-&gt;num,qq-&gt;age,<br />　qq-&gt;addr);<br />} <br /><br />　　文件stu_list已由例10.6的程序建立，本程序用随机读出的方法读出第二个学生的数据。程序中定义boy为stu类型变量，qq为指向boy的指针。以读二进制文件方式打开文件，程序第22行移动文件位置指针。其中的i值为1，表示从文件头开始，移动一个stu类型的长度， 然后再读出的数据即为第二个学生的数据。<br /><br />　　文件检测函数<br /><br />　　C语言中常用的文件检测函数有以下几个。<br /><br />　　一、文件结束检测函数feof函数调用格式： feof(文件指针)； <br /><br />　　功能：判断文件是否处于文件结束位置，如文件结束，则返回值为1，否则为0。<br /><br />　　二、读写文件出错检测函数ferror函数调用格式： ferror(文件指针)； <br /><br />　　功能：检查文件在用各种输入输出函数进行读写时是否出错。 如ferror返回值为0表示未出错，否则表示有错。<br /><br />　　三、文件出错标志和文件结束标志置0函数clearerr函数调用格式： clearerr(文件指针); <br /><br />　　功能：本函数用于清除出错标志和文件结束标志，使它们为0值。<br /><br />　　C库文件<br /><br />　　C系统提供了丰富的系统文件，称为库文件，C的库文件分为两类，一类是扩展名为".h"的文件，称为头文件， 在前面的包含命令中我们已多次使用过。在".h"文件中包含了常量定义、 类型定义、宏定义、函数原型以及各种编译选择设置等信息。另一类是函数库，包括了各种函数的目标代码，供用户在程序中调用。 通常在程序中调用一个库函数时，要在调用之前包含该函数原型所在的".h" 文件。<br /><br />　　在附录中给出了全部库函数。<br /><br />ALLOC.H 　　　说明内存管理函数(分配、释放等)。<br />ASSERT.H 　 　定义 assert调试宏。<br />BIOS.H 　　 　说明调用IBM—PC ROM BIOS子程序的各个函数。<br />CONIO.H 　　　说明调用DOS控制台I/O子程序的各个函数。<br />CTYPE.H 　　　包含有关字符分类及转换的名类信息(如 isalpha和toascii等)。<br />DIR.H 　　　　包含有关目录和路径的结构、宏定义和函数。<br />DOS.H 　　　　定义和说明MSDOS和8086调用的一些常量和函数。<br />ERRON.H 　　　定义错误代码的助记符。<br />FCNTL.H 　　　定义在与open库子程序连接时的符号常量。<br />FLOAT.H 　　　包含有关浮点运算的一些参数和函数。<br />GRAPHICS.H 　 说明有关图形功能的各个函数，图形错误代码的常量定义，正对不同驱动程序的各种颜色值，及函数用到的一些特殊结构。<br />IO.H 　　　　 包含低级I/O子程序的结构和说明。<br />LIMIT.H 　　　包含各环境参数、编译时间限制、数的范围等信息。<br />MATH.H 　　　 说明数学运算函数，还定了 HUGE VAL 宏， 说明了matherr和matherr子程序用到的特殊结构。<br />MEM.H 　　　　说明一些内存操作函数(其中大多数也在STRING.H 中说明)。<br />PROCESS.H 　　说明进程管理的各个函数，spawn…和EXEC …函数的结构说明。<br />SETJMP.H 　　 定义longjmp和setjmp函数用到的jmp buf类型， 说明这两个函数。<br />SHARE.H 　　　定义文件共享函数的参数。<br />SIGNAL.H 　　 定义SIG[ZZ(Z] [ZZ)]IGN和SIG[ZZ(Z] [ZZ)]DFL常量，说明rajse和signal两个函数。<br />STDARG.H 　　 定义读函数参数表的宏。(如vprintf,vscarf函数)。<br />STDDEF.H 　　 定义一些公共数据类型和宏。<br />STDIO.H 　　　定义Kernighan和Ritchie在Unix System V 中定义的标准和扩展的类型和宏。还定义标准I/O 预定义流：stdin,stdout和stderr，说明 I/O流子程序。<br />STDLIB.H 　　 说明一些常用的子程序：转换子程序、搜索/ 排序子程序等。<br />STRING.H 　　 说明一些串操作和内存操作函数。<br />SYS\STAT.H 　 定义在打开和创建文件时用到的一些符号常量。<br />SYS\TYPES.H 　说明ftime函数和timeb结构。<br />SYS\TIME.H 　 定义时间的类型time[ZZ(Z] [ZZ)]t。<br />TIME.H 　　　 定义时间转换子程序asctime、localtime和gmtime的结构，ctime、 difftime、 gmtime、 localtime和stime用到的类型，并提供这些函数的原型。<br />VALUE.H 　　　定义一些重要常量， 包括依赖于机器硬件的和为与Unix System V相兼容而说明的一些常量，包括浮点和双精度值的范围。<br /><img src ="http://www.cppblog.com/jht/aggbug/7933.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jht/" target="_blank">季浩</a> 2006-05-31 13:33 <a href="http://www.cppblog.com/jht/archive/2006/05/31/7933.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UNIX系统编程常用库函数说明[转载]</title><link>http://www.cppblog.com/jht/archive/2006/05/31/7928.html</link><dc:creator>季浩</dc:creator><author>季浩</author><pubDate>Wed, 31 May 2006 05:17:00 GMT</pubDate><guid>http://www.cppblog.com/jht/archive/2006/05/31/7928.html</guid><wfw:comment>http://www.cppblog.com/jht/comments/7928.html</wfw:comment><comments>http://www.cppblog.com/jht/archive/2006/05/31/7928.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jht/comments/commentRss/7928.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jht/services/trackbacks/7928.html</trackback:ping><description><![CDATA[
		<p class="post-info">
				<a title="Permanent Link: UNIX系统编程常用库函数说明" href="http://linux.21ds.net/2001/08/23/88b9fae7a67dd22b5a4e632b673792f1/" rel="bookmark">
				</a> </p>
		<div class="post-content">
				<p>UNIX系统为程序员提供了许多子程序,这些子程序可存取各种安全属性.有 <br />些是信息子程序,返回文件属性,实际的和有效的UID,GID等信息.有些子程序可 <br />改变文件属性.UID,GID等有些处理口令文件和小组文件,还有些完成加密和解密. <br />本文主要讨论有关系统子程序,标准C库子程序的安全,如何写安全的C程序 <br />并从root的角度介绍程序设计(仅能被root调用的子程序). <br />1.系统子程序 <br />(1)I/O子程序 <br />*creat():建立一个新文件或重写一个暂存文件. <br />需要两个参数:文件名和存取许可值(8进制方式).如: <br />creat(”/usr/pat/read_write”,0666) /* 建立存取许可方式为0666的文件 */ <br />调用此子程序的进程必须要有建立的文件的所在目录的写和执行许可,置 <br />给creat()的许可方式变量将被umask()设置的文件建立屏蔽值所修改,新 <br />文件的所有者和小组由有效的UID和GID决定. <br />返回值为新建文件的文件描述符. <br />*fstat():见后面的stat(). <br />*open():在C程序内部打开文件. <br />需要两个参数:文件路径名和打开方式(I,O,I&amp;O). <br />如果调用此子程序的进程没有对于要打开的文件的正确存取许可(包括文 <br />件路径上所有目录分量的搜索许可),将会引起执行失败. <br />如果此子程序被调用去打开不存在的文件,除非设置了O_CREAT标志,调用 <br />将不成功.此时,新文件的存取许可作为第三个参数(可被用户的umask修 <br />改). <br />当文件被进程打开后再改变该文件或该文件所在目录的存取许可,不影响 <br />对该文件的I/O操作. <br />*read():从已由open()打开并用作输入的文件中读信息. <br />它并不关心该文件的存取许可.一旦文件作为输入打开,即可从该文件中读 <br />取信息. <br />*write():输出信息到已由open()打开并用作输出的文件中.同read()一样 <br />它也不关心该文件的存取许可. <br />(2)进程控制 <br />*exec()族:包括execl(),execv(),execle(),execve(),execlp()和execvp() <br />可将一可执行模快拷贝到调用进程占有的存贮空间.正被调用进 <br />程执行的程序将不复存在,新程序取代其位置. <br />这是UNIX系统中一个程序被执行的唯一方式:用将执行的程序复盖原有的 <br />程序. <br />安全注意事项: <br />. 实际的和有效的UID和GID传递给由exec()调入的不具有SUID和SGID许 <br />可的程序. <br />. 如果由exec()调入的程序有SUID和SGID许可,则有效的UID和GID将设 <br />置给该程序的所有者或小组. <br />. 文件建立屏蔽值将传递给新程序. <br />. 除设了对exec()关闭标志的文件外,所有打开的文件都传递给新程序. <br />用fcntl()子程序可设置对exec()的关闭标志. <br />*fork():用来建立新进程.其建立的子进程是与调用fork()的进程(父进程) <br />完全相同的拷贝(除了进程号外) <br />安全注意事项: <br />. 子进程将继承父进程的实际和有效的UID和GID. <br />. 子进程继承文件方式建立屏蔽值. <br />. 所有打开的文件传给子进程. <br />*signal():允许进程处理可能发生的意外事件和中断. <br />需要两个参数:信号编号和信号发生时要调用的子程序. <br />信号编号定义在signal.h中. <br />信号发生时要调用的子程序可由用户编写,也可用系统给的值,如:SIG_IGN <br />则信号将被忽略,SIG_DFL则信号将按系统的缺省方式处理. <br />如许多与安全有关的程序禁止终端发中断信息(BREAK和DELETE),以免自己 <br />被用户终端终止运行. <br />有些信号使UNIX系统的产生进程的核心转储(进程接收到信号时所占内存 <br />的内容,有时含有重要信息),此系统子程序可用于禁止核心转储. <br />(3)文件属性 <br />*access():检测指定文件的存取能力是否符合指定的存取类型. <br />需要两个参数:文件名和要检测的存取类型(整数). <br />存取类型定义如下: <br />0: 检查文件是否存在 <br />1: 检查是否可执行(搜索) <br />2: 检查是否可写 <br />3: 检查是否可写和执行 <br />4: 检查是否可读 <br />5: 检查是否可读和执行 <br />6: 检查是否可读可写可执行 <br />这些数字的意义和chmod命令中规定许可方式的数字意义相同. <br />此子程序使用实际的UID和GID检测文件的存取能力(一般有效的UID和GID <br />用于检查文件存取能力). <br />返回值: 0:许可 -1:不许可. <br />*chmod():将指定文件或目录的存取许可方式改成新的许可方式. <br />需要两个参数:文件名和新的存取许可方式. <br />*chown():同时改变指定文件的所有者和小组的UID和GID.(与chown命令不 <br />同). <br />由于此子程序同时改变文件的所有者和小组,故必须取消所操作文件的SUID <br />和SGID许可,以防止用户建立SUID和SGID程序,然后运行chown()去获得别 <br />人的权限. <br />*stat():返回文件的状态(属性). <br />需要两个参数:文件路径名和一个结构指针,指向状态信息的存放 <br />的位置. <br />结构定义如下: <br />st_mode: 文件类型和存取许可方式 <br />st_ino: I节点号 <br />st_dev: 文件所在设备的ID <br />st_rdev: 特别文件的ID <br />st_nlink: 文件链接数 <br />st_uid: 文件所有者的UID <br />st_gid: 文件小组的GID <br />st_size: 按字节计数的文件大小 <br />st_atime: 最后存取时间(读) <br />st_mtime: 最后修改时间(写)和最后状态的改变 <br />st_ctime: 最后的状态修改时间 <br />返回值: 0:成功 1:失败 <br />*umask():将调用进程及其子进程的文件建立屏蔽值设置为指定的存取许可. <br />需要一个参数: 新的文件建立屏值. <br />(4)UID和GID的处理 <br />*getuid():返回进程的实际UID. <br />*getgid():返回进程的实际GID. <br />以上两个子程序可用于确定是谁在运行进程. <br />*geteuid():返回进程的有效UID. <br />*getegid():返回进程的有效GID. <br />以上两个子程序可在一个程序不得不确定它是否在运行某用户而不是运行 <br />它的用户的SUID程序时很有用,可调用它们来检查确认本程序的确是以该 <br />用户的SUID许可在运行. <br />*setuid():用于改变有效的UID. <br />对于一般用户,此子程序仅对要在有效和实际的UID之间变换的SUID程序才 <br />有用(从原有效UID变换为实际UID),以保护进程不受到安全危害.实际上该 <br />进程不再是SUID方式运行. <br />*setgid():用于改变有效的GID. <br />2.标准C库 <br />(1)标准I/O <br />*fopen():打开一个文件供读或写,安全方面的考虑同open()一样. <br />*fread(),getc(),fgetc(),gets(),scanf()和fscanf():从已由fopen()打 <br />开供读的文件中读取信息.它们并不关心文件的存取许可.这一点 <br />同read(). <br />*fwrite(),put(),fputc(),puts,fputs(),printf(),fprintf():写信息到 <br />已由fopen()打开供写的文件中.它们也不关心文件的存取许可. <br />同write(). <br />*getpass():从终端上读至多8个字符长的口令,不回显用户输入的字符. <br />需要一个参数: 提示信息. <br />该子程序将提示信息显示在终端上,禁止字符回显功能,从/dev/tty读取口 <br />令,然后再恢复字符回显功能,返回刚敲入的口令的指针. <br />*popen():将在(5)运行shell中介绍. <br />(2)/etc/passwd处理 <br />有一组子程序可对/etc/passwd文件进行方便的存取,可对文件读取到入口 <br />项或写新的入口项或更新等等. <br />*getpwuid():从/etc/passwd文件中获取指定的UID的入口项. <br />*getpwnam():对于指定的登录名,在/etc/passwd文件检索入口项. <br />以上两个子程序返回一指向passwd结构的指针,该结构定义在 <br />/usr/include/pwd.h中,定义如下: <br />struct passwd { <br />char * pw_name; /* 登录名 */ <br />char * pw_passwd; /* 加密后的口令 */ <br />uid_t pw_uid; /* UID */ <br />gid_t pw_gid; /* GID */ <br />char * pw_age; /* 代理信息 */ <br />char * pw_comment; /* 注释 */ <br />char * pw_gecos; <br />char * pw_dir; /* 主目录 */ <br />char * pw_shell; /* 使用的shell */ <br />}; <br />*getpwent(),setpwent(),endpwent():对口令文件作后续处理. <br />首次调用getpwent(),打开/etc/passwd并返回指向文件中第一个入口项的 <br />指针,保持调用之间文件的打开状态. <br />再调用getpwent()可顺序地返回口令文件中的各入口项. <br />调用setpwent()把口令文件的指针重新置为文件的开始处. <br />使用完口令文件后调用endpwent()关闭口令文件. <br />*putpwent():修改或增加/etc/passwd文件中的入口项. <br />此子程序将入口项写到一个指定的文件中,一般是一个临时文件,直接写口 <br />令文件是很危险的.最好在执行前做文件封锁,使两个程序不能同时写一个 <br />文件.算法如下: <br />. 建立一个独立的临时文件,即/etc/passnnn,nnn是PID号. <br />. 建立新产生的临时文件和标准临时文件/etc/ptmp的链,若建链失败, <br />则为有人正在使用/etc/ptmp,等待直到/etc/ptmp可用为止或退出. <br />. 将/etc/passwd拷贝到/etc/ptmp,可对此文件做任何修改. <br />. 将/etc/passwd移到备份文件/etc/opasswd. <br />. 建立/etc/ptmp和/etc/passwd的链. <br />. 断开/etc/passnnn与/etc/ptmp的链. <br />注意:临时文件应建立在/etc目录,才能保证文件处于同一文件系统中,建 <br />链才能成功,且临时文件不会不安全.此外,若新文件已存在,即便建 <br />链的是root用户,也将失败,从而保证了一旦临时文件成功地建链后 <br />没有人能再插进来干扰.当然,使用临时文件的程序应确保清除所有 <br />临时文件,正确地捕捉信号. <br />(3)/etc/group的处理 <br />有一组类似于前面的子程序处理/etc/group的信息,使用时必须用include <br />语句将/usr/include/grp.h文件加入到自己的程序中.该文件定义了group <br />结构,将由getgrnam(),getgrgid(),getgrent()返回group结构指针. <br />*getgrnam():在/etc/group文件中搜索指定的小组名,然后返回指向小组入 <br />口项的指针. <br />*getgrgid():类似于前一子程序,不同的是搜索指定的GID. <br />*getgrent():返回group文件中的下一个入口项. <br />*setgrent():将group文件的文件指针恢复到文件的起点. <br />*endgrent():用于完成工作后,关闭group文件. <br />*getuid():返回调用进程的实际UID. <br />*getpruid():以getuid()返回的实际UID为参数,确定与实际UID相应的登录 <br />名,或指定一UID为参数. <br />*getlogin():返回在终端上登录的用户的指针. <br />系统依次检查STDIN,STDOUT,STDERR是否与终端相联,与终端相联的标准输 <br />入用于确定终端名,终端名用于查找列于/etc/utmp文件中的用户,该文件 <br />由login维护,由who程序用来确认用户. <br />*cuserid():首先调用getlogin(),若getlogin()返回NULL指针,再调用 <br />getpwuid(getuid()). <br />*以下为命令: <br />*logname:列出登录进终端的用户名. <br />*who am i:显示出运行这条命令的用户的登录名. <br />*id:显示实际的UID和GID(若有效的UID和GID和实际的不同时也显示有效的 <br />UID和GID)和相应的登录名. <br />(4)加密子程序 <br />1977年1月,NBS宣布一个用于美国联邦政府ADP系统的网络的标准加密法:数 <br />据加密标准即DES用于非机密应用方面.DES一次处理64BITS的块,56位的加 <br />密键. <br />*setkey(),encrypt():提供用户对DES的存取. <br />此两子程序都取64BITS长的字符数组,数组中的每个元素代表一个位,为0 <br />或1.setkey()设置将按DES处理的加密键,忽略每第8位构成一个56位的加 <br />密键.encrypt()然后加密或解密给定的64BITS长的一块,加密或解密取决 <br />于该子程序的第二个变元,0:加密 1:解密. <br />*crypt():是UNIX系统中的口令加密程序,也被/usr/lib/makekey命令调用. <br />crypt()子程序与crypt命令无关,它与/usr/lib/makekey一样取8个字符长 <br />的关键词,2个salt字符.关键词送给setkey(),salt字符用于混合encrypt() <br />中的DES算法,最终调用encrypt()重复25次加密一个相同的字符串. <br />返回加密后的字符串指针. <br />(5)运行shell <br />*system():运行/bin/sh执行其参数指定的命令,当指定命令完成时返回. <br />*popen():类似于system(),不同的是命令运行时,其标准输入或输出联到由 <br />popen()返回的文件指针. <br />二者都调用fork(),exec(),popen()还调用pipe(),完成各自的工作,因而 <br />fork()和exec()的安全方面的考虑开始起作用. <br />3.写安全的C程序 <br />一般有两方面的安全问题,在写程序时必须考虑: <br />(1)确保自己建立的任何临时文件不含有机密数据,如果有机密数据,设置 <br />临时文件仅对自己可读/写.确保建立临时文件的目录仅对自己可写. <br />(2)确保自己要运行的任何命令(通过system(),popen(),execlp(), <br />execvp()运行的命令)的确是自己要运行的命令,而不是其它什么命 <br />令,尤其是自己的程序为SUID或SGID许可时要小心. <br />第一方面比较简单,在程序开始前调用umask(077).若要使文件对其他人可 <br />读,可再调chmod(),也可用下述语名建立一个”不可见”的临时文件. <br />creat(”/tmp/xxx”,0); <br />file=open(”/tmp/xxx”,O_RDWR); <br />unlink(”/tmp/xxx”); <br />文件/tmp/xxx建立后,打开,然后断开链,但是分配给该文件的存储器并未删 <br />除,直到最终指向该文件的文件通道被关闭时才被删除.打开该文件的进程 <br />和它的任何子进程都可存取这个临时文件,而其它进程不能存取该文件,因 <br />为它在/tmp中的目录项已被unlink()删除. <br />第二方面比较复杂而微妙,由于system(),popen(),execlp(),execvp()执行 <br />时,若不给出执行命令的全路径,就能”骗”用户的程序去执行不同的命令.因 <br />为系统子程序是根据PATH变量确定哪种顺序搜索哪些目录,以寻找指定的命 <br />令,这称为SUID陷井.最安全的办法是在调用system()前将有效UID改变成实 <br />际UID,另一种比较好的方法是以全路径名命令作为参数.execl(),execv(), <br />execle(),execve()都要求全路径名作为参数.有关SUID陷井的另一方式是 <br />在程序中设置PATH,由于system()和popen()都启动shell,故可使用shell句 <br />法.如: <br />system(”PATH=/bin:/usr/bin cd”); <br />这样允许用户运行系统命令而不必知道要执行的命令在哪个目录中,但这种 <br />方法不能用于execlp(),execvp()中,因为它们不能启动shell执行调用序列 <br />传递的命令字符串. <br />关于shell解释传递给system()和popen()的命令行的方式,有两个其它的问 <br />题: <br />*shell使用IFS shell变量中的字符,将命令行分解成单词(通常这个 <br />shell变量中是空格,tab,换行),如IFS中是/,字符串/bin/ed被解释成单词 <br />bin,接下来是单词ed,从而引起命令行的曲解. <br />再强调一次:在通过自己的程序运行另一个程序前,应将有效UID改为实际的 <br />UID,等另一个程序退出后,再将有效UID改回原来的有效UID. <br />SUID/SGID程序指导准则 <br />(1)不要写SUID/SGID程序,大多数时候无此必要. <br />(2)设置SGID许可,不要设置SUID许可.应独自建立一个新的小组. <br />(3)不要用exec()执行任何程序.记住exec()也被system()和popen()调用. <br />. 若要调用exec()(或system(),popen()),应事先用setgid(getgid()) <br />将有效GID置加实际GID. <br />. 若不能用setgid(),则调用system()或popen()时,应设置IFS: <br />popen(”IFS=\t\n;export IFS;/bin/ls”,”r”); <br />. 使用要执行的命令的全路径名. <br />. 若不能使用全路径名,则应在命令前先设置PATH: <br />popen(”IFS=\t\n;export IFS;PATH=/bin:/usr/bin;/bin/ls”,”r”); <br />. 不要将用户规定的参数传给system()或popen();若无法避免则应检查 <br />变元字符串中是否有特殊的shell字符. <br />. 若用户有个大程序,调用exec()执行许多其它程序,这种情况下不要将 <br />大程序设置为SGID许可.可以写一个(或多个)更小,更简单的SGID程序 <br />执行必须具有SGID许可的任务,然后由大程序执行这些小SGID程序. <br />(4)若用户必须使用SUID而不是SGID,以相同的顺序记住(2),(3)项内容,并 <br />相应调整.不要设置root的SUID许可.选一个其它户头. <br />(5)若用户想给予其他人执行自己的shell程序的许可,但又不想让他们能 <br />读该程序,可将程序设置为仅执行许可,并只能通过自己的shell程序来 <br />运行. <br />编译,安装SUID/SGID程序时应按下面的方法 <br />(1)确保所有的SUID(SGID)程序是对于小组和其他用户都是不可写的,存取 <br />权限的限制低于4755(2755)将带来麻烦.只能更严格.4111(2111)将使 <br />其他人无法寻找程序中的安全漏洞. <br />(2)警惕外来的编码和make/install方法 <br />. 某些make/install方法不加选择地建立SUID/SGID程序. <br />. 检查违背上述指导原则的SUID/SGID许可的编码. <br />. 检查makefile文件中可能建立SUID/SGID文件的命令. <br />4.root程序的设计 <br />有若干个子程序可以从有效UID为0的进程中调用.许多前面提到的子程序, <br />当从root进程中调用时,将完成和原来不同的处理.主要是忽略了许可权限的检 <br />查. <br />由root用户运行的程序当然是root进程(SUID除外),因有效UID用于确定文 <br />件的存取权限,所以从具有root的程序中,调用fork()产生的进程,也是root进程. <br />(1)setuid():从root进程调用setuid()时,其处理有所不同,setuid()将把有 <br />效的和实际的UID都置为指定的值.这个值可以是任何整型数.而对非root <br />进程则仅能以实际UID或本进程原来有效的UID为变量值调用setuid(). <br />(2)setgid():在系统进程中调用setgid()时,与setuid()类似,将实际和有效 <br />的GID都改变成其参数指定的值. <br />* 调用以上两个子程序时,应当注意下面几点: <br />. 调用一次setuid()(setgid())将同时设置有效和实际UID(GID),独立分 <br />别设置有效或实际UID(GID)固然很好,但无法做到这点. <br />. setuid()(setgid())可将有效和实际UID(GID)设置成任何整型数,其数 <br />值不必一定与/etc/passwd(/etc/group)中用户(小组)相关联. <br />. 一旦程序以一个用户的UID了setuid(),该程序就不再做为root运行,也 <br />不可能再获root特权. <br />(3)chown():当root进程运行chown()时,chown()将不删除文件的SUID和/或 <br />SGID许可,但当非root进程运行chown()时,chown()将取消文件的SUID和/ <br />或SGID许可. <br />(4)chroot():改变进程对根目录的概念,调用chroot()后,进程就不能把当前 <br />工作目录改变到新的根目录以上的任一目录,所有以/开始的路径搜索,都 <br />从新的根目录开始. <br />(5)mknod():用于建立一个文件,类似于creat(),差别是mknod()不返回所打开 <br />文件的文件描述符,并且能建立任何类型的文件(普通文件,特殊文件,目录 <br />文件).若从非root进程调用mknod()将执行失败,只有建立FIFO特别文件 <br />(有名管道文件)时例外,其它任何情况下,必须从root进程调用mknod().由 <br />于creat()仅能建立普通文件,mknod()是建立目录文件的唯一途径,因而仅 </p>
				<p>有root能建立目录,这就是为什么mkdir命令具有SUID许可并属root所有. <br />一般不从程序中调用mknod().通常用/etc/mknod命令建立特别设备文件而 <br />这些文件一般不能在使用着时建立和删除,mkdir命令用于建立目录.当用 <br />mknod()建立特别文件时,应当注意确从所建的特别文件不允许存取内存, <br />磁盘,终端和其它设备. <br />(6)unlink():用于删除文件.参数是要删除文件的路径名指针.当指定了目录 <br />时,必须从root进程调用unlink(),这是必须从root进程调用unlink()的唯 <br />一情况,这就是为什么rmdir命令具有root的SGID许可的原因. <br />(7)mount(),umount():由root进程调用,分别用于安装和拆卸文件系统.这两 <br />个子程序也被mount和umount命令调用,其参数基本和命令的参数相同.调 <br />用mount(),需要给出一个特别文件和一个目录的指针,特别文件上的文件 <br />系统就将安装在该目录下,调用时还要给出一个标识选项,指定被安装的文 <br />件系统要被读/写(0)还是仅读(1).umount()的参数是要一个要拆卸的特别 <br />文件的指针. <br />本文由isbase成员编译或原创，如要转载请保持文章的完整性 </p>
		</div>
<img src ="http://www.cppblog.com/jht/aggbug/7928.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jht/" target="_blank">季浩</a> 2006-05-31 13:17 <a href="http://www.cppblog.com/jht/archive/2006/05/31/7928.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>前天一道我不能回答好的面试题:内存泄露你怎么解决？希望大家不吝赐教</title><link>http://www.cppblog.com/jht/archive/2006/05/13/7048.html</link><dc:creator>季浩</dc:creator><author>季浩</author><pubDate>Fri, 12 May 2006 18:42:00 GMT</pubDate><guid>http://www.cppblog.com/jht/archive/2006/05/13/7048.html</guid><wfw:comment>http://www.cppblog.com/jht/comments/7048.html</wfw:comment><comments>http://www.cppblog.com/jht/archive/2006/05/13/7048.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.cppblog.com/jht/comments/commentRss/7048.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jht/services/trackbacks/7048.html</trackback:ping><description><![CDATA[        题目描述很简单：内存泄露了，现象是看到该程序的内存占用率不断增长，作为一个程序员你怎么解决这个问题？<br /><br />        我答的不好，回来之后又好好的想了想，其实回答这个问题应该从不同的方面来考虑<br /><br />        首先分析内存泄露容易发生的情况，《OOP启示录》对这些情况都讲得挺详细的，在类的构造函数与析构函数中没有匹配地调用 new/delete！没有正确地清除嵌套的对象指针！在释放对象数组时，没有使用delete []；指向由指向对象的指针构成的数组不等同于与对象数组。缺少拷贝构造函数，编译器缺省添加的拷贝构造函数不足，缺省的拷贝构造函数采用位拷贝！......用我自己的想法描述就是，每次自己分配一块内存区域的时候，都要想到用完之后要将该内存区释放掉！当然特殊的情形这句话不适用。<br />       既然知道了内存泄露事件的多发地带，我们可以多在这些地方设置检察机制，相对来说就有一点针对性了！面试官说这样是一种解决办法，可能10000个函数，我们可以把错误范围缩小到200个，然后你还有什么办法继续解决这个问题？<br /><br />      我基本上是把我暂时能想到的都说了，什么设置断点调试啊，用IDE工具看地址变化。。。不过好像都不能达到面试官满意度。。。<br />      他说没有这样的IDE工具给你用，接着你怎么解决？<br />      唉。。。受打击了，事实如此，我对这个不够理解。。。<br /><br />     之后上网想找找内存泄露相关的资料，搜出来的文章大部分都是林锐高质量C++编程里关于内存的那篇，大感失望，怎么就没有其他更好更深入的文章了呢？？？<br /><br />     大家讨论讨论，我相信这个问题挺具有代表性的，大家讨论出个结果，都弄懂了岂不是更好？<br /><br /><br /><img src ="http://www.cppblog.com/jht/aggbug/7048.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jht/" target="_blank">季浩</a> 2006-05-13 02:42 <a href="http://www.cppblog.com/jht/archive/2006/05/13/7048.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]C++中类的多态与虚函数的使用</title><link>http://www.cppblog.com/jht/archive/2006/05/05/6647.html</link><dc:creator>季浩</dc:creator><author>季浩</author><pubDate>Fri, 05 May 2006 09:37:00 GMT</pubDate><guid>http://www.cppblog.com/jht/archive/2006/05/05/6647.html</guid><wfw:comment>http://www.cppblog.com/jht/comments/6647.html</wfw:comment><comments>http://www.cppblog.com/jht/archive/2006/05/05/6647.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jht/comments/commentRss/6647.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jht/services/trackbacks/6647.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: C++中类的多态与虚函数的使用																																																		出处：PConline																																																																[ 2005-03-16 10:17:37 ] 								作者：管宁 ...&nbsp;&nbsp;<a href='http://www.cppblog.com/jht/archive/2006/05/05/6647.html'>阅读全文</a><img src ="http://www.cppblog.com/jht/aggbug/6647.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jht/" target="_blank">季浩</a> 2006-05-05 17:37 <a href="http://www.cppblog.com/jht/archive/2006/05/05/6647.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]C/C+语言struct深层探索</title><link>http://www.cppblog.com/jht/archive/2006/05/05/6646.html</link><dc:creator>季浩</dc:creator><author>季浩</author><pubDate>Fri, 05 May 2006 09:26:00 GMT</pubDate><guid>http://www.cppblog.com/jht/archive/2006/05/05/6646.html</guid><wfw:comment>http://www.cppblog.com/jht/comments/6646.html</wfw:comment><comments>http://www.cppblog.com/jht/archive/2006/05/05/6646.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jht/comments/commentRss/6646.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jht/services/trackbacks/6646.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="6" width="99%" background="http://www.pconline.com.cn/images/point.gif" border="0">
				<tbody>
						<tr>
								<td align="middle" colspan="3">
										<table cellspacing="0" cellpadding="0" width="100%" border="0">
												<tbody>
														<tr>
																<td align="middle" width="68%">
																		<font color="#339900" size="3">
																				<b>C/C+语言struct深层探索</b>
																		</font>
																</td>
																<td valign="bottom" align="right" width="17%">出处：PConline</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
						<tr>
								<td width="145">[ 2005-08-11 10:30:50 ] </td>
								<td align="middle">作者：宋宝华 </td>
								<td align="right">责任编辑：xietaoming</td>
						</tr>
				</tbody>
		</table>
		<h4>1. struct的巨大作用</h4>
		<p>　　面对一个人的大型C/C++程序时，只看其对struct的使用情况我们就可以对其编写者的编程经验进行评估。因为一个大型的C/C++程序，势必要涉及一些(甚至大量)进行数据组合的结构体，这些结构体可以将原本意义属于一个整体的数据组合在一起。从某种程度上来说，会不会用struct，怎样用struct是区别一个开发人员是否具备丰富开发经历的标志<br />在网络协议、通信控制、嵌入式系统的C/C++编程中，我们经常要传送的不是简单的字节流（char型数组），而是多种数据组合起来的一个整体，其表现形式是一个结构体。</p>
		<p>　　经验不足的开发人员往往将所有需要传送的内容依顺序保存在char型数组中，通过指针偏移的方法传送网络报文等信息。这样做编程复杂，易出错，而且一旦控制方式及通信协议有所变化，程序就要进行非常细致的修改。</p>
		<p>　　一个有经验的开发者则灵活运用结构体，举一个例子，假设网络或控制协议中需要传送三种报文，其格式分别为packetA、packetB、packetC：</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />
				<span style="COLOR: #0000ff">struct</span>
				<span style="COLOR: #000000"> structA <br /><img id="Codehighlighter1_16_35_Open_Image" onclick="this.style.display='none'; Codehighlighter1_16_35_Open_Text.style.display='none'; Codehighlighter1_16_35_Closed_Image.style.display='inline'; Codehighlighter1_16_35_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_16_35_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_16_35_Closed_Text.style.display='none'; Codehighlighter1_16_35_Open_Image.style.display='inline'; Codehighlighter1_16_35_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
				<span id="Codehighlighter1_16_35_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
						<img src="http://www.cppblog.com/images/dot.gif" />
				</span>
				<span id="Codehighlighter1_16_35_Open_Text">
						<span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /> </span>
						<span style="COLOR: #0000ff">int</span>
						<span style="COLOR: #000000"> a;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /> </span>
						<span style="COLOR: #0000ff">char</span>
						<span style="COLOR: #000000"> b;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
				</span>
				<span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">struct</span>
				<span style="COLOR: #000000"> structB <br /><img id="Codehighlighter1_55_76_Open_Image" onclick="this.style.display='none'; Codehighlighter1_55_76_Open_Text.style.display='none'; Codehighlighter1_55_76_Closed_Image.style.display='inline'; Codehighlighter1_55_76_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_55_76_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_55_76_Closed_Text.style.display='none'; Codehighlighter1_55_76_Open_Image.style.display='inline'; Codehighlighter1_55_76_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
				<span id="Codehighlighter1_55_76_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
						<img src="http://www.cppblog.com/images/dot.gif" />
				</span>
				<span id="Codehighlighter1_55_76_Open_Text">
						<span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /> </span>
						<span style="COLOR: #0000ff">char</span>
						<span style="COLOR: #000000"> a;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /> </span>
						<span style="COLOR: #0000ff">short</span>
						<span style="COLOR: #000000"> b;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
				</span>
				<span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">struct</span>
				<span style="COLOR: #000000"> structC<br /><img id="Codehighlighter1_95_124_Open_Image" onclick="this.style.display='none'; Codehighlighter1_95_124_Open_Text.style.display='none'; Codehighlighter1_95_124_Closed_Image.style.display='inline'; Codehighlighter1_95_124_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_95_124_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_95_124_Closed_Text.style.display='none'; Codehighlighter1_95_124_Open_Image.style.display='inline'; Codehighlighter1_95_124_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
				<span id="Codehighlighter1_95_124_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
						<img src="http://www.cppblog.com/images/dot.gif" />
				</span>
				<span id="Codehighlighter1_95_124_Open_Text">
						<span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /> </span>
						<span style="COLOR: #0000ff">int</span>
						<span style="COLOR: #000000"> a;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /> </span>
						<span style="COLOR: #0000ff">char</span>
						<span style="COLOR: #000000"> b;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /> </span>
						<span style="COLOR: #0000ff">float</span>
						<span style="COLOR: #000000"> c;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
				</span>
		</div>
		<p class="code"> </p>
		<p>　　优秀的程序设计者这样设计传送的报文：</p>
		<p>
		</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />
				<span style="COLOR: #0000ff">struct</span>
				<span style="COLOR: #000000"> CommuPacket<br /><img id="Codehighlighter1_19_170_Open_Image" onclick="this.style.display='none'; Codehighlighter1_19_170_Open_Text.style.display='none'; Codehighlighter1_19_170_Closed_Image.style.display='inline'; Codehighlighter1_19_170_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_19_170_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_19_170_Closed_Text.style.display='none'; Codehighlighter1_19_170_Open_Image.style.display='inline'; Codehighlighter1_19_170_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
				<span id="Codehighlighter1_19_170_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
						<img src="http://www.cppblog.com/images/dot.gif" />
				</span>
				<span id="Codehighlighter1_19_170_Open_Text">
						<span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /> </span>
						<span style="COLOR: #0000ff">int</span>
						<span style="COLOR: #000000"> iPacketType;　　</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">报文类型标志</span>
						<span style="COLOR: #008000">
								<br />
								<img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />
						</span>
						<span style="COLOR: #000000"> union　　　　　　</span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">每次传送的是三种报文中的一种，使用union</span>
						<span style="COLOR: #008000">
								<br />
								<img id="Codehighlighter1_87_168_Open_Image" onclick="this.style.display='none'; Codehighlighter1_87_168_Open_Text.style.display='none'; Codehighlighter1_87_168_Closed_Image.style.display='inline'; Codehighlighter1_87_168_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" />
								<img id="Codehighlighter1_87_168_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_87_168_Closed_Text.style.display='none'; Codehighlighter1_87_168_Open_Image.style.display='inline'; Codehighlighter1_87_168_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />
						</span>
						<span style="COLOR: #000000"> </span>
						<span id="Codehighlighter1_87_168_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
								<img src="http://www.cppblog.com/images/dot.gif" />
						</span>
						<span id="Codehighlighter1_87_168_Open_Text">
								<span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />  </span>
								<span style="COLOR: #0000ff">struct</span>
								<span style="COLOR: #000000"> structA packetA;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />  </span>
								<span style="COLOR: #0000ff">struct</span>
								<span style="COLOR: #000000"> structB packetB;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />  </span>
								<span style="COLOR: #0000ff">struct</span>
								<span style="COLOR: #000000"> structC packetC;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" /> }</span>
						</span>
						<span style="COLOR: #000000">
								<br />
								<img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
				</span>
				<span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span>
		</div>
		<p>　　在进行报文传送时，直接传送struct CommuPacket一个整体。</p>
		<p>　　假设发送函数的原形如下：</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />
				<span style="COLOR: #008000">//</span>
				<span style="COLOR: #008000"> pSendData：发送字节流的首地址，iLen：要发送的长度</span>
				<span style="COLOR: #008000">
						<br />
						<img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />
				</span>
				<span style="COLOR: #000000">Send(</span>
				<span style="COLOR: #0000ff">char</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000"> pSendData, unsigned </span>
				<span style="COLOR: #0000ff">int</span>
				<span style="COLOR: #000000">  iLen);<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />发送方可以直接进行如下调用发送struct CommuPacket的一个实例sendCommuPacket：<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />Send( (</span>
				<span style="COLOR: #0000ff">char</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000">)</span>
				<span style="COLOR: #000000">&amp;</span>
				<span style="COLOR: #000000">sendCommuPacket , </span>
				<span style="COLOR: #0000ff">sizeof</span>
				<span style="COLOR: #000000">(CommuPacket) );<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />假设接收函数的原形如下：<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #008000">//</span>
				<span style="COLOR: #008000"> pRecvData：发送字节流的首地址，iLen：要接收的长度<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #008000">//</span>
				<span style="COLOR: #008000">返回值：实际接收到的字节数</span>
				<span style="COLOR: #008000">
						<br />
						<img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />
				</span>
				<span style="COLOR: #000000">unsigned </span>
				<span style="COLOR: #0000ff">int</span>
				<span style="COLOR: #000000"> Recv(</span>
				<span style="COLOR: #0000ff">char</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000"> pRecvData, unsigned </span>
				<span style="COLOR: #0000ff">int</span>
				<span style="COLOR: #000000">  iLen)；</span>
		</div>
		<p class="code">　　接收方可以直接进行如下调用将接收到的数据保存在struct CommuPacket的一个实例recvCommuPacket中：</p>
		<p>
		</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />
				<span style="COLOR: #000000">Recv( (</span>
				<span style="COLOR: #0000ff">char</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000">)</span>
				<span style="COLOR: #000000">&amp;</span>
				<span style="COLOR: #000000">recvCommuPacket , </span>
				<span style="COLOR: #0000ff">sizeof</span>
				<span style="COLOR: #000000">(CommuPacket) );<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />　　接着判断报文类型进行相应处理：<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">switch</span>
				<span style="COLOR: #000000">(recvCommuPacket. iPacketType)<br /><img id="Codehighlighter1_113_257_Open_Image" onclick="this.style.display='none'; Codehighlighter1_113_257_Open_Text.style.display='none'; Codehighlighter1_113_257_Closed_Image.style.display='inline'; Codehighlighter1_113_257_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_113_257_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_113_257_Closed_Text.style.display='none'; Codehighlighter1_113_257_Open_Image.style.display='inline'; Codehighlighter1_113_257_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
				<span id="Codehighlighter1_113_257_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
						<img src="http://www.cppblog.com/images/dot.gif" />
				</span>
				<span id="Codehighlighter1_113_257_Open_Text">
						<span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span>
						<span style="COLOR: #0000ff">case</span>
						<span style="COLOR: #000000"> PACKET_A:<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    …    </span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">A类报文处理</span>
						<span style="COLOR: #008000">
								<br />
								<img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />
						</span>
						<span style="COLOR: #000000">    </span>
						<span style="COLOR: #0000ff">break</span>
						<span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span>
						<span style="COLOR: #0000ff">case</span>
						<span style="COLOR: #000000"> PACKET_B:<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    …　  </span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">B类报文处理</span>
						<span style="COLOR: #008000">
								<br />
								<img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />
						</span>
						<span style="COLOR: #000000">    </span>
						<span style="COLOR: #0000ff">break</span>
						<span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    </span>
						<span style="COLOR: #0000ff">case</span>
						<span style="COLOR: #000000"> PACKET_C:<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />    …   </span>
						<span style="COLOR: #008000">//</span>
						<span style="COLOR: #008000">C类报文处理</span>
						<span style="COLOR: #008000">
								<br />
								<img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" />
						</span>
						<span style="COLOR: #000000">    </span>
						<span style="COLOR: #0000ff">break</span>
						<span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
				</span>
				<span style="COLOR: #000000">
						<br />
						<img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />
						<br />
						<img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />
				</span>
		</div>
		<p>　　以上程序中最值得注意的是</p>
		<p class="code">Send( (char *)&amp;sendCommuPacket , sizeof(CommuPacket) );<br />Recv( (char *)&amp;recvCommuPacket , sizeof(CommuPacket) );</p>
		<p>　　中的强制类型转换：(char *)&amp;sendCommuPacket、(char *)&amp;recvCommuPacket，先取地址，再转化为char型指针，这样就可以直接利用处理字节流的函数。</p>
		<p>　　利用这种强制类型转化，我们还可以方便程序的编写，例如要对sendCommuPacket所处内存初始化为0，可以这样调用标准库函数memset()：</p>
		<p class="code">memset((char *)&amp;sendCommuPacket,0, sizeof(CommuPacket));</p>
		<h4>2. struct的成员对齐</h4>
		<p>　　Intel、微软等公司曾经出过一道类似的面试题：</p>
		<p>
		</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />
				<span style="COLOR: #000000">1</span>
				<span style="COLOR: #000000">. #include </span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #000000">iostream.h</span>
				<span style="COLOR: #000000">&gt;</span>
				<span style="COLOR: #000000">
						<br />
						<img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />
						<br />
						<img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />
				</span>
				<span style="COLOR: #000000">2</span>
				<span style="COLOR: #000000">. #pragma pack(</span>
				<span style="COLOR: #000000">8</span>
				<span style="COLOR: #000000">)<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #000000">3</span>
				<span style="COLOR: #000000">. </span>
				<span style="COLOR: #0000ff">struct</span>
				<span style="COLOR: #000000"> example1<br /><img id="Codehighlighter1_67_95_Open_Image" onclick="this.style.display='none'; Codehighlighter1_67_95_Open_Text.style.display='none'; Codehighlighter1_67_95_Closed_Image.style.display='inline'; Codehighlighter1_67_95_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_67_95_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_67_95_Closed_Text.style.display='none'; Codehighlighter1_67_95_Open_Image.style.display='inline'; Codehighlighter1_67_95_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
				<span style="COLOR: #000000">4</span>
				<span style="COLOR: #000000">. </span>
				<span id="Codehighlighter1_67_95_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
						<img src="http://www.cppblog.com/images/dot.gif" />
				</span>
				<span id="Codehighlighter1_67_95_Open_Text">
						<span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span>
						<span style="COLOR: #000000">5</span>
						<span style="COLOR: #000000">. </span>
						<span style="COLOR: #0000ff">short</span>
						<span style="COLOR: #000000"> a;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span>
						<span style="COLOR: #000000">6</span>
						<span style="COLOR: #000000">. </span>
						<span style="COLOR: #0000ff">long</span>
						<span style="COLOR: #000000"> b;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /></span>
						<span style="COLOR: #000000">7</span>
						<span style="COLOR: #000000">. }</span>
				</span>
				<span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #000000">8</span>
				<span style="COLOR: #000000">. </span>
				<span style="COLOR: #0000ff">struct</span>
				<span style="COLOR: #000000"> example2<br /><img id="Codehighlighter1_121_179_Open_Image" onclick="this.style.display='none'; Codehighlighter1_121_179_Open_Text.style.display='none'; Codehighlighter1_121_179_Closed_Image.style.display='inline'; Codehighlighter1_121_179_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_121_179_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_121_179_Closed_Text.style.display='none'; Codehighlighter1_121_179_Open_Image.style.display='inline'; Codehighlighter1_121_179_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
				<span style="COLOR: #000000">9</span>
				<span style="COLOR: #000000">. </span>
				<span id="Codehighlighter1_121_179_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
						<img src="http://www.cppblog.com/images/dot.gif" />
				</span>
				<span id="Codehighlighter1_121_179_Open_Text">
						<span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span>
						<span style="COLOR: #000000">10</span>
						<span style="COLOR: #000000">. </span>
						<span style="COLOR: #0000ff">char</span>
						<span style="COLOR: #000000"> c;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span>
						<span style="COLOR: #000000">11</span>
						<span style="COLOR: #000000">. example1 struct1;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /> </span>
						<span style="COLOR: #000000">12</span>
						<span style="COLOR: #000000">. </span>
						<span style="COLOR: #0000ff">short</span>
						<span style="COLOR: #000000"> e;    <br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /></span>
						<span style="COLOR: #000000">13</span>
						<span style="COLOR: #000000">. }</span>
				</span>
				<span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #000000">14</span>
				<span style="COLOR: #000000">. #pragma pack()<br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #000000">15</span>
				<span style="COLOR: #000000">. </span>
				<span style="COLOR: #0000ff">int</span>
				<span style="COLOR: #000000"> main(</span>
				<span style="COLOR: #0000ff">int</span>
				<span style="COLOR: #000000"> argc, </span>
				<span style="COLOR: #0000ff">char</span>
				<span style="COLOR: #000000">*</span>
				<span style="COLOR: #000000"> argv[])<br /><img id="Codehighlighter1_243_446_Open_Image" onclick="this.style.display='none'; Codehighlighter1_243_446_Open_Text.style.display='none'; Codehighlighter1_243_446_Closed_Image.style.display='inline'; Codehighlighter1_243_446_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_243_446_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_243_446_Closed_Text.style.display='none'; Codehighlighter1_243_446_Open_Image.style.display='inline'; Codehighlighter1_243_446_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
				<span style="COLOR: #000000">16</span>
				<span style="COLOR: #000000">. </span>
				<span id="Codehighlighter1_243_446_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
						<img src="http://www.cppblog.com/images/dot.gif" />
				</span>
				<span id="Codehighlighter1_243_446_Open_Text">
						<span style="COLOR: #000000">{<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /> </span>
						<span style="COLOR: #000000">17</span>
						<span style="COLOR: #000000">. example2 struct2;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span>
						<span style="COLOR: #000000">18</span>
						<span style="COLOR: #000000">. cout </span>
						<span style="COLOR: #000000">&lt;&lt;</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">sizeof</span>
						<span style="COLOR: #000000">(example1) </span>
						<span style="COLOR: #000000">&lt;&lt;</span>
						<span style="COLOR: #000000"> endl;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span>
						<span style="COLOR: #000000">19</span>
						<span style="COLOR: #000000">. cout </span>
						<span style="COLOR: #000000">&lt;&lt;</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">sizeof</span>
						<span style="COLOR: #000000">(example2) </span>
						<span style="COLOR: #000000">&lt;&lt;</span>
						<span style="COLOR: #000000"> endl;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span>
						<span style="COLOR: #000000">20</span>
						<span style="COLOR: #000000">. cout </span>
						<span style="COLOR: #000000">&lt;&lt;</span>
						<span style="COLOR: #000000"> (unsigned </span>
						<span style="COLOR: #0000ff">int</span>
						<span style="COLOR: #000000">)(</span>
						<span style="COLOR: #000000">&amp;</span>
						<span style="COLOR: #000000">struct2.struct1) </span>
						<span style="COLOR: #000000">-</span>
						<span style="COLOR: #000000"> (unsigned </span>
						<span style="COLOR: #0000ff">int</span>
						<span style="COLOR: #000000">)(</span>
						<span style="COLOR: #000000">&amp;</span>
						<span style="COLOR: #000000">struct2) <br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span>
						<span style="COLOR: #000000">&lt;&lt;</span>
						<span style="COLOR: #000000"> endl;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align="top" /></span>
						<span style="COLOR: #000000">21</span>
						<span style="COLOR: #000000">. </span>
						<span style="COLOR: #0000ff">return</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #000000">0</span>
						<span style="COLOR: #000000">;<br /><img src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /></span>
						<span style="COLOR: #000000">22</span>
						<span style="COLOR: #000000">. }</span>
				</span>
				<span style="COLOR: #000000">
						<br />
						<img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />
						<br />
						<img src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align="top" />
				</span>
		</div>
		<p>　　问程序的输入结果是什么？</p>
		<p>　　答案是：</p>
		<p>8<br />16<br />4</p>
		<p>　　不明白？还是不明白？下面一一道来：</p>
		<p>
				<strong>2.1 自然对界</strong>
		</p>
		<p>　　struct是一种复合数据类型，其构成元素既可以是基本数据类型（如int、long、float等）的变量，也可以是一些复合数据类型（如array、struct、union等）的数据单元。对于结构体，编译器会自动进行成员变量的对齐，以提高运算效率。缺省情况下，编译器为结构体的每个成员按其自然对界（natural alignment）条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储，第一个成员的地址和整个结构的地址相同。</p>
		<p>　　自然对界(natural alignment)即默认对齐方式，是指按结构体的成员中size最大的成员对齐。</p>
		<p>　　例如：</p>
		<p class="code">struct naturalalign<br />{<br /> char a;<br /> short b;<br /> char c;<br />};</p>
		<p>　　在上述结构体中，size最大的是short，其长度为2字节，因而结构体中的char成员a、c都以2为单位对齐，sizeof(naturalalign)的结果等于6；</p>
		<p>　　如果改为：</p>
		<p class="code">struct naturalalign<br />{<br /> char a;<br /> int b;<br /> char c;<br />};</p>
		<p>　　其结果显然为12。</p>
		<p>
				<strong>2.2指定对界</strong>
		</p>
		<p>　　一般地，可以通过下面的方法来改变缺省的对界条件：</p>
		<p>　　· 使用伪指令#pragma pack (n)，编译器将按照n个字节对齐；<br />　　· 使用伪指令#pragma pack ()，取消自定义字节对齐方式。</p>
		<p>　　注意：<strong>如果#pragma pack (n)中指定的n大于结构体中最大成员的size，则其不起作用，结构体仍然按照size最大的成员进行对界。</strong></p>
		<p>　　例如：</p>
		<p class="code">#pragma pack (n)<br />struct naturalalign<br />{<br /> char a;<br /> int b;<br /> char c;<br />};<br />#pragma pack ()</p>
		<p>　　当n为4、8、16时，其对齐方式均一样，sizeof(naturalalign)的结果都等于12。而当n为2时，其发挥了作用，使得sizeof(naturalalign)的结果为8。</p>
		<p>　　在VC++ 6.0编译器中，我们可以指定其对界方式（见图1），其操作方式为依次选择projetct &gt; setting &gt; C/C++菜单，在struct member alignment中指定你要的对界方式。</p>
		<p align="center">
				<img alt="" src="http://www.pconline.com.cn/pcedu/empolder/gj/c/0508/pic/11cstruct01.gif" border="0" />
		</p>
		<p align="center">
				<strong>图1：</strong>
				<em>在VC++ 6.0中指定对界方式</em>
		</p>
		<p>　　另外，通过__attribute((aligned (n)))也可以让所作用的结构体成员对齐在n字节边界上，但是它较少被使用，因而不作详细讲解。</p>
		<p>
				<strong>2.3 面试题的解答</strong>
		</p>
		<p>　　至此，我们可以对Intel、微软的面试题进行全面的解答。</p>
		<p>　　程序中第2行#pragma pack (8)虽然指定了对界为8，但是由于struct example1中的成员最大size为4（long变量size为4），故struct example1仍然按4字节对界，struct example1的size为8，即第18行的输出结果；</p>
		<p>　　struct example2中包含了struct example1，其本身包含的简单数据成员的最大size为2（short变量e），但是因为其包含了struct example1，而struct example1中的最大成员size为4，struct example2也应以4对界，#pragma pack (8)中指定的对界对struct example2也不起作用，故19行的输出结果为16；</p>
		<p>　　由于struct example2中的成员以4为单位对界，故其char变量c后应补充3个空，其后才是成员struct1的内存空间，20行的输出结果为4。</p>
		<h4>3. C和C++间struct的深层区别</h4>
		<p>　　在C++语言中struct具有了“类”　的功能，其与关键字class的区别在于struct中成员变量和函数的默认访问权限为public，而class的为private。</p>
		<p>　　例如，定义struct类和class类：</p>
		<p class="code">struct structA<br />{<br />char a;<br />…<br />}<br />class classB<br />{<br />      char a;<br />      …<br />}</p>
		<p>　　则：</p>
		<p class="code">struct A a;<br />a.a = 'a';    //访问public成员，合法<br />classB b;<br />b.a = 'a';    //访问private成员，不合法</p>
		<p>　　许多文献写到这里就认为已经给出了C++中struct和class的全部区别，实则不然，另外一点需要注意的是：</p>
		<p>　　C++中的struct保持了对C中struct的全面兼容（这符合C++的初衷——“a better c”），因而，下面的操作是合法的：</p>
		<p class="code">//定义struct<br />struct structA<br />{<br />char a;<br />char b;<br />int c;<br />};<br />structA a = {'a' , 'a' ,1};    //  定义时直接赋初值</p>
		<p>　　即struct可以在定义的时候直接以{ }对其成员变量赋初值，而class则不能，在经典书目《thinking C++ 2nd edition》中作者对此点进行了强调。</p>
		<p>
				<br clear="all" />
		</p>
		<h4>4. struct编程注意事项</h4>
		<p>　　看看下面的程序：</p>
		<p class="code">1. #include &lt;iostream.h&gt;<br /><br />2. struct structA<br />3. {<br />4. int iMember;<br />5. char *cMember;<br />6. };<br /><br />7. int main(int argc, char* argv[])<br />8. {<br />9. structA instant1,instant2;<br />10.char c = 'a';<br />    <br />11. instant1.iMember = 1;<br />12. instant1.cMember = &amp;c; <br /> <br />13.instant2 = instant1;<br /> <br />14.cout &lt;&lt; *(instant1.cMember) &lt;&lt; endl;<br /> <br />15.*(instant2.cMember) = 'b';<br /> <br />16. cout &lt;&lt; *(instant1.cMember) &lt;&lt; endl;<br /> <br />17. return 0;<br />}</p>
		<p>　　14行的输出结果是：a<br />　　16行的输出结果是：b</p>
		<p>　　Why?我们在15行对instant2的修改改变了instant1中成员的值！</p>
		<p>　　原因在于13行的instant2 = instant1赋值语句采用的是变量逐个拷贝，这使得instant1和instant2中的cMember指向了同一片内存，因而对instant2的修改也是对instant1的修改。</p>
		<p>　　在C语言中，当结构体中存在指针型成员时，一定要注意在采用赋值语句时是否将2个实例中的指针型成员指向了同一片内存。</p>
		<p>　　在C++语言中，当结构体中存在指针型成员时，我们需要重写struct的拷贝构造函数并进行“=”操作符重载。</p>
		<p class="code">
				<br />
		</p>
		<h4>
				<br clear="all" />
		</h4>
<img src ="http://www.cppblog.com/jht/aggbug/6646.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jht/" target="_blank">季浩</a> 2006-05-05 17:26 <a href="http://www.cppblog.com/jht/archive/2006/05/05/6646.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>