﻿<?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>BlogJava-Snowdream-随笔分类-C/C++</title><link>http://www.blogjava.net/zellux/category/21898.html</link><description>迷茫的大二：读书 思考 等待</description><language>zh-cn</language><lastBuildDate>Sat, 24 May 2008 05:40:20 GMT</lastBuildDate><pubDate>Sat, 24 May 2008 05:40:20 GMT</pubDate><ttl>60</ttl><item><title>原来GCC是支持尾递归的递推优化的</title><link>http://www.blogjava.net/zellux/archive/2008/05/24/202528.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Fri, 23 May 2008 18:05:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2008/05/24/202528.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/202528.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2008/05/24/202528.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/202528.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/202528.html</trackback:ping><description><![CDATA[
		<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.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				<span style="COLOR: #000000">#include </span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #000000">stdlib.h</span>
				<span style="COLOR: #000000">&gt;</span>
				<span style="COLOR: #000000">
						<br />
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />#include </span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #000000">stdio.h</span>
				<span style="COLOR: #000000">&gt;</span>
				<span style="COLOR: #000000">
						<br />
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
						<br />
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				</span>
				<span style="COLOR: #0000ff">void</span>
				<span style="COLOR: #000000"> print_forever(</span>
				<span style="COLOR: #0000ff">int</span>
				<span style="COLOR: #000000"> n)<br /><img id="Codehighlighter1_66_118_Open_Image" onclick="this.style.display='none'; Codehighlighter1_66_118_Open_Text.style.display='none'; Codehighlighter1_66_118_Closed_Image.style.display='inline'; Codehighlighter1_66_118_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_66_118_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_66_118_Closed_Text.style.display='none'; Codehighlighter1_66_118_Open_Image.style.display='inline'; Codehighlighter1_66_118_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
				<span id="Codehighlighter1_66_118_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.blogjava.net/images/dot.gif" />
				</span>
				<span id="Codehighlighter1_66_118_Open_Text">
						<span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    printf(</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">%d\n</span>
						<span style="COLOR: #000000">"</span>
						<span style="COLOR: #000000">, n);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    print_forever(n </span>
						<span style="COLOR: #000000">+</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #000000">1</span>
						<span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
				</span>
				<span style="COLOR: #000000">
						<br />
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
						<br />
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				</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">*</span>
				<span style="COLOR: #000000">argv[])<br /><img id="Codehighlighter1_154_192_Open_Image" onclick="this.style.display='none'; Codehighlighter1_154_192_Open_Text.style.display='none'; Codehighlighter1_154_192_Closed_Image.style.display='inline'; Codehighlighter1_154_192_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_154_192_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_154_192_Closed_Text.style.display='none'; Codehighlighter1_154_192_Open_Image.style.display='inline'; Codehighlighter1_154_192_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
				<span id="Codehighlighter1_154_192_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.blogjava.net/images/dot.gif" />
				</span>
				<span id="Codehighlighter1_154_192_Open_Text">
						<span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    print_forever(</span>
						<span style="COLOR: #000000">0</span>
						<span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />    </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.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
				</span>
				<span style="COLOR: #000000">
						<br />
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				</span>
		</div>
		<br />用gcc -O2编译运行后会不停地打印从0开始的自然数，注意如果编译器没有做优化的话，打印到某个数的时候肯定会发生栈溢出从而程序终止的情况，但这个程序却能一直运行下去，说明编译器做了尾递归优化。<br /><br />用gcc -O2 -S生成这个程序的汇编代码后证实了这一点。<br /><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.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">.L6:<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />        movl    </span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">ebx, </span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">esp)<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />        addl    $</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">, </span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">ebx<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />        movl    $.LC0, (</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">esp)<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />        call    printf<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />        jmp     .L6<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div>print_forever的关键部分被优化成了一个n不断增加的死循环。<br /><br />接下来是分析哪个优化选项处理了尾递归。<br /><br />用O3 O2 O1三个优化强度编译程序，查看汇编代码后，发现尾递归优化是O2中新增的功能。于是查看O2新开启的优化开关：<br />gcc -c -Q -O1 --help=optimizers &gt; /tmp/O1-opts<br />gcc -c -Q -O2 --help=optimizers &gt; /tmp/O2-opts<br />diff /tmp/O2-opts /tmp/O1-opts | grep enabled<br />输出结果：<br /><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 id="Code_Closed_Image_020417" onclick="this.style.display='none'; Code_Closed_Text_020417.style.display='none'; Code_Open_Image_020417.style.display='inline'; Code_Open_Text_020417.style.display='inline';" height="16" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" /><img id="Code_Open_Image_020417" style="DISPLAY: none" onclick="this.style.display='none'; Code_Open_Text_020417.style.display='none'; Code_Closed_Image_020417.style.display='inline'; Code_Closed_Text_020417.style.display='inline';" height="16" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" /><span id="Code_Closed_Text_020417" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"></span><span id="Code_Open_Text_020417" style="DISPLAY: none"><br /><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">falign</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">loops                               [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">falign</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">jumps                               [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">falign</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">labels                              [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">fcaller</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">saves                              [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">fcrossjumping                              [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">fcse</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">follow</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">jumps                          [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">fdelete</span><span style="COLOR: #000000">-</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">pointer</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">checks                [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">fexpensive</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">optimizations                   [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">fforward</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">propagate                         [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">fgcse                                      [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">finline</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">small</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">functions                    [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">foptimize</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">register</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">move                    [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">foptimize</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">sibling</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">calls                    [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">fpeephole2                                 [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">fregmove                                   [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">freorder</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">blocks                            [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">freorder</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">functions                         [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">fschedule</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">insns2                           [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">fstrict</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">aliasing                           [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">fthread</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">jumps                              [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">ftree</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">pre                                  [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">ftree</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">store</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">ccp                            [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">   </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">ftree</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">vrp                                  [enabled]<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></span></div><br />经证实是-foptimize-sibling-calls这个选项实现了尾递归的优化，具体内容可以参看<br /><a href="http://gcc.gnu.org./ml/gcc-patches/2000-03/msg00867.html">http://gcc.gnu.org./ml/gcc-patches/2000-03/msg00867.html</a><img src ="http://www.blogjava.net/zellux/aggbug/202528.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2008-05-24 02:05 <a href="http://www.blogjava.net/zellux/archive/2008/05/24/202528.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C/C++中的序列点</title><link>http://www.blogjava.net/zellux/archive/2008/05/16/200811.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Fri, 16 May 2008 02:42:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2008/05/16/200811.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/200811.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2008/05/16/200811.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/200811.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/200811.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 发信人: NetMD (C++), 信区: CPlusPlus<br>标  题: [FAQ] C/C++中的序列点<br>发信站: 水木社区 (Wed Feb  7 01:13:41 2007), 站内&nbsp;&nbsp;<a href='http://www.blogjava.net/zellux/archive/2008/05/16/200811.html'>阅读全文</a><img src ="http://www.blogjava.net/zellux/aggbug/200811.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2008-05-16 10:42 <a href="http://www.blogjava.net/zellux/archive/2008/05/16/200811.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lab2</title><link>http://www.blogjava.net/zellux/archive/2007/11/20/161745.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Mon, 19 Nov 2007 16:37:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/11/20/161745.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/161745.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/11/20/161745.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/161745.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/161745.html</trackback:ping><description><![CDATA[<p><span style="font-family: 宋体">这个</span>lab<span style="font-family: 宋体">主要考察</span>gdb<span style="font-family: 宋体">的使用和对汇编代码的理解。后者在平时的作业中涉及得较多，这里不再赘述，主要介绍一下</span>gdb<br />
<span style="font-family: 宋体">其实偶对这个也不是很熟，有错误请指正</span> @@</p>
<p><span style="font-family: 宋体">简单的说，</span>gdb<span style="font-family: 宋体">是一款强大的调试工具，尽管它只有文本界面（需要图形界面可以使用</span>ddd<span style="font-family: 宋体">，不过区别不大），但是功能却比</span>eclipse<span style="font-family: 宋体">等调试环境强很多。</span></p>
<p><span style="font-family: 宋体">接下来看看怎样让它为</span>lab2<span style="font-family: 宋体">拆炸弹服务，在命令行下运行</span>gdb bomb<span style="font-family: 宋体">就能开始调试这个炸弹程序，提高警惕，恩</span></p>
<p><span style="font-family: 宋体">首先最重要的，就是如何阻止炸弹的引爆，</span>gdb<span style="font-family: 宋体">自然提供了一般调试工具都包括的断点功能——</span>break<span style="font-family: 宋体">命令</span></p>
<p><span style="font-family: 宋体">在</span>gdb<span style="font-family: 宋体">中输入</span>help break<span style="font-family: 宋体">能够看到相关的信息</span></p>
<p>(gdb) <u>help break</u></p>
<p>Set breakpoint at specified line or function.<br />
Argument may be line number, function name, or "*" and an address.<br />
If line number is specified, break at start of code for that line.<br />
If function is specified, break at start of code for that function.<br />
If an address is specified, break at that exact address.<br />
With no arg, uses current execution address of selected stack frame.<br />
This is useful for breaking on return to a stack frame.<br />
Multiple breakpoints at one place are permitted, and useful if conditional.<br />
Do "help breakpoints" for info on other commands dealing with breakpoints.</p>
<p><span style="font-family: 宋体">可以看到</span>break<span style="font-family: 宋体">允许我们使用行号、函数名或地址设置断点</span></p>
<p><span style="font-family: 宋体">按</span><u>ctrl+z</u><span style="font-family: 宋体">暂时挂起当前的</span>gdb<span style="font-family: 宋体">进程，运行</span><u>objdump &#8211;d bomb | more</u> <span style="font-family: 宋体">查看反编译后的炸弹文件，可以看到里面有这么一行（开始的那个地址每个人都不同）：</span></p>
<p>08049719 &lt;explode_bomb&gt;:</p>
<p><span style="font-family: 宋体">这个就是万恶的引爆炸弹的函数了，运行</span><u>fg</u><span style="font-family: 宋体">返回</span>gdb<span style="font-family: 宋体">环境，在这个函数设置断点：</span></p>
<p><u>break explode_bomb</u>&nbsp;<span style="font-family: 宋体">（可以使用</span>tab<span style="font-family: 宋体">键自动补齐）</span></p>
<p><span style="font-family: 宋体">显示</span></p>
<p>Breakpoint 1 at 0x8049707</p>
<p><span style="font-family: 宋体">接下来你可以喘口气，一般情况下炸弹是不会引爆的了</span></p>
<p><span style="font-family: 宋体">下面我们来拆第一个炸弹，首先同样是设置断点，</span>bomb.c<span style="font-family: 宋体">中给出了各个关卡的函数名，第一关就是</span>phase_1<span style="font-family: 宋体">，使用</span><u>break phase_1</u><span style="font-family: 宋体">在第一关设置断点</span></p>
<p><span style="font-family: 宋体">接下来就开始运行吧，输入</span><u>run</u></p>
<p>Welcome to my fiendish little bomb. You hava 6 phases with</p>
<p>which to blow yourself up. Hava a nice day!</p>
<p><span style="font-family: 宋体">我们已经设置了炸弹断点，这些恐吓可以直接无视。</span></p>
<p><span style="font-family: 宋体">输入</span><u>ABC</u><span style="font-family: 宋体">继续（输入这个是为了方便在后面的测试中找到自己的输入串地址）</span></p>
<p><span style="font-family: 宋体">提示</span>Breakpoint 2, 0x08048c2e in phase_1 ()<span style="font-family: 宋体">，说明现在程序已经停在第一个关了</span></p>
<p><span style="font-family: 宋体">接下来就是分析汇编代码，使用</span><u>disassemble phase_1</u><span style="font-family: 宋体">显示这个函数的汇编代码</span></p>
<p><span style="font-family: 宋体">注意其中关键的几行：</span></p>
<p>8048c2e:68 b4 99 04 08&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; push&nbsp;&nbsp; $0x80499b4</p>
<p>8048c33:ff 75 08&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;pushl&nbsp;0x8(%ebp)</p>
<p>8048c36:e8 b1 03 00 00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;call&nbsp;&nbsp; 8048fec &lt;strings_not_equal&gt;</p>
<p><span style="font-family: 宋体">这个</span>lab<span style="font-family: 宋体">很厚道的一点就是函数名很明确地说明了函数的功能</span> ^_^</p>
<p><span style="font-family: 宋体">估计这三行代码的意思就是比较两个字符串相等，不相等的话应该就会让炸弹爆炸了</span></p>
<p><span style="font-family: 宋体">因为字符串很大，所以传递给这个比较函数的肯定是他们的地址，分别为</span>0x80499b4<span style="font-family: 宋体">和</span>0x8(%ebp)</p>
<p><span style="font-family: 宋体">我们先来看后者，使用</span><u>p/x *(int*)($ebp + 8)</u><span style="font-family: 宋体">查看字符串所在的地址</span></p>
<p>$1 = 0x804a720<span style="font-family: 宋体">，继续使用</span><u>p/x *0x804a720</u><span style="font-family: 宋体">查看内存中这个地址的内容</span></p>
<p>$2 = 0x434241<span style="font-family: 宋体">，连续的三个数，是不是想起什么了？把这三个数分别转换为十进制，就是</span>67 66 65<span style="font-family: 宋体">，分别为</span>CBA<span style="font-family: 宋体">的</span>ASCII<span style="font-family: 宋体">码，看来这里保存了我们输入的串。</span></p>
<p><span style="font-family: 宋体">接下来</span>0x80499b4<span style="font-family: 宋体">里肯定保存着过关的密码</span></p>
<p><u>p/x *0x80499b4</u><span style="font-family: 宋体">，显示</span>$3 = 0x62726556<span style="font-family: 宋体">，</span>c<span style="font-family: 宋体">中的字符串是以</span>0<span style="font-family: 宋体">结尾的，看来这个字符串还不止这个长度，继续使用</span></p>
<p><u>p/x *0x80499b4@10</u><span style="font-family: 宋体">查看这个地址及其后面</span>36<span style="font-family: 宋体">个字节的内容，终于在第二行中出现了终结符</span>&#8221;0x0&#8221;<span style="font-family: 宋体">（不一定是四个字节）</span></p>
<p>$4 = {0x62726556, 0x7469736f, 0x656c2079, 0x20736461, 0x75206f74, 0x656c636e, 0x202c7261, 0x72616e69,</p>
<p>&nbsp;0x75636974, 0x6574616c, 0x69687420, 0x2e73676e, 0x0, 0x21776f57, 0x756f5920, 0x20657627, 0x75666564,</p>
<p>&nbsp;0x20646573, 0x20656874, 0x72636573}</p>
<p><span style="font-family: 宋体">把开头到</span>0x0<span style="font-family: 宋体">的所有信息字节下来，通过手算或者自己写程序得出最后的密码串（注意</span>little endian<span style="font-family: 宋体">中字符的排列方式！）</span></p>
<p><span style="font-family: 宋体">输入</span>run<span style="font-family: 宋体">重新运行，输入刚才得出的密码串，如果前面的计算正确的话，就会提示</span></p>
<p>Phase 1 defused. How about the next one? </p>
<p><span style="font-family: 宋体">关于这个</span>lab<span style="font-family: 宋体">的一些其他心得：</span></p>
<p style="margin-left: 18pt; text-indent: -18pt">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>VMware<span style="font-family: 宋体">中开发很不舒服，屏幕小、字体丑</span>@@<span style="font-family: 宋体">、需要</span>Ctrl+Alt<span style="font-family: 宋体">切换回</span>windows<span style="font-family: 宋体">，不怎么方便，推荐在</span>windows<span style="font-family: 宋体">下使用</span>pietty<span style="font-family: 宋体">登录虚拟机中的</span>linux<span style="font-family: 宋体">系统（</span>RedHat 9<span style="font-family: 宋体">默认安装了</span>sshd<span style="font-family: 宋体">），个人觉得这样比较方便。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ASCII<span style="font-family: 宋体">查询可以在</span>linux<span style="font-family: 宋体">终端中运行</span>man ascii<span style="font-family: 宋体">。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">退出</span>gdb<span style="font-family: 宋体">后，再次进入时一定要注意使用</span>break<span style="font-family: 宋体">给</span>explode_bomb<span style="font-family: 宋体">上断点，不可大意</span> ~.~</p>
<p style="margin-left: 18pt; text-indent: -18pt">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">后面的几关涉及递归等内容，也有和前面几次作业很相似的东东。</span></p>
5.&nbsp;&nbsp;&nbsp;&nbsp;gdb中还有一个很好用的jump指令，可以在运行时任意跳转。<br />
6.&nbsp;&nbsp;&nbsp;&nbsp;看汇编代码时，使用objdump -d bomb &gt; bomb.asm把汇编代码保存到bomb.asm中，然后使用sftp工具把这个文件下载到windows或者直接在vim中查看，这样比在gdb中看方便一些。<br />
7.&nbsp;&nbsp;&nbsp;&nbsp;个人认为lab2和期中考试不冲突，这个lab2可以帮你理清很多汇编语言的概念 <br />
<br />
其他补充：<br />
sfox:&nbsp;<br />
可以通过GDB中的<u>x /s addr</u>输出以\0结尾的字符串<br />
ICSLab:&nbsp;<br />
为了防止每次拆的时候都不停的输入之前的stage的key，可以把key存入文本文件，一行一个key，不要有多余字符<br />
然后GDB run 的时候用<u>gdb bomb</u> 回车<br />
(gdb) <u>b .... ....</u><br />
(gdb) <u>r password.txt<br />
</u>这样bomb就会自动从password.txt中读入之前的密码<br />
直到到达最后一个空行处，如Lab2的说明文档中所述。<br />
<img src ="http://www.blogjava.net/zellux/aggbug/161745.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-11-20 00:37 <a href="http://www.blogjava.net/zellux/archive/2007/11/20/161745.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 入门笔记 (8)  - Object-Oriented Programming</title><link>http://www.blogjava.net/zellux/archive/2007/11/15/160659.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Wed, 14 Nov 2007 16:44:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/11/15/160659.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/160659.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/11/15/160659.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/160659.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/160659.html</trackback:ping><description><![CDATA[1. 纯虚函数的声明：将函数赋值为0<br />
virtual void gen_elems(int pos) = 0;<br />
<br />
2. 通常情况下，定义了一个或多个虚函数的基类要定义一个虚析构函数，因为在释放子类内存时具体析构函数需要在运行期才能确定。 <br />
作者也不建议把析构函数定义为纯虚的，即使没有任何具体的实现。<br />
<br />
恩，睡觉
<img src ="http://www.blogjava.net/zellux/aggbug/160659.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-11-15 00:44 <a href="http://www.blogjava.net/zellux/archive/2007/11/15/160659.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>memcpy函数代码分析</title><link>http://www.blogjava.net/zellux/archive/2007/10/19/153822.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Fri, 19 Oct 2007 15:56:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/10/19/153822.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/153822.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/10/19/153822.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/153822.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/153822.html</trackback:ping><description><![CDATA[<span style="font-family: Courier">maillist上有人问关于这个函数的问题，回复中有人推荐去看它的源代码<br />
<br />
<span style="font-family: 宋体">memcpy调用了__memcpy函数执行内存的复制（__memcpy3d就先不管了），下面是这个这两个函数的代码</span><br />
<br />
<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 alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">memcpy(</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">to,&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">from,&nbsp;size_t&nbsp;n)<br />
<img id="Codehighlighter1_51_158_Open_Image" onclick="this.style.display='none'; Codehighlighter1_51_158_Open_Text.style.display='none'; Codehighlighter1_51_158_Closed_Image.style.display='inline'; Codehighlighter1_51_158_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_51_158_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_51_158_Closed_Text.style.display='none'; Codehighlighter1_51_158_Open_Image.style.display='inline'; Codehighlighter1_51_158_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_51_158_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 alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_51_158_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />#ifdef&nbsp;CONFIG_X86_USE_3DNOW<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;__memcpy3d(to,&nbsp;from,&nbsp;n);<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #0000ff">#else</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;__memcpy(to,&nbsp;from,&nbsp;n);<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #0000ff">#endif</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;__always_inline&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;__memcpy(</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;to,&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;from,&nbsp;size_t&nbsp;n)<br />
<img id="Codehighlighter1_240_595_Open_Image" onclick="this.style.display='none'; Codehighlighter1_240_595_Open_Text.style.display='none'; Codehighlighter1_240_595_Closed_Image.style.display='inline'; Codehighlighter1_240_595_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_240_595_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_240_595_Closed_Text.style.display='none'; Codehighlighter1_240_595_Open_Image.style.display='inline'; Codehighlighter1_240_595_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_240_595_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 alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_240_595_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;d0,&nbsp;d1,&nbsp;d2;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />__asm__&nbsp;__volatile__(<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">rep&nbsp;;&nbsp;movsl\n\t</span><span style="color: #000000">"</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">movl&nbsp;%4,%%ecx\n\t</span><span style="color: #000000">"</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">andl&nbsp;$3,%%ecx\n\t</span><span style="color: #000000">"</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #0000ff">#if</span><span style="color: #000000">&nbsp;1&nbsp;/*&nbsp;want&nbsp;to&nbsp;pay&nbsp;2&nbsp;byte&nbsp;penalty&nbsp;for&nbsp;a&nbsp;chance&nbsp;to&nbsp;skip&nbsp;microcoded&nbsp;rep?&nbsp;*/</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">jz&nbsp;1f\n\t</span><span style="color: #000000">"</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #0000ff">#endif</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">rep&nbsp;;&nbsp;movsb\n\t</span><span style="color: #000000">"</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">1:</span><span style="color: #000000">"</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;:&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">=&amp;c</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;(d0),&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">=&amp;D</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;(d1),&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">=&amp;S</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;(d2)<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;:&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">0</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;(n</span><span style="color: #000000">/</span><span style="color: #000000">4</span><span style="color: #000000">),&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">g</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;(n),&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">1</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;((</span><span style="color: #0000ff">long</span><span style="color: #000000">)&nbsp;to),&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">2</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;((</span><span style="color: #0000ff">long</span><span style="color: #000000">)&nbsp;from)<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;:&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">memory</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;(to);<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div>
<br />
看了一本内联汇编的书，总算把这段代码搞懂了。<br />
起始时，把n/4保存在%ecx寄存器中，并把to和from的地址分别存入%edi和%esi （引用占位符）<br />
然后重复调用movsl n/4次，接下来应该还有(n mod 4)个字节尚未复制，这里用了一个比较巧妙的方法<br />
movl %4, %%ecx&nbsp;&nbsp;&nbsp; 把n的值保存到%ecx<br />
andl $3, %%ecx&nbsp;&nbsp;&nbsp;&nbsp;n与3做逻辑与，得到n mod 4<br />
jz 1f&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果4 | n，跳过后面的复制<br />
rep movsb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 再复制(n mod 4)个字节<br />
<br />
由于是按四个字节复制的，因此效率上memcpy肯定比strcpy高不少。</span> 
<img src ="http://www.blogjava.net/zellux/aggbug/153822.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-10-19 23:56 <a href="http://www.blogjava.net/zellux/archive/2007/10/19/153822.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在未安装qt的windows系统中运行qt程序</title><link>http://www.blogjava.net/zellux/archive/2007/10/04/150451.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Thu, 04 Oct 2007 15:31:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/10/04/150451.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/150451.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/10/04/150451.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/150451.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/150451.html</trackback:ping><description><![CDATA[<p>同目录下包含这三个文件即可<br />
<br />
mingwm10.dll<br />
QtCore4.dll<br />
QtGui4.dll</p>
<img src ="http://www.blogjava.net/zellux/aggbug/150451.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-10-04 23:31 <a href="http://www.blogjava.net/zellux/archive/2007/10/04/150451.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 入门笔记 (7)</title><link>http://www.blogjava.net/zellux/archive/2007/10/01/150087.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Mon, 01 Oct 2007 11:26:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/10/01/150087.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/150087.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/10/01/150087.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/150087.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/150087.html</trackback:ping><description><![CDATA[主要是做DS Project 1时碰到的问题<br />
1. 泛型方法push(elemType &amp;x)无法接受常数等const类型，必须将形参声明为const elemType &amp;x<br />
<br />
2. 在给泛型类SimpleList增加operator&lt;&lt;方法时，把实现代码放在类的声明外部会报错，直接放在里面就可以，不知道是不是必须是内联inline的才可以。<br />
水木问了下，答案是<br />
<br />
<strong>除非在友元声明中显式指定了模板参数，否则与函数模板同名的友元函数的声明不会引用该函数模板.如果未指定模板参数，则友元声明将声明一个非模板函数。<br />
</strong><br />
3. C++中可以throw很多东西，比如String, int等。catch (...)表示把所有的异常都捕捉到。<br />
<img src ="http://www.blogjava.net/zellux/aggbug/150087.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-10-01 19:26 <a href="http://www.blogjava.net/zellux/archive/2007/10/01/150087.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>char *s = "hello"和char s1[]="world"的区别</title><link>http://www.blogjava.net/zellux/archive/2007/10/01/150002.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Sun, 30 Sep 2007 17:40:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/10/01/150002.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/150002.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/10/01/150002.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/150002.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/150002.html</trackback:ping><description><![CDATA[水木上的帖子<br />
<br />
s 是全局数据区，<br />
s1 是函数的栈空间区域，函数执行完成，这个空间就没了<br />
------------------------------------------------------------------------------------------<br />
7.2 可是我听说 char a[ ] 和 char *a 是一样的。 <br />
并非如此。(你所听说的应该跟函数的形式参数有关；参见问题 &nbsp;6.4) 数组不是指针。 数组定义 char a[6] 请求预留 6 个字符的位置, 并用名称 ``a" 表示。也就是说, 有一个称为 ``a" 的位置, 可以放入 6 个字符。 而指针申明 char *p, 请求一个位置放置一个指针, 用名称 ``p" 表示。 这个指针几乎可以指向任何位置: 任何字符和任何连续的字符, 或者哪里也不指(参见问题 5.1 和 &nbsp;1.10)。 <br />
<br />
一个图形胜过千言万语。声明 <br />
<br />
&nbsp;&nbsp; &nbsp;char a[] = "hello";<br />
&nbsp;&nbsp; &nbsp;char *p = "world";<br />
<br />
将会初始化下图所示的数据结果:&nbsp;<br />
<span style="font-family: Courier">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +---+---+---+---+---+---+<br style="font-family: " />
&nbsp;&nbsp; &nbsp;a: | h | e | l | l | o |\0 |<br style="font-family: " />
&nbsp;&nbsp; &nbsp; &nbsp; +---+---+---+---+---+---+<br style="font-family: " />
&nbsp;&nbsp; &nbsp; &nbsp; +-----+ &nbsp; &nbsp; +---+---+---+---+---+---+<br style="font-family: " />
&nbsp;&nbsp; &nbsp;p: | &nbsp;*======&gt; | w | o | r | l | d |\0 |<br style="font-family: " />
&nbsp;&nbsp; &nbsp; &nbsp; +-----+ &nbsp; &nbsp; +---+---+---+---+---+---+</span><br />
<br />
根据 x 是数组还是指针, 类似 x[3] 这样的引用会生成不同的代码。认识到这一点大有裨益。以上面的声明为例, 当编译器看到表达式 &nbsp;a[3] 的时候, 它生成代码从 a 的位置开始跳过 3 个, 然后取出那个字符. 如果它看到 p[3], 它生成代码找到 ``p" 的位置, 取出其中的指针值, 在指针上加 3 然后取出指向的字符。换言之, a[3] 是 名为 a 的对象 (的起始位置) 之后 3 个位置的值, 而 p[3] 是 &nbsp;p 指向的对象的 3 个位置之后的值. 在上例中, a[3] 和 &nbsp;p[3] 碰巧都是 'l' , 但是编译器到达那里的途径不尽相同。本质的区别在于类似 a 的数组和类似 p 的指针一旦在表达式中出现就会按照不同的方法计算, 不论它们是否有下标。下一问题继续深入解释。 参见问题 1.13。 <br />
<br />
参考资料： [K&amp;R2, Sec. 5.5 p. 104]; [CT&amp;P, Sec. 4.5 pp. 64-5]。 <br />
<br />
7.3 那么, 在 C 语言中 ``指针和数组等价" 到底是什么意思 ？ <br />
在 C 语言中对数组和指针的困惑多数都来自这句话。说数组和指针 ``等价" &nbsp;不表示它们相同, 甚至也不能互换。它的意思是说数组和指针的算法定义可以用指针方便的访问数组或者模拟数组。 <br />
特别地, 等价的基础来自这个关键定义: <br />
<br />
一个 T 的数组类型的左值如果出现在表达式中会蜕变为一个指向数组第一个成员的指针(除了三种例外情况); 结果指针的类型是 T 的指针。 <br />
这就是说, 一旦数组出现在表达式中, 编译器会隐式地生成一个指向数组第一个成员地指针, 就像程序员写出了 &amp;a[0] 一样。例外的情况是, 数组为 &nbsp;sizeof 或 &amp; 操作符的操作数, 或者为字符数组的字符串初始值。 <br />
<br />
作为这个这个定义的后果, 编译器并那么不严格区分数组下标操作符和指针。在形如 a[i] 的表达式中, 根据上边的规则, 数组蜕化为指针然后按照指针变量的方式如 p[i] 那样寻址, 如问题 6.2 所述, 尽管最终的内存访问并不一样。 如果你把数组地址赋给指针: <br />
<br />
&nbsp;&nbsp; &nbsp;p = a;<br />
<br />
那么 p[3] 和 a[3] 将会访问同样的成员。 <br />
参见问题 6.6 和 6.11。 <br />
------------------------------------------------------------------------------------------<br />
char *s1 = "hello";<br />
char s2[6] = "hello";<br />
<br />
类型指针与类型数组名在很多场合中可等价使用。容易给人造成的印象是两者是等价。<br />
这话不尽然。首先我们要明白这是两个不同的东西。<br />
<br />
s1的类型char *，而s2的类型是array of char。<br />
s1初始化为一个指针值，指向一个内存区域，该处有6个字符的数据，<br />
即'h', 'e', 'l', 'l', 'o', '\0'。 在运行过程中，s1的值可改变，指向其他任何允许的地址。<br />
但上面的数据("hello")不会在程序退出之前销毁[注：这是另外一个比较迷惑人的细节]，<br />
即使s1变量生命周期结束。<br />
<br />
s2初始化为6个字符的数组，也是'h', 'e', 'l', 'l', 'o', '\0'。在运行过程中，s2的内容可改变，<br />
也就是存储在s2中的hello也就"消失"了。<br />
<br />
但为什么容易给人造成类型指针与类型数组名可等价的疑惑呢？虽然类型不同，但C规定（为了<br />
追求简洁与灵活性，C假设使用者知道自己代码会有什么结果。）在很多场合下，认为数组名<br />
与类型指针类型兼容。记忆中只有2中情况下，数组名不可等同视为数组指针，&amp;与sizeof操作符。<br />
<br />
&nbsp;&nbsp; &nbsp;void foo1(const char *str) {...}; <br />
&nbsp;&nbsp; &nbsp;void foo2(int size) {return size};<br />
&nbsp;&nbsp; &nbsp;...<br />
&nbsp;&nbsp; &nbsp;char *s1 = "hello";<br />
&nbsp;&nbsp; &nbsp;char s2[6] = "hello";<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;foo1(s1); &nbsp; // ok<br />
&nbsp;&nbsp; &nbsp;foo1(s2); &nbsp; // ok<br />
&nbsp;&nbsp; &nbsp;foo1(&amp;s2); &nbsp;// incompatible<br />
&nbsp;&nbsp; &nbsp;foo2(&amp;s2[0]); &nbsp;// ok<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;s1[0] = 0; &nbsp;// error<br />
&nbsp;&nbsp; &nbsp;s2[0] = 0; &nbsp;// ok<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;s1 = s2; &nbsp; // ok<br />
&nbsp;&nbsp; &nbsp;s2 = s1; &nbsp; // error<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;// 下面假设在ia32平台上运行<br />
&nbsp;&nbsp; &nbsp;foo2(sizeof(s1)); // return 4, pointer size<br />
&nbsp;&nbsp; &nbsp;foo2(sizeof(s2)); // return 6, array size<br />
&nbsp;&nbsp; &nbsp;<br />
只记得上面的这些内容，不知道对错，与大家共同提高。<br />
<img src ="http://www.blogjava.net/zellux/aggbug/150002.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-10-01 01:40 <a href="http://www.blogjava.net/zellux/archive/2007/10/01/150002.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 学习笔记 (6)</title><link>http://www.blogjava.net/zellux/archive/2007/10/01/150001.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Sun, 30 Sep 2007 17:08:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/10/01/150001.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/150001.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/10/01/150001.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/150001.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/150001.html</trackback:ping><description><![CDATA[<p>C++ 学习笔记(6)&nbsp; <br />
1. 类声明中定义的函数都被自动处理为inline函数。 <br />
&nbsp; <br />
2. Triangular t5(); 这句话似乎声明了一个类的实例，但事实上，C++为了保持与C语法的一致，该语句会被解释成一个返回Triangular对象的函数；正确的声明应该去掉()。 <br />
&nbsp;<br />
3. 考虑下面一段代码 <br />
class Matrix {<br />
public:<br />
&nbsp;&nbsp;&nbsp; Matrix( int row, int col )&nbsp; // ...<br />
&nbsp;&nbsp;&nbsp; ~Matrix()&nbsp; { delete [] _pmat; }<br />
private:<br />
&nbsp;&nbsp;&nbsp; int _row, _col;<br />
&nbsp;&nbsp;&nbsp; double *_pmat;<br />
};</p>
<p>&nbsp;<br />
{<br />
&nbsp;&nbsp;&nbsp; Matrix mat(4, 4);<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Matrix mat2 = mat;<br />
&nbsp;&nbsp;&nbsp; }<br />
} <br />
&nbsp;&nbsp;&nbsp; 把mat复制给mat2后，mat2中的_pmat与mat的_pmat指向同一个数组，在mat2所在的域结束后，mat2被释放，同时删除了_pmat指针指向的内容。错误发生。 <br />
&nbsp;&nbsp;&nbsp; 解决办法是在Matrix::Matrix( const Matrix &amp;rhs )中详细指出深层拷贝的方法，同时实现赋值操作符的重载。</p>
<p>4. mutable 和 const<br />
const方法无法修改类的成员，mutable成员除外。</p>
<img src ="http://www.blogjava.net/zellux/aggbug/150001.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-10-01 01:08 <a href="http://www.blogjava.net/zellux/archive/2007/10/01/150001.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 入门笔记 (5)</title><link>http://www.blogjava.net/zellux/archive/2007/09/24/147004.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Mon, 24 Sep 2007 12:45:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/09/24/147004.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/147004.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/09/24/147004.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/147004.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/147004.html</trackback:ping><description><![CDATA[1. 查看某个类型的最大最小值：<br />
#include &lt;limits&gt;<br />
int max_int = numeric_limits&lt;int&gt;::max();<br />
double min_dbl = numeric_limits&lt;double&gt;::max();<br />
<br />
2. A struct is simply a <em>class</em> whose members are public by default.<br />
<br />
3. 类的似有成员的保护依赖于对成员名使用的限制，也就是说，通过地址操作、强制类型转换等技术可以被访问，C++可以防止意外的发生，但不能阻止这种故意的欺骗。只有硬件层面才有可能防止这种恶意访问，但通常在现实中也很难做到。<br />
<br />
4. 使用类的初始化列表代替代码体中的赋值语句可以节省很多时间。而且，如果一个数据成员是const的，那么它只能在初始化列表中进行初始化；如果一个数据成员是不具有零参数的构造函数的类类型，那么它也必须在初始化列表中进行初始化。
<img src ="http://www.blogjava.net/zellux/aggbug/147004.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-09-24 20:45 <a href="http://www.blogjava.net/zellux/archive/2007/09/24/147004.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>A Note on TMin</title><link>http://www.blogjava.net/zellux/archive/2007/09/19/146605.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Wed, 19 Sep 2007 13:26:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/09/19/146605.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/146605.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/09/19/146605.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/146605.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/146605.html</trackback:ping><description><![CDATA[关于表示32位整型中最小的数-2147483648的一篇文章,from CSAPP http://csapp.cs.cmu.edu/public/tmin.html<br />
<h1>Summary</h1>
Due to one of the rules for processing integer constants in ANSI C,
the numeric constant <kbd>-2147483648</kbd> is handled in a peculiar
way on a 32-bit, two's complement machine.
<p>
The problem can be corrected by writing
<kbd>-2147483647-1</kbd>, rather than
<kbd>-2147483648</kbd> in any C code.
</p>
<br />
<h1>Description of Problem</h1>
The ANSI C standard requires that an integer constant too large to be
represented as a signed integer be ``promoted'' to an unsigned value.
When GCC encounters the value 2147483648, it gives a warning message:
``<kbd>warning: decimal constant is so large that it is
unsigned</kbd>.''  The result is the same as if the value had been
written <kbd>2147483648U</kbd>.<br />
ANSI C标准中要求太大的整型常量都表示为unsigned<br />
<p>
The compiler processes an expression of the form <kbd>-</kbd><em>X</em>
by first reading the expression <em>X</em> and then
negating it.  Thus, when the C compiler encounters the constant
<kbd>-2147483648</kbd>, it first processes <kbd>2147483648</kbd>,
yielding <kbd>2147483648U</kbd>, and then negates it.  The unsigned
negation of this value is also <kbd>2147483648U</kbd>.  The bit
pattern is correct, but the type is wrong! <br />
</p>
<p>书上的一个小错误<br />
</p>
<h1>Writing TMin in Code</h1>
The ANSI C standard states that the maximum and minimum integers
should be declared as constants <kbd>INT_MAX</kbd> and
<kbd>INT_MIN</kbd> in the file <kbd>limits.h</kbd>.  Looking at
this file on an IA32 Linux machine (in the directory
<kbd>/usr/include</kbd>), we find the following declarations:
<pre>/* Minimum and maximum values a `signed int' can hold.  */<br />
#define INT_MAX	2147483647<br />
#define INT_MIN	(-INT_MAX - 1)<br />
</pre>
<p>
This method of declaring <kbd>INT_MIN</kbd> avoids accidental
promotion and also avoids any warning messages by the C compiler about
integer overflow.
</p>
<p>
The following are ways to write TMin_32 for a 32-bit machine that give
the correct value and type, and don't cause any error messages:
</p>
<ul>
    <li><kbd> -2147483647-1</kbd>
    </li>
    <li><kbd> (int) 2147483648U</kbd>
    </li>
    <li><kbd> 1&lt;&lt;31</kbd>
    </li>
</ul>
The first method is preferred, since it indicates that the
result will be a negative number.<br />
表示-2147483648的几种方法<br />
<img src ="http://www.blogjava.net/zellux/aggbug/146605.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-09-19 21:26 <a href="http://www.blogjava.net/zellux/archive/2007/09/19/146605.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>支持参数和后台运行的shell</title><link>http://www.blogjava.net/zellux/archive/2007/08/28/140541.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Tue, 28 Aug 2007 07:37:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/08/28/140541.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/140541.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/08/28/140541.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/140541.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/140541.html</trackback:ping><description><![CDATA[CSAPP上的例子，但是书中的源码有问题，修改后的版本：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">csapp.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">#define</span><span style="color: #000000;">&nbsp;MAXARGS&nbsp;128</span><span style="color: #000000;"><br><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;eval(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">cmdline);<br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;parseline(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">buf,&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">**</span><span style="color: #000000;">argv);<br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;buildin_command(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">**</span><span style="color: #000000;">argv);<br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;cmdline[MAXLINE];<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">&gt;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Fgets(cmdline,&nbsp;MAXLINE,&nbsp;stdin);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(feof(stdin))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eval(cmdline);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;eval(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">cmdline)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">argv[MAXARGS];<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;buf[MAXLINE];<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;bg;<br>&nbsp;&nbsp;&nbsp;&nbsp;pid_t&nbsp;pid;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;strcpy(buf,&nbsp;cmdline);<br>&nbsp;&nbsp;&nbsp;&nbsp;bg&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;parseline(buf,&nbsp;argv);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(argv[</span><span style="color: #000000;">0</span><span style="color: #000000;">]&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;NULL)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">builtin_command(argv))<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;((pid&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Fork())&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(execve(argv[</span><span style="color: #000000;">0</span><span style="color: #000000;">],&nbsp;argv,&nbsp;environ)&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">%s:&nbsp;Command&nbsp;not&nbsp;found.\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;argv[</span><span style="color: #000000;">0</span><span style="color: #000000;">]);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">bg)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;status;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(waitpid(pid,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">status,&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unix_error(</span><span style="color: #000000;">"</span><span style="color: #000000;">waitfg:&nbsp;waitpid&nbsp;error</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">%d&nbsp;%s</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;pid,&nbsp;cmdline);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br>}<br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;builtin_command(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">**</span><span style="color: #000000;">argv)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">strcmp(argv[</span><span style="color: #000000;">0</span><span style="color: #000000;">],&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">quit</span><span style="color: #000000;">"</span><span style="color: #000000;">))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">strcmp(argv[</span><span style="color: #000000;">0</span><span style="color: #000000;">],&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">"</span><span style="color: #000000;">))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>}<br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;parseline(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">buf,&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">**</span><span style="color: #000000;">argv)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">delim;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;argc;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;bg;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;buf[strlen(buf)&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">*</span><span style="color: #000000;">buf&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">*</span><span style="color: #000000;">buf&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buf</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;argc&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;((delim&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;strchr(buf,&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">)))<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;argv[argc</span><span style="color: #000000;">++</span><span style="color: #000000;">]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;buf;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">delim&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">\0</span><span style="color: #000000;">'</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buf&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;delim&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">*</span><span style="color: #000000;">buf&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">*</span><span style="color: #000000;">buf&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buf</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;argv[argc]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;NULL;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(argc&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;((bg&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">*</span><span style="color: #000000;">argv[argc&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">]&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">'</span><span style="color: #000000;">))&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;argv[</span><span style="color: #000000;">--</span><span style="color: #000000;">argc]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;NULL;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;bg;<br>}<br></span></div>
<br><br><img src ="http://www.blogjava.net/zellux/aggbug/140541.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-08-28 15:37 <a href="http://www.blogjava.net/zellux/archive/2007/08/28/140541.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>APUE - File I/O (5)</title><link>http://www.blogjava.net/zellux/archive/2007/08/22/138633.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Wed, 22 Aug 2007 07:46:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/08/22/138633.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/138633.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/08/22/138633.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/138633.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/138633.html</trackback:ping><description><![CDATA[1. dup和dup2函数<br>#include &lt;unistd.h&gt;<br>int dup(int filedes);<br>int dup2(int filedes, int filedes2);<br>// Both return: new file descriptor if OK, -1 on error<br><br>dup返回的file descriptor(以下简称fd)为当前可用的最低号码，dup2则指定目的fd，如果该fd已被打开，则首先关闭这个fd。<br>dup后两个fd指向相同的file table entry，这意味着它们共享同一个的file status flag, read, write, append, offset等。<br><br>事实上，dup等价于<br>
fcntl(filedes, F_DUPFD, 0);<br>
<br>dup2和也类似于<br>
close(filedes2);<br>
fcntl(filedes, F_DUPFD, filedes2);<br>但这不是一个原子操作，而且errno也有一定的不同。<img src ="http://www.blogjava.net/zellux/aggbug/138633.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-08-22 15:46 <a href="http://www.blogjava.net/zellux/archive/2007/08/22/138633.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>APUE - File I/O (4) - Atomic Operations</title><link>http://www.blogjava.net/zellux/archive/2007/08/21/138379.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Tue, 21 Aug 2007 06:45:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/08/21/138379.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/138379.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/08/21/138379.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/138379.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/138379.html</trackback:ping><description><![CDATA[<strong>Appending to a File</strong><br>&nbsp;考虑某个单一进程试图在文件追加写入的操作。由于早期的UNIX系统不支持O_APPEND选项，因此得先用lseek将offset置于文件尾部。<br>if (lseek(fd, 0L, 2) &lt; 0)<br>&nbsp;&nbsp;&nbsp; err_sys("lseek error");<br>if (write(fd, buf, 100) != 100)<br>&nbsp;&nbsp;&nbsp; err_sys("write error");<br>注意这里的lseek函数的第三个参数2等于SEEK_END常量，但是早期UNIX并没有这个常量名（System V中才引进）<br><br>这样的处理在多进程试图在同一文件尾部追加写入时就有可能出现问题。<br>假设两个独立线程A B要在某个文件尾部追加写入，使用了上述方法，并没有使用O_APPEND开关。<br>首
先A指向了该文件尾部（假设是offset=1500的地方），接着内核切换到B进程，B也指向了该尾部，然后写入了100字节，此时内核把v-node
中当前文件的大小改为了1600。内核再次切换进程，A继续运行，调用write方法，结果就在offset=1500的地方写入了，覆盖了B进程写入的
内容。<br><br>这个问题其实和Java中的多线程差不多，指向文件尾部和写入应该作为一个原子操作执行，就像Java中使用synchronized块保护原子操作。使用O_APPEND选项就是一种解决方法。<br>另一种解决方法时使用XSI extension中的pread和pwrite函数。<br>#include &lt;unistd.h&gt;<br><br>ssize_t pread(int <em>filedes,</em> void <em>*buf,</em> size_t <em>nbytes,</em> off_t <em>offset</em>);<br>// Returns: number of bytes read, 0 if end of file, -1 on error<br><br>ssize_t pwrite(int <em>filedes</em>, const void <em>*buf</em>, size_t <em>nbytes</em>, off_t <em>offset</em>);<br>// Returns: number of bytes read, 0 if end of file, -1 on error<br><br>调用pread与调用lseek后再调用read等价，以下情况除外：<br>1. pread的两个步骤无法被中断。<br>2. 文件指针尚未被更新时。<br><br>pwrite与lseek+write的差别也相似。<br><br><strong>Creating a File<br></strong>当使用O_CREAT和O_EXCL开关调用open函数时，如果文件已经存在，则open函数返回失败值。如果不使用这两个开关，可以这样写：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;((fd&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;open(pathname,&nbsp;O_WRONLY))&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(errno&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;ENOENT)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;((fd&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;creat(pathname,&nbsp;mode))&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_sys(</span><span style="color: #000000;">"</span><span style="color: #000000;">creat&nbsp;error</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_sys(</span><span style="color: #000000;">"</span><span style="color: #000000;">open&nbsp;error</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>}<br></span></div>
<br>当open函数执行后creat函数执行前另一个进程创建了同名文件的话，该数据就会被擦除。 <img src ="http://www.blogjava.net/zellux/aggbug/138379.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-08-21 14:45 <a href="http://www.blogjava.net/zellux/archive/2007/08/21/138379.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>APUE - File I/O (3) - File Sharing</title><link>http://www.blogjava.net/zellux/archive/2007/08/20/138233.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Mon, 20 Aug 2007 14:39:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/08/20/138233.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/138233.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/08/20/138233.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/138233.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/138233.html</trackback:ping><description><![CDATA[内核使用三种数据结构表示一个打开的文件，他们之间的关系决定了进程间对于共享文件的作用。<br>Every process has an entry in the process table. Within each process table entry is a table of open file descriptors, which we can think of as a vector, with one entry per descriptor. Associated with each file descriptor are<br>1) The file descriptor flags (close-on-exec; refer to Figure 3.6 and Section 3.14)<br>2) A pointer to a file table entry<br><br>The kernel maintains a file table for all open files. Each file table entry contains<br>1) The file status flags for the file, such as read, write, append, sync, and nonblocking<br>2) The current file offset<br>3) A pointer to the v-node table entry for the file<br><br>Each open file (or device) has a v-node structure that contains information about the type of file and pointers to functions that operate on the file. For most files, the v-node also contains the i-node for the file. This information is read from disk when the file is opened, so that all the pertinent information about the file is readily available. For example, the i-node contains the owner of the file, the size of the file, pointers to where the actual data blocks for the file are located on disk, and so on.<br><br><img src="http://www.blogjava.net/images/blogjava_net/zellux/a.gif" border="0"><br>上图为这三种数据结构及其相互联系<br>其中v-node主要用于提供单个操作系统上的多文件系统支持，Sun把它称为Virtual File System<br>linux中没有v-node，使用了一个generic i-node代替，尽管使用了不同的实现方式，v-node在概念上与generic i-node相同。<br><br>下面来讨论两个独立的进程打开同一文件的情况<br>这种情况下两个进程拥有不同的file table，但其中的两个指针指向了同一个v-node。<br><br> 知道了这些数据结构的情况以后，我们可以更精确的知道某些操作的结果<br>1) 每次write操作结束后，当前文件的offset增加，如果这个操作导致当前的offset超出了文件长度，则i-node表中记录的文件大小会被修改为改动后的大小。<br>2) 使用O_APPEND方式打开文件后，每次调用write函数时，当前文件的offset都会被设置为i-node表中的该文件大小，从而write函数只能在文件尾部追加。<br>3) lseek 函数只改变在file table中的当前文件offset，并不会产生io操作<br><br>注意file descriptor flag和file status flag的作用域差别，前者属于某个单独进程的单独的file descriptor，后者则适用于任意进程中指向给定file table entry的所有descriptor。fcntl函数可以修改这两种flag<br><br>  <img src ="http://www.blogjava.net/zellux/aggbug/138233.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-08-20 22:39 <a href="http://www.blogjava.net/zellux/archive/2007/08/20/138233.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>APUE - File I/O (2) </title><link>http://www.blogjava.net/zellux/archive/2007/08/13/136516.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Mon, 13 Aug 2007 14:14:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/08/13/136516.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/136516.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/08/13/136516.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/136516.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/136516.html</trackback:ping><description><![CDATA[&nbsp;1. File hole<br>The file's offset can be greater than the file's current size, in which case the next <u>write</u> to the file will extend the file. This is referred to as creating a <em>hole </em>in a file and is allowed. Any bytes in a file that not been written are read back as 0.<br>A
hole in a file isn't required to have storage backing it on disk.
Depending on the file system implementation, when you write after
seeking past the end of the file, new disk blocks might be allocated to
store the data, but there's no need to allocate disk blocks for the
data between the old end of file and t he location where you start
writing.<br><br>2. read Function<br>#include &lt;unistd.h&gt;<br>ssize_t read(int filedes, void *buf, size_t nbytes);<br>// Returns: number of bytes read, 0 if end of file, -1 on error<br>
read读取的字节数小于所要求的字节数的几种可能：<br>
1) 从文件中读取，在所要求的字节数读取完成前到达文件尾。<br>
2) 从终端读取，这种情况下通常每次最多读取一行内容。<br>
3) 通过网络读取，网络缓冲可能导致读取到少于要求的字节数。<br>
4) 从管道或者FIFO中读取<br>
5) 从record-oriented设备中读取，如磁带，每次至多返回一个记录。orz...<br>
6) 在一定数量的数据读取后被信号中断。<br>
<br>
3. write Function<br>
#include &lt;unistd.h&gt;<br>
ssize_t write(int filedes, const void *buf, size_t nbytes);<br>
// Returns: number of bytes written if OK, -1 on error<br>
导致错误的通常原因是磁盘已满，或者超出了给定进程的文件大小限制。 <img src ="http://www.blogjava.net/zellux/aggbug/136516.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-08-13 22:14 <a href="http://www.blogjava.net/zellux/archive/2007/08/13/136516.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 入门笔记 (4)</title><link>http://www.blogjava.net/zellux/archive/2007/08/12/136172.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Sun, 12 Aug 2007 08:08:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/08/12/136172.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/136172.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/08/12/136172.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/136172.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/136172.html</trackback:ping><description><![CDATA[<p>PS: 看了IEF2007 ipx vs pj, ipx vs lx的四场ZvP，ipx和他们的差距自然很大，细节上lx比pj强不少，包括小狗进入矿区时农民的控制，开局的计算等。推荐ipx vs pj中Luna上的一场，局面一边倒，ipx充分展示了ZvP的关键——灵活，打得很妖。<br><br>1. 任何存储字符串size()方法返回的结果的变量必须为string::size_type类型。特别重要的是，不要把size的返回结果赋给一个int变量。string::size_type是一个unsigned型。<br>同样，在定义用作索引的变量时，最好也用string::size_type类型。<br><br>2. vector::const_iterator() 返回只读迭代器。 <br></p>
<p>3. <br>typedef string *pstring;<br>const pstring cstr;<br>等价于string *const cstr;<br>而不是const string *cstr;<br>也可以写成pstring const str;<br>但是大多数人习惯把const写在类型的前面，尽管这种情况把const放在类型后面更容易理解。<br></p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/zellux/aggbug/136172.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-08-12 16:08 <a href="http://www.blogjava.net/zellux/archive/2007/08/12/136172.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>APUE - File I/O (1) </title><link>http://www.blogjava.net/zellux/archive/2007/08/09/135654.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Thu, 09 Aug 2007 14:46:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/08/09/135654.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/135654.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/08/09/135654.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/135654.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/135654.html</trackback:ping><description><![CDATA[1. unbuffered IO是相对于standard IO而言的，unbuffered指每个read和write函数都是通过内核系统调用实现的。这些函数并不是ISO C的一部分，但都属于POSIX.1和Single UNIX Specification.<br><br>2. File Descriptors<br>内
核中所有打开的文件都是通过File Descriptor指向的。file
descriptor是一个非负的整数，按照管理，UNIX系统把0指定为进程的标准输入，1为进程的标准输出，2为标准错误输出。为了程序的通用性考
虑，这些magic number应该由&lt;unistd.h&gt;中的STDIN_FILENO, STDOUT_FILENO,
STRERR_FILENO代替。<br>file descriptor的范围是从[0, OPEN_MAX]，早期系统的上限为19，现在许多已经到达了63，Linux 2.4.22把每个进程打开的文件数上限提升到了2^20.<br><br>3. open 函数<br>#include &lt;fcntl.h&gt;<br>int open(const char <em>*pathname,</em> int <em>oflag</em>, ..., /* mode_t <em>mode</em> */ );<br>返回: 正常 - 最小的未被使用的file descriptor，出错 - 0 <br>oflag: O_RDONLY(0), O_WRONLY(1), O_RDWR(2) 括号内为大多数情况下的值，这三个参数中必选一个，剩下的可选参数指定了是否追加、是否创建等信息，具体参见man 2 open<br><br>4. File Name and Pathname Truncation<br>如果创建的文件名长度大于NAME_MAX常量，BSD系统会返回一个错误状态，并把errno设为ENAMETOOLONG。如果只是把文件名截去部分就有可能导致与已存在的文件重名。<br>POSIX.1中的常量_POSIX_NO_TRUNC指定了长文件名和路径会被截断还是会引发错误<br><br>5.&nbsp; 创建文件<br>#include &lt;fcntl.h&gt;<br>int creat(const char *<em>pathname</em>, mode_t <em>mode</em>);<br>事实上这个函数等价于<br>open (<em>pathname</em>, O_WRONLY | O_CREAT | O_TRUNC, <em>mode</em>);<br><br>6. 关闭文件<br>#include &lt;fcntl.h&gt;<br>int close(int <em>filedes</em>);<br>返回: 成功 -1，出错 0<br>当一个进程结束时，系统会自动关闭该进程打开的所有文件。<br><br>7. lseek 函数<br>每个打开的文件都有一个current file offset属性，通常是一个非负的整数。默认情况下文件打开后该值为0,除非指定了O_APPEND选项。<br>#include &lt;unistd.h&gt;<br>off_t lseek(int <em>filedes,</em> off_t <em>offset,</em> int <em>whence</em>);<br>// Returns: new file offset if OK, -1 on error<br><br>可以通过seek 0字节来得到当前的offset<br>off_t currpos;<br>currpos = lseek(fd, 0, SEEK_CUR);<br>这个方法也可以用来判断当前文件是否可以被seek，如果是指向管道(pipe)，FIFO，或者socket的file descriptor，lseek把errno设置为ESPIPE并返回-1<br><br>某些设备可能允许负值的offset(如FreeBSD上的/dev/kmem)，因此在检查返回值时应判断是否等于-1，而不是是否小于0<img src ="http://www.blogjava.net/zellux/aggbug/135654.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-08-09 22:46 <a href="http://www.blogjava.net/zellux/archive/2007/08/09/135654.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CSAPP - Linking - 动态链接库</title><link>http://www.blogjava.net/zellux/archive/2007/08/07/135097.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Tue, 07 Aug 2007 15:10:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/08/07/135097.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/135097.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/08/07/135097.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/135097.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/135097.html</trackback:ping><description><![CDATA[1. 静态库(static library)的主要缺陷：<br>
1) 静态库通常需要维护和定期更新，而这些库的使用者就得注意这些变化，并且在库修改后重新将自己的程序和库链接起来<br>
2) 以printf和scanf这两个函数为例，它们的代码在每个运行的进程里都保留了一份，在一个典型的操作系统上运行着50-100个进程，这无疑是对系统资源的严重浪费。（内存的一个有趣的特性是，它永远是一个短缺的资源，无关一个系统里有多大的内存）<br>
<br>
2. 共享库(shared library)弥补了静态库的这些缺陷。所谓共享库，就是指在<strong>运行时</strong>可以被读入到<strong>任意的</strong>内存地址，并与程序链接的模块。这个过程也被称为动态链接(dynamic linking)，由动态链接器(dynamic linker)完成。<br>
Unix系统中共享对象通常后缀为.so，微软的操作系统中大量使用了共享库，通常被称为DLL(dynamic link libraries)<br>
<br>
3. 共享库的&#8220;共享&#8221;表现在两个方面：<br>
1) 在任何一个给定的文件系统中，对于某个特定的库，只有一个.so文件<br>
2) 共享库单独的一份.text域可以由多个不同的运行进程共享。<br>
<br>
4. 编译一个共享库：gcc -shared -fPIC -o libvector.so addvec.c multvec.c<br>
-fPIC开关让编译器产生位置独立的代码(PIC, position independent code)<br>
-shared开关使得编译器产生共享对象的文件<br>
<br>
5. 动态链接的几个应用：<br>
1) 软件的分布式开发<br>
2) 开发高效的Web服务器<br>
早期的Web服务器通过fork和execve调用子进程来产生动态的内容，被称为CGI，而现代的Web服务器则通过基于动态链接库的一种高效的方式。<br>
主要的方法是把生成动态内容的函数打包到一个共享库中，当服务器端接收到一个请求后，服务器动态地读入并且链接到相应的函数，并直接调用这个函数，而
fork和execve则是在子进程的环境中运行的。函数调用后继续存在，以后的类似请求都只需要一个简单的调用就可以了。另外，方法也可以在不停止服务
器的情况下更新，也可以加入新的函数。<br>
<br>
6. Unix系统中读入并链接共享库的方法<br>
#include &lt;dlfcn.h&gt;<br>
void *dlopen(const char *filename, int flag);<br>
// returns: ptr to handle if OK, NULL on error<br>
需要通过-rdynamic编译，具体见CSAPP P569<br>
<br>
获得已经打开的库的句柄(handle)<br>
#include &lt;dlfcn.h&gt;<br>
void #dlsym(void *handle, char *symbol);<br>
// returns: ptr to symbol if OK, NULL on error<br>
<br>
关闭共享库<br>
#include &lt;dlfcn.h&gt;<br>
int dlclose(void *handle);<br>
// returns: 0 if OK, -1 on error<br>
<br>
获得错误信息<br>
#include &lt;dlfcn.h&gt;<br>
const char *dlerror(void); <img src ="http://www.blogjava.net/zellux/aggbug/135097.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-08-07 23:10 <a href="http://www.blogjava.net/zellux/archive/2007/08/07/135097.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>模仿命令行shell的简单程序</title><link>http://www.blogjava.net/zellux/archive/2007/08/04/134358.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Fri, 03 Aug 2007 16:20:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/08/04/134358.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/134358.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/08/04/134358.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/134358.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/134358.html</trackback:ping><description><![CDATA[APUE上的例程，稍微改了下，在进程开始和结束的时候会分别显示当前的PID和退出状态。<br>不支持参数<br>1. fgets命令从标准输入读入命令，当键入文件结束字符（通常是Ctrl+D）时进程结束<br>2. 以\0替换输入命令的最后一个字符，即去掉换行符，使得execlp能够处理<br>3. fork函数创建一个新进程，对父进程返回新的子进程的非负PID，对子进程返回0<br>4. 在子进程中，调用execlp以执行从标准输入读入的命令。fork和exec的组合产生了一个新进程<br>5. 新的子进程开始执行后，父进程等待子进程的终止，这一要求由waitpid实现<br>6. 执行这个程序后还可以在这个简易shell中创建新的自身的进程<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">sys</span><span style="color: #000000;">/</span><span style="color: #000000;">types.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">sys</span><span style="color: #000000;">/</span><span style="color: #000000;">wait.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">ourhdr.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;buf[MAXLINE];<br>&nbsp;&nbsp;&nbsp;&nbsp;pid_t&nbsp;&nbsp;&nbsp;pid;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">%%&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(fgets(buf,&nbsp;MAXLINE,&nbsp;stdin)&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;NULL)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buf&nbsp;[strlen(buf)&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(&nbsp;(pid&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;fork())&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_sys(</span><span style="color: #000000;">"</span><span style="color: #000000;">fork&nbsp;error</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(pid&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;execlp(buf,&nbsp;buf,&nbsp;(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_ret(</span><span style="color: #000000;">"</span><span style="color: #000000;">couldn't&nbsp;execute:&nbsp;%s</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;buf);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(</span><span style="color: #000000;">127</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">***&nbsp;%d&nbsp;***\n</span><span style="color: #000000;">"</span><span style="color: #000000;">, status);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;parent&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(&nbsp;(pid&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;waitpid(pid,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">status,&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">))&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_sys(</span><span style="color: #000000;">"</span><span style="color: #000000;">waitpid&nbsp;error</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">***&nbsp;%d&nbsp;***\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;pid);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">%%&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;exit(</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br>}<br></span></div>
<br><img src ="http://www.blogjava.net/zellux/aggbug/134358.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-08-04 00:20 <a href="http://www.blogjava.net/zellux/archive/2007/08/04/134358.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编译《UNIX环境高级编程》中的第一个程序</title><link>http://www.blogjava.net/zellux/archive/2007/08/03/134139.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Thu, 02 Aug 2007 17:13:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/08/03/134139.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/134139.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/08/03/134139.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/134139.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/134139.html</trackback:ping><description><![CDATA[如果直接编译myls.c，会报错<br>/tmp/cceQcwN0.o: In function `main':<br>myls.c:(.text+0x24): undefined reference to `err_quit'<br>myls.c:(.text+0x5b): undefined reference to `err_sys'<br>collect2: ld 返回 1<br><br>需要下载随书附带的源代码并编译所需的库文件<br>源代码下载：http://www.blogjava.net/Files/zellux/apue.linux3.tar.Z.zip<br>（下载后去掉.zip后缀）<br><br>apue/README 文件中有具体的编译方法，对于Linux系统比较简单，进入lib.rhlin目录，然后运行make，就会在apue目录下生成libmisc.a，以后编译的时候连接这个库就行了。<br><br>以书中的第一个程序myls.c为例
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">sys</span><span style="color: #000000;">/</span><span style="color: #000000;">types.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">dirent.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br><br>#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">ourhdr.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;argc,&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;DIR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">dp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">struct</span><span style="color: #000000;">&nbsp;dirent&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">dirp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(argc&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_quit(</span><span style="color: #000000;">"</span><span style="color: #000000;">a&nbsp;single&nbsp;argument&nbsp;(the&nbsp;directory&nbsp;name)&nbsp;is&nbsp;required</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(&nbsp;(dp&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;opendir(argv[</span><span style="color: #000000;">1</span><span style="color: #000000;">]))&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;NULL)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err_sys(</span><span style="color: #000000;">"</span><span style="color: #000000;">can't&nbsp;open&nbsp;%s</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;argv[</span><span style="color: #000000;">1</span><span style="color: #000000;">]);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(&nbsp;(dirp&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;readdir(dp))&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;NULL)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">%s\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;dirp</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">d_name);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;closedir(dp);<br>&nbsp;&nbsp;&nbsp;&nbsp;exit(</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br>}<br></span></div>
<br>$ gcc myls.c libmisc.a<br>出现几个Warning：<br>libmisc.a(strerror.o): In function `strerror':<br>strerror.c:(.text+0x18): warning: `sys_errlist' is deprecated; use `strerror' or `strerror_r' instead<br>strerror.c:(.text+0xf): warning: `sys_nerr' is deprecated; use `strerror' or `strerror_r' instead<br>看来这本书的确太老了<img src="http://www.blogjava.net/CuteSoft_Client/CuteEditor/images/face7.gif" align="absmiddle" border="0"><br>$ ./a.out .<br>就会列出当前目录下的所有文件<br><br><img src ="http://www.blogjava.net/zellux/aggbug/134139.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-08-03 01:13 <a href="http://www.blogjava.net/zellux/archive/2007/08/03/134139.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CSAPP - Linking - Strong and weak symbols</title><link>http://www.blogjava.net/zellux/archive/2007/08/02/134126.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Thu, 02 Aug 2007 15:45:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/08/02/134126.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/134126.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/08/02/134126.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/134126.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/134126.html</trackback:ping><description><![CDATA[<span style="color: #575874;">《窃听风暴》的男主角乌尔里希&#183;穆埃(Ulrich M&#252;he)
病逝了。。。</span><br style="color: #575874;"><span style="color: #575874;">好片子，好演员，可惜了。。。</span><br><br>CSAPP 第七章Linking太枯燥了<img src="http://www.blogjava.net/CuteSoft_Client/CuteEditor/images/face8.gif" align="absmiddle" border="0">&nbsp; 啃了半天总算看到一点实际经历中遇到过的。<br><br>在编译阶段，编译器把全局变量标记为strong或者weak，并导出到汇编程序中，由汇编程序把这些信息隐式地添加到relocatable object file的符号表(symbol table)中。<br>函数和被初始化的全局变量被标记为strong，未初始化的全局变量被标记为weak。<br>Unix连接器(linker)使用下面的规则来处理多个符号的情况：<br>1. 不允许多个strong symbol的存在<br>2. 如果有一个strong symbol和若干个weak symbol，使用strong symbol<br>3. 只有若干个weak symbol，则使用其中任意一个<br><br>几个例子（未特殊说明的情况，变量定义均在全局范围）：<br>1. foo1.c和bar1.c中都有int main()方法，即存在了两个strong symbol，连接器就会产生一条错误信息。<br>2.
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">/* foo3.c */<br>#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">stdio.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;f(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">);<br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;x&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">15213</span><span style="color: #000000;">;<br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;f();<br>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">x&nbsp;=&nbsp;%d\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;x);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>}</span></div>
<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;bar3.c&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;x;<br><br>void&nbsp;f()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">15212</span><span style="color: #000000;">;<br>}</span></div>
main()方法调用f()后，x变为15212并被输出。<br><span style="color: red; font-weight: bold;">注意这可能不是main()方法的作者原来的意图。</span><br>类似的情况也可能发生在两个weak symbol同名的时候。<br><br>3. 全局变量类型不同的情况：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;foo5.c&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br>#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">stdio.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;f(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">);<br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;x&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">15213</span><span style="color: #000000;">;<br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;y&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">15212</span><span style="color: #000000;">;<br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;f();<br>&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">x&nbsp;=&nbsp;0x%x&nbsp;&nbsp;y&nbsp;=&nbsp;0x%x&nbsp;\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;x,&nbsp;y);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>}<br></span></div>
<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;bar4.c&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">double</span><span style="color: #000000;"> x;<br><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;f()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">0.0</span><span style="color: #000000;">;<br>}<br></span></div>
根据书上的内容，<br>linux&gt; gcc -o foobar5 foo5.c bar5.c<br>linux&gt; ./foobar5<br>结果应该是<br>x = 0x0&nbsp; y = 0x80000000<br><br>但是在自己机器上编译时报错了，可能连接器版本较高，会自动找出这种错误<img src="http://www.blogjava.net/CuteSoft_Client/CuteEditor/images/face22.gif" align="absmiddle" border="0"><br>/usr/bin/ld: Warning: alignment 4 of symbol `x' in /tmp/ccupQXSG.o is smaller than 8 in /tmp/ccNNG9XZ.o<br>是double和int大小不义导致的对齐问题<br><br><br>这些问题都比较细小难以被查觉，通常在程序执行了一段时间后才出现较严重的问题，因此很难被修复，尤其当许多程序员不清楚连接器的工作方式的时候。<br>另外可以使用GCC的-warn-common标记(flag)，使得它在解析多个同名的全局变量时发出警告。<br>试了下没成功@@<br>gcc --warn-common提示无法识别的命令行选项，gcc -Wall则不会发出警告。<br>  <img src ="http://www.blogjava.net/zellux/aggbug/134126.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-08-02 23:45 <a href="http://www.blogjava.net/zellux/archive/2007/08/02/134126.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>推荐一本好书：高质量C++/C编程指南</title><link>http://www.blogjava.net/zellux/archive/2007/08/01/133847.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Wed, 01 Aug 2007 10:16:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/08/01/133847.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/133847.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/08/01/133847.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/133847.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/133847.html</trackback:ping><description><![CDATA[前 言<br>软件质量是被大多数程序员挂在嘴上而不是放在心上的东西！<br>除了完全外行和真正的编程高手外，初读本书，你最先的感受将是惊慌：&#8220;哇！我以前捏造的C++/C 程序怎么会有那么多的毛病？&#8221;<br>别难过，作者只不过比你早几年、多几次惊慌而已。<br>请花一两个小时认真阅读这本百页经书，你将会获益匪浅，这是前面N-1 个读者的建议。
<br>http://www.blogjava.net/Files/zellux/c.zip
<br><img src ="http://www.blogjava.net/zellux/aggbug/133847.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-08-01 18:16 <a href="http://www.blogjava.net/zellux/archive/2007/08/01/133847.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C 学习笔记 (2)</title><link>http://www.blogjava.net/zellux/archive/2007/07/12/129904.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Thu, 12 Jul 2007 11:33:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/07/12/129904.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/129904.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/07/12/129904.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/129904.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/129904.html</trackback:ping><description><![CDATA[1. 二维数组内存分配<br>Algorithm in C上的方法，这种方法好处在于t[i]是指向各行首的指针，类似于Java的数组；而如果直接用malloc分配m*n*sizeof(int)大小的空间，则没有这种效果，类似于C#中的[,]数组<br>int **malloc2d(int r, int c)<br>{<br>&nbsp;&nbsp;&nbsp; int i;<br>&nbsp;&nbsp;&nbsp; int **t = malloc(r * sizeof(int *));<br>&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; r; i++)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t[i] = malloc(c * sizeof(int));<br>&nbsp;&nbsp;&nbsp; return t;<br>}<br> <img src ="http://www.blogjava.net/zellux/aggbug/129904.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-07-12 19:33 <a href="http://www.blogjava.net/zellux/archive/2007/07/12/129904.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C 学习笔记 (1)</title><link>http://www.blogjava.net/zellux/archive/2007/07/10/129381.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Tue, 10 Jul 2007 08:33:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/07/10/129381.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/129381.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/07/10/129381.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/129381.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/129381.html</trackback:ping><description><![CDATA[<p>1. 函数接收一维数组的形参声明<br>func1(str)<br>char str[10];<br>{<br>}<br>表示有界数组，数组的下标只能小于或等于传递数组的大小。10可省略，表示无界数组。</p>
<p>但事实上两者区别很小，编译器只是让函数接收一个指针。</p>
<p>二维数组类似</p>
<p>char str[][10];<br></p>
<p>2. 宏</p>
<p>#define MIN(a, b) (a&lt;b) ? a : b</p>
<p>使用该宏时表达式被直接替换，增加了代码的速度，但因此增加了程序的长度。</p>
<img src ="http://www.blogjava.net/zellux/aggbug/129381.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-07-10 16:33 <a href="http://www.blogjava.net/zellux/archive/2007/07/10/129381.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>几个C的字符串操作代码</title><link>http://www.blogjava.net/zellux/archive/2007/07/08/128923.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Sun, 08 Jul 2007 13:05:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/07/08/128923.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/128923.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/07/08/128923.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/128923.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/128923.html</trackback:ping><description><![CDATA[很简短，有点trick的感觉，就像小学里写的那些(n-1) mod x + 1。进了大学后很少写类似风格的代码了，这些用在java项目中就要因为可读性被bs了。<br>1. 计算串长度 strlen(a)<br>for (i = 0; a[i] != 0; i++); return i;<br><br>2. 复制 strcpy(a, b)<br>for (i = 0; (a[i] = b[i]) != 0; i++);<br><br>3. 比较 strcmp(a, b)<br>for (i = 0; a[i] == b[i]; i++)<br>&nbsp;&nbsp;&nbsp; if (a[i] == 0) return 0;<br>return a[i] - b[i];<br>注意适用于不同长度的字符串<br><br>指针版本<br>1. strlen(a)<br>b = a; while (*b++); return b - a - 1;<br><br>2. strcpy(a, b)<br>while (*a++ = *b++);<br><br>3. strcmp(a, b)<br>while (*a++ = *b++)<br>&nbsp;&nbsp;&nbsp; if (*(a-1) == 0) return 0;<br>return *(a-1) - *(b-1);<br><br><br><br><img src ="http://www.blogjava.net/zellux/aggbug/128923.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-07-08 21:05 <a href="http://www.blogjava.net/zellux/archive/2007/07/08/128923.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于char*的内存分配</title><link>http://www.blogjava.net/zellux/archive/2007/06/17/124831.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Sun, 17 Jun 2007 12:22:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/06/17/124831.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/124831.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/06/17/124831.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/124831.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/124831.html</trackback:ping><description><![CDATA[
<p>BBS上peter大牛的问题：</p>
<p><em>char *s = "string1";<br/>strcpy(s, "string2");<br/>这样为什么会segmentation fault?</em><br/></p>
<p>后面的解答：</p>
<p><em>char *s="string1" //此时"string1"在常量区 s是指向常量区的一个指针 你不能对<br/>常量区的内容进行修改<br/><br/>char s[]="string2" //此时"string2" 在栈区 此时可以对里面的内容进行修改<br/><br/>所以你可以写成<br/><br/>char s[]="string1";<br/>strcpy(s,"string2");</em></p>
<img src ="http://www.blogjava.net/zellux/aggbug/124831.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-06-17 20:22 <a href="http://www.blogjava.net/zellux/archive/2007/06/17/124831.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 入门笔记(3)</title><link>http://www.blogjava.net/zellux/archive/2007/06/03/121672.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Sun, 03 Jun 2007 10:58:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/06/03/121672.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/121672.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/06/03/121672.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/121672.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/121672.html</trackback:ping><description><![CDATA[
<p>1. 关于函数指针<br/><em>The C++ Programming Language</em>上的一段示例代码：<br/>map&lt;string, int&gt; histogram;<br/><br/>void record(const string&amp; s)<br/>{<br/>histogram[s]++;<br/>}<br/><br/>void print(const pair&lt;const string, int&gt;&amp; r)<br/>{<br/>cout &lt;&lt; r.first &lt;&lt; ' ' &lt;&lt; r.second &lt;&lt; '\n\;<br/>}<br/><br/>int main()<br/>{<br/>istream_iterator&lt;string&gt; ii(cin);<br/>istream_iterator&lt;string&gt; eos;<br/><br/>for_each(ii, eos, record);<br/>for_each(histogram.begin(), histogram.end(), print);<br/>}<br/><br/>其中record和print是以函数指针的形式传递给for_each的。感觉这种方法最清晰、直接。<br/>Java似乎更多的是用接口来达到类似的效果的，比如Collections.sort(Comparable)，通常通过匿名内部类来进行自定义元素的比较，从而排序。但是这在语义上已经不是函数了，而是将被排序对象解释为实现了Comparable接口的对象。<br/>另外Java反射机制中也有Mehod方法，觉得也可以通过传递Method类，然后在sort方法中调用这个Method的invoke方法，这应该更接近函数指针的语义。但没看到过这样的实例。<br/>C#则引入了委托的概念，通过delegate关键字声明该方法。多一个关键字感觉就是啰唆了点。 -,-<br/>现在开始对第一次在Thinking in Java中看到的Callback回调机制有了一点感觉。当时看的时候很难理解。<br/>看来在学习某一门语言的时候有一定其他语言的背景进行比较，很容易加深理解。</p>
<p>2. 使用地址传递结构，减少开销<br/>学C++最不适应的就是指针的应用，因为没有C的基础，尽管高中竞赛用的是Pascal，也用指针实现了trie、图的链式表示等比较复杂的数据结构，但是也没有像C++这样指针穿插在整个程序中的，当然C更多。<br/>C++传递结构时默认是先复制一份拷贝，然后函数操作的是该拷贝，而不是Java中的传递引用（当然Java没有结构这一类型）。<br/><em>C++ Primer Plus</em>中指出要<br/>1) 调用函数时传递地址&amp;myStruct<br/>2) 形参声明为指针MyStruct *<br/>3) 访问成员使用操作符 -&gt;<br/><br/>3. 将引用用于结构<br/>同样，为了节省时空开销，在函数返回值时尽量使用引用。<br/><span style="TEXT-DECORATION: underline">const</span> MyStruct &amp; use(MyStruct &amp; mystruct)<br/>注意最好将返回的引用声明为const，否则可以使用这样的代码：<br/>use(myStruct).used = 10;<br/>容易产生语义混乱。<br/>但在某些时候必须去掉const关键字。</p>
<img src ="http://www.blogjava.net/zellux/aggbug/121672.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-06-03 18:58 <a href="http://www.blogjava.net/zellux/archive/2007/06/03/121672.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 入门笔记(2)</title><link>http://www.blogjava.net/zellux/archive/2007/05/30/120978.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Wed, 30 May 2007 12:14:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/05/30/120978.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/120978.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/05/30/120978.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/120978.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/120978.html</trackback:ping><description><![CDATA[<p>1. 最近用Dev C++写的几个程序中，最容易出错的就是忘记初始化和数组越界。C++（至少在Dev C++编译器中）并没有像Java那样严格的纠错功能，因此要格外小心。<br><br>2. C++ Programming Language上的一个样例程序，能看懂，但不能吃透。</p>
<p>&#160;</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.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">vector</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">fstream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iterator</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_129_378_Open_Image onclick="this.style.display='none'; Codehighlighter1_129_378_Open_Text.style.display='none'; Codehighlighter1_129_378_Closed_Image.style.display='inline'; Codehighlighter1_129_378_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_129_378_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_129_378_Closed_Text.style.display='none'; Codehighlighter1_129_378_Open_Image.style.display='inline'; Codehighlighter1_129_378_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()&nbsp;</span><span id=Codehighlighter1_129_378_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.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_129_378_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ifstream&nbsp;fin(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">p61.in</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;istream_iterator</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;ii(fin);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;istream_iterator</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;eos;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;b(ii,&nbsp;eos);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ostream_iterator</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;oo(cout,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;unique_copy(b.begin(),&nbsp;b.end(),&nbsp;oo);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">PAUSE</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>3. 向函数传递二维指针<br>void f(int a[][4]) 或者 void f(int (*a2)[4])<br></p>
<img src ="http://www.blogjava.net/zellux/aggbug/120978.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-05-30 20:14 <a href="http://www.blogjava.net/zellux/archive/2007/05/30/120978.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++入门笔记(1)</title><link>http://www.blogjava.net/zellux/archive/2007/05/27/120221.html</link><dc:creator>ZelluX</dc:creator><author>ZelluX</author><pubDate>Sun, 27 May 2007 11:56:00 GMT</pubDate><guid>http://www.blogjava.net/zellux/archive/2007/05/27/120221.html</guid><wfw:comment>http://www.blogjava.net/zellux/comments/120221.html</wfw:comment><comments>http://www.blogjava.net/zellux/archive/2007/05/27/120221.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zellux/comments/commentRss/120221.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zellux/services/trackbacks/120221.html</trackback:ping><description><![CDATA[都是最近做usaco时碰到的问题<br>1. string转int, double<br>atoi(str.c_str())<br>atod(str.c_str())<br><br>2. std库里已经有swap方法了，难怪我写了以后反应ambiguous method<br><br><br>
<img src ="http://www.blogjava.net/zellux/aggbug/120221.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zellux/" target="_blank">ZelluX</a> 2007-05-27 19:56 <a href="http://www.blogjava.net/zellux/archive/2007/05/27/120221.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>