<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>王永杰的Blog(博客) &#187; C&amp;C++</title>
	<atom:link href="http://wyj.zhuwo.info/category/tech/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://wyj.zhuwo.info</link>
	<description>Keep thinking, seeking and practicing!</description>
	<lastBuildDate>Thu, 26 Jan 2012 11:41:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>MD5 算法 (The MD5 Message-Digest Algorithm)</title>
		<link>http://wyj.zhuwo.info/2011/06/the-md5-message-digest-algorithm/</link>
		<comments>http://wyj.zhuwo.info/2011/06/the-md5-message-digest-algorithm/#comments</comments>
		<pubDate>Thu, 09 Jun 2011 03:13:44 +0000</pubDate>
		<dc:creator>王永杰</dc:creator>
				<category><![CDATA[C&C++]]></category>
		<category><![CDATA[linux应用]]></category>
		<category><![CDATA[技术为本]]></category>

		<guid isPermaLink="false">http://wyj.zhuwo.info/?p=333</guid>
		<description><![CDATA[MD5即Message-Digest Algorithm 5（信息-摘要算法 5），用于确保信息传输完整一致。是计算机广泛使用的雜湊算法之一（又译摘要算法、哈希算法），主流编程语言普遍已有MD5实现。 在维基百科上有详细介绍，在各种语言上也都已有相应实现。 http://www.ietf.org/rfc/rfc1321.txt 上给出了算法介绍和C语言的实现。 我们在使用过程中发现一个问题，就是计算出来的MD5值有误。 经过调查，并非算法有问题，而是因为机器是64位系统导致的，在32位系统上就没问题。 为了通用性，只要把md5.h中的41行，修改一下就可以了。 typedef unsigned int UINT4;]]></description>
			<content:encoded><![CDATA[<p><strong>MD5</strong>即Message-Digest Algorithm 5（信息-摘要<a title="算法" href="http://zh.wikipedia.org/wiki/%E7%AE%97%E6%B3%95">算法</a> 5），用于确保信息传输完整一致。是计算机广泛使用的雜湊算法之一（又译<strong><a title="摘要算法" href="http://zh.wikipedia.org/w/index.php?title=%E6%91%98%E8%A6%81%E7%AE%97%E6%B3%95&amp;action=edit&amp;redlink=1">摘要算法</a></strong>、哈希算法），主流编程语言普遍已有MD5实现。</p>
<p>在维基百科上有详细介绍，在各种语言上也都已有相应实现。<br />
<a href="http://www.ietf.org/rfc/rfc1321.txt">http://www.ietf.org/rfc/rfc1321.txt</a> 上给出了算法介绍和C语言的实现。<br />
我们在使用过程中发现一个问题，就是计算出来的MD5值有误。<br />
经过调查，并非算法有问题，而是因为机器是64位系统导致的，在32位系统上就没问题。<br />
为了通用性，只要把md5.h中的41行，修改一下就可以了。<br />
typedef unsigned int UINT4;</p>
]]></content:encoded>
			<wfw:commentRss>http://wyj.zhuwo.info/2011/06/the-md5-message-digest-algorithm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一个简单的 makefile 模板</title>
		<link>http://wyj.zhuwo.info/2011/05/a-simple-makefile-template/</link>
		<comments>http://wyj.zhuwo.info/2011/05/a-simple-makefile-template/#comments</comments>
		<pubDate>Mon, 23 May 2011 09:03:27 +0000</pubDate>
		<dc:creator>王永杰</dc:creator>
				<category><![CDATA[C&C++]]></category>
		<category><![CDATA[linux应用]]></category>
		<category><![CDATA[技术为本]]></category>

		<guid isPermaLink="false">http://wyj.zhuwo.info/?p=330</guid>
		<description><![CDATA[一个简单的 makefile 模板， CC = gcc CFLAGS+=-c -Wall -I[include_path] LDFLAGS+= -lm SOURCES= \ main.c \ OBJECTS=$(SOURCES:.c=.o) EXECUTABLE=test all: $(SOURCES) $(EXECUTABLE) $(EXECUTABLE): $(OBJECTS) $(CC) $(LDFLAGS) $(OBJECTS) -o $@ .c.o: $(CC) $(CFLAGS) $&#60; -o $@ .PHONY: clean clean: rm -f $(EXECUTABLE) $(OBJECTS)]]></description>
			<content:encoded><![CDATA[<p>一个简单的 makefile 模板，</p>
<pre>CC = gcc

CFLAGS+=-c -Wall -I[include_path]
LDFLAGS+= -lm

SOURCES= \
		 main.c \

OBJECTS=$(SOURCES:.c=.o)

EXECUTABLE=test

all: $(SOURCES) $(EXECUTABLE) 

$(EXECUTABLE): $(OBJECTS)
	$(CC) $(LDFLAGS) $(OBJECTS) -o $@

.c.o:
	$(CC) $(CFLAGS) $&lt; -o $@

.PHONY: clean
clean:
	rm -f $(EXECUTABLE) $(OBJECTS)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://wyj.zhuwo.info/2011/05/a-simple-makefile-template/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Undefined reference to &#8216;pow()&#8217; using  (ZZ)</title>
		<link>http://wyj.zhuwo.info/2011/05/undefined-reference-to-pow-using-zz/</link>
		<comments>http://wyj.zhuwo.info/2011/05/undefined-reference-to-pow-using-zz/#comments</comments>
		<pubDate>Mon, 23 May 2011 08:59:03 +0000</pubDate>
		<dc:creator>王永杰</dc:creator>
				<category><![CDATA[C&C++]]></category>
		<category><![CDATA[技术为本]]></category>

		<guid isPermaLink="false">http://wyj.zhuwo.info/?p=328</guid>
		<description><![CDATA[加上 flag -lm 即可。]]></description>
			<content:encoded><![CDATA[<p>加上 flag -lm 即可。</p>
]]></content:encoded>
			<wfw:commentRss>http://wyj.zhuwo.info/2011/05/undefined-reference-to-pow-using-zz/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What&#8217;s this: __attribute__((packed))</title>
		<link>http://wyj.zhuwo.info/2011/03/whats-this-__attribute__packed/</link>
		<comments>http://wyj.zhuwo.info/2011/03/whats-this-__attribute__packed/#comments</comments>
		<pubDate>Thu, 03 Mar 2011 10:27:02 +0000</pubDate>
		<dc:creator>王永杰</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[C&C++]]></category>
		<category><![CDATA[技术为本]]></category>

		<guid isPermaLink="false">http://wyj.zhuwo.info/?p=292</guid>
		<description><![CDATA[今天在Android的代码里面看到了“__attribute__((packed))”，不清楚什么意思，上网搜了一下，大概明白了。就是让struct按照紧凑模式排列，中间不留任何缝隙。这样在不同的处理器，不同的网络传输等情况都不会出现对齐问题了。很好很强大。 参考链接：http://www.linuxquestions.org/questions/programming-9/whats-this-__attribute__-packed-193570/ 后面是摘录网页上的解释，写的很好。 __attribute__((packed)) ensures that structure fields align on one-byte boundaries. If you want to ensure that your structures have the same size on all processors, the packed attribute is how you tell gcc. As an example, let&#8217;s define &#8230; <a href="http://wyj.zhuwo.info/2011/03/whats-this-__attribute__packed/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>今天在Android的代码里面看到了“__attribute__((packed))”，不清楚什么意思，上网搜了一下，大概明白了。就是让struct按照紧凑模式排列，中间不留任何缝隙。这样在不同的处理器，不同的网络传输等情况都不会出现对齐问题了。很好很强大。</p>
<p>参考链接：http://www.linuxquestions.org/questions/programming-9/whats-this-__attribute__-packed-193570/</p>
<p>后面是摘录网页上的解释，写的很好。<span id="more-292"></span></p>
<p>__attribute__((packed)) ensures that structure fields align on one-byte  boundaries. If you want to ensure that your structures have the same  size on all <a id="KonaLink0" href="http://www.linuxquestions.org/questions/#"><span style="color: blue;">processors</span></a>, the packed attribute is how you tell gcc.</p>
<p>As an example, let&#8217;s define this structure:</p>
<div>
<div>Code:</div>
<pre dir="ltr">struct s {
   char aChar;
   int    anInt;
};</pre>
</div>
<p>A processor that aligns on eight-byte boundaries may compile this  so that aChar is in the first byte, followed by seven bytes of unused  space, then starting anInt in the ninth byte.</p>
<p>A processor that aligns on four-byte boundaries may compile this so that  aChar is in the first byte, followed by three bytes of unused space,  then starting anInt in the fifth byte.</p>
<p>To force anInt to begin immediately after aChar, you would define the structure like this:</p>
<div>
<div>Code:</div>
<pre dir="ltr">struct s {
   char aChar;
   int anInt __attribute__((packed));
};</pre>
</div>
<p>To test these ideas out, I ran this code on an old Pentium 166:</p>
<div>
<div>Code:</div>
<pre dir="ltr">#include &lt;stdio.h&gt;

struct s1 {
   char a;
   int  i;
};

struct s2 {
   char a;
   int i __attribute__((packed));
};

int main( int argc, char* argv[] ) {

  struct s1 s_1;
  struct s2 s_2;

  printf( "sizeof s1 is %d\n" , sizeof(s_1) );
  printf( "sizeof s2 is %d\n" , sizeof(s_2) );

  return( 0 );
}</pre>
</div>
<p>And got these results:</p>
<div>
<div>Code:</div>
<pre dir="ltr">eric.r.turner@turing:~/lab/packed$ ./foo
sizeof s1 is 8
sizeof s2 is 5</pre>
</div>
<p>Looks like this processor aligns on four-byte boundaries.</p>
]]></content:encoded>
			<wfw:commentRss>http://wyj.zhuwo.info/2011/03/whats-this-__attribute__packed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VIM自动给脚本加注释(转载)</title>
		<link>http://wyj.zhuwo.info/2008/08/vim%e8%87%aa%e5%8a%a8%e7%bb%99%e8%84%9a%e6%9c%ac%e5%8a%a0%e6%b3%a8%e9%87%8a%e8%bd%ac%e8%bd%bd/</link>
		<comments>http://wyj.zhuwo.info/2008/08/vim%e8%87%aa%e5%8a%a8%e7%bb%99%e8%84%9a%e6%9c%ac%e5%8a%a0%e6%b3%a8%e9%87%8a%e8%bd%ac%e8%bd%bd/#comments</comments>
		<pubDate>Tue, 05 Aug 2008 03:35:03 +0000</pubDate>
		<dc:creator>王永杰</dc:creator>
				<category><![CDATA[C&C++]]></category>
		<category><![CDATA[linux应用]]></category>
		<category><![CDATA[技术为本]]></category>

		<guid isPermaLink="false">http://wyj.zhuwo.info/?p=85</guid>
		<description><![CDATA[写程序的时候给代码注释有时候蛮烦人的，尤其是用英文写注释的时候，不过养成写注释的习惯，对日后代码的维护还是很有帮助的，一般脚本的开头会注明编写时间，版本，用途等说明。 VIM 里面可以使用映射(map)来帮你自动插入这些信息，就像下面这样 #**************************************************** #         Author: Muddyboot &#8211; toobyddum@gmail.com #  Last modified: 2007-08-10 21:19 #       Filename: /etc/vimrc #    Description: Configuration for vim editor #**************************************************** 其中 Last modified 后面的时间是根据当前时间自动插入的，Filename 后的文件名也是当前编辑的文件名。 我们的目的是在VIM的命令模式下面，按下fuck 4个字符，自动在文件的开头插入上面的信息，这就需要在VIM的配置文件中定义关于 fuck 的map指令 为了方便，先定义一个函数 function AddTitle() call setline(1,&#8221;#****************************************************&#8221;) call append(1,&#8221;#         &#8230; <a href="http://wyj.zhuwo.info/2008/08/vim%e8%87%aa%e5%8a%a8%e7%bb%99%e8%84%9a%e6%9c%ac%e5%8a%a0%e6%b3%a8%e9%87%8a%e8%bd%ac%e8%bd%bd/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>写程序的时候给代码注释有时候蛮烦人的，尤其是用英文写注释的时候，不过养成写注释的习惯，对日后代码的维护还是很有帮助的，一般脚本的开头会注明编写时间，版本，用途等说明。</p>
<p>VIM 里面可以使用映射(map)来帮你自动插入这些信息，就像下面这样</p>
<p>#****************************************************<br />
#         Author: Muddyboot &#8211; toobyddum@gmail.com<br />
#  Last modified: 2007-08-10 21:19<br />
#       Filename: /etc/vimrc<br />
#    Description: Configuration for vim editor<br />
#****************************************************</p>
<p>其中 Last modified 后面的时间是根据当前时间自动插入的，Filename 后的文件名也是当前编辑的文件名。<span id="more-85"></span></p>
<p>我们的目的是在VIM的命令模式下面，按下fuck 4个字符，自动在文件的开头插入上面的信息，这就需要在VIM的配置文件中定义关于 fuck 的map指令</p>
<p>为了方便，先定义一个函数</p>
<p>function AddTitle()<br />
call setline(1,&#8221;#****************************************************&#8221;)<br />
call append(1,&#8221;#         Author: Muddyboot &#8211; toobyddum@gmail.com&#8221;)<br />
call append(2,&#8221;#  &#8221; . &#8220;Last modified: &#8221; . strftime(&#8220;%Y-%m-%d %H:%M&#8221;))<br />
call append(3,&#8221;#       Filename: &#8221; . expand(&#8220;%&#8221;))<br />
call append(4,&#8221;#    Description: &#8220;)<br />
call append(5,&#8221;#****************************************************&#8221;)<br />
endf</p>
<p>函数用 function 关键字开头，函数名的第一个字母需要大写<br />
setline 表示在第一行插入 #********<br />
append 表示追加行，expand表示展开变量的值，%代表文件名，strftime 表示当前时间</p>
<p>然后定义 map 规则：</p>
<p>map fuck &lt;esc&gt;:call AddTitle()&lt;cr&gt;&lt;esc&gt;:$&lt;esc&gt;o</p>
<p>&lt;esc&gt;表示按&lt;ESC&gt;键，&lt;cr&gt;表示回车，上面的指令的意思是在文件开头加入注释，然后跳到文件末尾，进入输入模式。</p>
<p>OK，很简单吧~~~~~~</p>
<p>好，当你对一个脚本修改后，需要更新 Last modified 时间怎么办，手动吗？当然不用这么麻烦~~~~</p>
<p>同样可以指定一个 map 规则，比如 shit</p>
<p>map shit &lt;esc&gt;:/# *Last modified: /s@:.*$@\=strftime(&#8220;: %Y-%m-%d %H:%M&#8221;)@&lt;cr&gt;</p>
<p>让我们一步一步分析上面规则的意思：</p>
<p>/# *Last modified: / 表示查找以 # 开头，后面跟上一些空格，然后是 Last modified: 的行，也就是上面插入注释的第2行<br />
s@&#8230;.@@ 表示替换<br />
第一个 @&#8230;.@ 中间的内容，表示原来的时间，<br />
第二个 @&#8230;.@ 是新的当前时间，由于这个时间是动态的，需要调用函数，故在@后需要用 \= 来告诉 s 命令<br />
\= 后面的代码是一个表达式，其值就是当前时间<br />
最后一个 &lt;cr&gt; 代表回车，也就是执行这个替换操作</p>
<p>好了，现在，你只要按下fuck，VIM会自动行首插入注释，如果下次你修改了文件，按下shit，注释中的最后更改时间则会自动同步到当前时间，再一次感受到了VIM的强大功能了吧 ！</p>
<p>BTW, 当然，你可以使用其他的map名字，不一定非要 fuck 和 shit，偶用它们，不过是觉得好记罢了~~~~</p>
<p>转自：http://blog.chinaunix.net/u/6542/showart.php?id=357716</p>
]]></content:encoded>
			<wfw:commentRss>http://wyj.zhuwo.info/2008/08/vim%e8%87%aa%e5%8a%a8%e7%bb%99%e8%84%9a%e6%9c%ac%e5%8a%a0%e6%b3%a8%e9%87%8a%e8%bd%ac%e8%bd%bd/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>如何在C/C++代码中执行一个DOS命令（Win平台）</title>
		<link>http://wyj.zhuwo.info/2008/07/%e5%a6%82%e4%bd%95%e5%9c%a8cc%e4%bb%a3%e7%a0%81%e4%b8%ad%e6%89%a7%e8%a1%8c%e4%b8%80%e4%b8%aados%e5%91%bd%e4%bb%a4%ef%bc%88win%e5%b9%b3%e5%8f%b0%ef%bc%89/</link>
		<comments>http://wyj.zhuwo.info/2008/07/%e5%a6%82%e4%bd%95%e5%9c%a8cc%e4%bb%a3%e7%a0%81%e4%b8%ad%e6%89%a7%e8%a1%8c%e4%b8%80%e4%b8%aados%e5%91%bd%e4%bb%a4%ef%bc%88win%e5%b9%b3%e5%8f%b0%ef%bc%89/#comments</comments>
		<pubDate>Mon, 28 Jul 2008 03:34:15 +0000</pubDate>
		<dc:creator>王永杰</dc:creator>
				<category><![CDATA[C&C++]]></category>
		<category><![CDATA[技术为本]]></category>
		<category><![CDATA[ShellExecute]]></category>
		<category><![CDATA[WinExec]]></category>

		<guid isPermaLink="false">http://wyj.zhuwo.info/?p=59</guid>
		<description><![CDATA[简单来说可以有三种方式可以实现： int system( const char *command ). UINT WinExec( LPCSTR lpCmdLine, UINT uCmdShow ). HINSTANCE ShellExecute( HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFile, LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShowCmd ). 这三种函数都可以创建一个新的进程，具体的函数定义请查看MSDN，里面说的很清楚。这里要说明的是如何执行一个DOS命令，比如 mkdir 。第一个函数很简单，直接把命令用字符串表示作为参数传入即可，如：&#8221;mkdir D:\\temp\\test&#8221;。后面两个就不太一样了，参数应该为&#8221;cmd /c mkdir D:\\temp\\test&#8221;。比如WinExec(&#8220;cmd /c mkdir D:\\temp\\test&#8221;, SW_HIDE). 和 ShellExecute(NULL, &#8220;open&#8221;, &#8220;cmd /c mkdir&#8221;, &#8220;D:\\temp\\test&#8221;, &#8230; <a href="http://wyj.zhuwo.info/2008/07/%e5%a6%82%e4%bd%95%e5%9c%a8cc%e4%bb%a3%e7%a0%81%e4%b8%ad%e6%89%a7%e8%a1%8c%e4%b8%80%e4%b8%aados%e5%91%bd%e4%bb%a4%ef%bc%88win%e5%b9%b3%e5%8f%b0%ef%bc%89/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>简单来说可以有三种方式可以实现：</p>
<ol>
<li>int system( const char *<span class="parameter">command</span> ).</li>
<li>UINT WinExec( LPCSTR lpCmdLine, UINT uCmdShow ).</li>
<li>HINSTANCE ShellExecute( HWND <em>hwnd</em>, LPCTSTR <em>lpOperation</em>, LPCTSTR <em>lpFile</em>, LPCTSTR <em>lpParameters</em>, LPCTSTR <em>lpDirectory</em>, INT <em>nShowCmd</em> ).<span id="more-59"></span></li>
</ol>
<p>这三种函数都可以创建一个新的进程，具体的函数定义请查看MSDN，里面说的很清楚。这里要说明的是如何执行一个DOS命令，比如 mkdir 。第一个函数很简单，直接把命令用字符串表示作为参数传入即可，如：&#8221;mkdir D:\\temp\\test&#8221;。后面两个就不太一样了，参数应该为&#8221;cmd /c mkdir D:\\temp\\test&#8221;。比如WinExec(&#8220;cmd /c mkdir D:\\temp\\test&#8221;, SW_HIDE).  和 ShellExecute(NULL, &#8220;open&#8221;, &#8220;cmd /c mkdir&#8221;, &#8220;D:\\temp\\test&#8221;, NULL, SW_HIDE). 这样就可以了。我也是试了好久，没有搞定，最后还是求助于搜索，才得解。</p>
<p>[参考链接]：http://topic.csdn.net/t/20031023/01/2385175.html</p>
]]></content:encoded>
			<wfw:commentRss>http://wyj.zhuwo.info/2008/07/%e5%a6%82%e4%bd%95%e5%9c%a8cc%e4%bb%a3%e7%a0%81%e4%b8%ad%e6%89%a7%e8%a1%8c%e4%b8%80%e4%b8%aados%e5%91%bd%e4%bb%a4%ef%bc%88win%e5%b9%b3%e5%8f%b0%ef%bc%89/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>为什么预编译头(Precompiled Header)能够提高编译速度？</title>
		<link>http://wyj.zhuwo.info/2008/05/%e4%b8%ba%e4%bb%80%e4%b9%88%e9%a2%84%e7%bc%96%e8%af%91%e5%a4%b4precompiled-header%e8%83%bd%e5%a4%9f%e6%8f%90%e9%ab%98%e7%bc%96%e8%af%91%e9%80%9f%e5%ba%a6%ef%bc%9f/</link>
		<comments>http://wyj.zhuwo.info/2008/05/%e4%b8%ba%e4%bb%80%e4%b9%88%e9%a2%84%e7%bc%96%e8%af%91%e5%a4%b4precompiled-header%e8%83%bd%e5%a4%9f%e6%8f%90%e9%ab%98%e7%bc%96%e8%af%91%e9%80%9f%e5%ba%a6%ef%bc%9f/#comments</comments>
		<pubDate>Sat, 24 May 2008 10:19:58 +0000</pubDate>
		<dc:creator>王永杰</dc:creator>
				<category><![CDATA[C&C++]]></category>
		<category><![CDATA[为什么？]]></category>
		<category><![CDATA[技术为本]]></category>

		<guid isPermaLink="false">http://wyj.zhuwo.info/?p=54</guid>
		<description><![CDATA[上一篇博客我解释了“为什么可以引用未包含的头文件内容？”，这也让我想起了另外一个问题：“为什么预编译头(Precompiled Header)能够提高编译速度？”。既然要刨根问底，不妨再解释一下这个问题。其实呢，只要理解“编译 &#8211; 链接”这两个步骤各自的作用和一般编译器提高编译速度的方式，那这个问题是小菜一碟啊。 编译(Compile)——把每个源码文件编译成二进制文件（一般是obj）。链接(Link)——把所有的Obj文件堆积木一样组织在一起，形成了DLL、EXE等类型的目标文件。 一般来说，如果一个文件所依赖的所有项如头文件等都没有修改过，那么该文件就不需要重新编译。不管是makefile还是VC的project通过检测依赖关系，减少重新编译的代码量来提高编译速度的。 那么就不难理解为什么预编译头能够提高编译速度了。如果StdAfx.h里面的头文件在每一份实现文件里面都重新包含了一遍，那么每一次实现文件的修改都会导致该文件的重新编译，因而所包含的头文件都要展开一次用于重新编译，无疑会放慢编译速度。然而，如果将公用而不常修改的头文件置于StdAfx.h里面，那么编译器会在第一次遇到StdAfx.h的时候将它编译解释生成stdafx.obj和一个PCH文件，以后再遇到StdAfx.h的时候就会直接使用PCH文件，而不会重新编译了。对于MFC和SDK几万行的头文件来说，速度当然会有大大提高啦。]]></description>
			<content:encoded><![CDATA[<p><a href="http://wyj.zhuwo.info/2008/05/24/%e4%b8%ba%e4%bb%80%e4%b9%88%e5%8f%af%e4%bb%a5%e5%bc%95%e7%94%a8%e6%9c%aa%e5%8c%85%e5%90%ab%e7%9a%84%e5%a4%b4%e6%96%87%e4%bb%b6%e5%86%85%e5%ae%b9%ef%bc%9f/#more-53">上一篇博客</a>我解释了“<a title="为什么可以引用未包含的头文件内容？" href="http://wyj.zhuwo.info/2008/05/24/%e4%b8%ba%e4%bb%80%e4%b9%88%e5%8f%af%e4%bb%a5%e5%bc%95%e7%94%a8%e6%9c%aa%e5%8c%85%e5%90%ab%e7%9a%84%e5%a4%b4%e6%96%87%e4%bb%b6%e5%86%85%e5%ae%b9%ef%bc%9f/">为什么可以引用未包含的头文件内容？</a>”，这也让我想起了另外一个问题：“为什么预编译头(Precompiled Header)能够提高编译速度？”。既然要刨根问底，不妨再解释一下这个问题。其实呢，只要理解“编译 &#8211; 链接”这两个步骤各自的作用和一般编译器提高编译速度的方式，那这个问题是小菜一碟啊。</p>
<p><span id="more-54"></span>编译(Compile)——把每个源码文件编译成二进制文件（一般是obj）。链接(Link)——把所有的Obj文件堆积木一样组织在一起，形成了DLL、EXE等类型的目标文件。</p>
<p>一般来说，如果一个文件所依赖的所有项如头文件等都没有修改过，那么该文件就不需要重新编译。不管是makefile还是VC的project通过检测依赖关系，减少重新编译的代码量来提高编译速度的。</p>
<p>那么就不难理解为什么预编译头能够提高编译速度了。如果StdAfx.h里面的头文件在每一份实现文件里面都重新包含了一遍，那么每一次实现文件的修改都会导致该文件的重新编译，因而所包含的头文件都要展开一次用于重新编译，无疑会放慢编译速度。然而，如果将公用而不常修改的头文件置于StdAfx.h里面，那么编译器会在第一次遇到StdAfx.h的时候将它编译解释生成stdafx.obj和一个PCH文件，以后再遇到StdAfx.h的时候就会直接使用PCH文件，而不会重新编译了。对于MFC和SDK几万行的头文件来说，速度当然会有大大提高啦。</p>
]]></content:encoded>
			<wfw:commentRss>http://wyj.zhuwo.info/2008/05/%e4%b8%ba%e4%bb%80%e4%b9%88%e9%a2%84%e7%bc%96%e8%af%91%e5%a4%b4precompiled-header%e8%83%bd%e5%a4%9f%e6%8f%90%e9%ab%98%e7%bc%96%e8%af%91%e9%80%9f%e5%ba%a6%ef%bc%9f/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>为什么可以引用未包含的头文件内容？</title>
		<link>http://wyj.zhuwo.info/2008/05/%e4%b8%ba%e4%bb%80%e4%b9%88%e5%8f%af%e4%bb%a5%e5%bc%95%e7%94%a8%e6%9c%aa%e5%8c%85%e5%90%ab%e7%9a%84%e5%a4%b4%e6%96%87%e4%bb%b6%e5%86%85%e5%ae%b9%ef%bc%9f/</link>
		<comments>http://wyj.zhuwo.info/2008/05/%e4%b8%ba%e4%bb%80%e4%b9%88%e5%8f%af%e4%bb%a5%e5%bc%95%e7%94%a8%e6%9c%aa%e5%8c%85%e5%90%ab%e7%9a%84%e5%a4%b4%e6%96%87%e4%bb%b6%e5%86%85%e5%ae%b9%ef%bc%9f/#comments</comments>
		<pubDate>Sat, 24 May 2008 08:59:22 +0000</pubDate>
		<dc:creator>王永杰</dc:creator>
				<category><![CDATA[C&C++]]></category>
		<category><![CDATA[为什么？]]></category>
		<category><![CDATA[技术为本]]></category>

		<guid isPermaLink="false">http://wyj.zhuwo.info/?p=53</guid>
		<description><![CDATA[缘起 最近几天奉老大之命学习研究了一下VCF和VCFBuilder。我在修改编译错误的时候发现有些头文件里面引用了其他头文件里面的类，但是在该头文件里面有没有引入任何其他头文件。编译的时候也没有提示这个错误，按照我的惯性思维，这很不可思议啊！这也让我想起了VC编译环境提供的预编译头StdAfx.h也是这个现象，当时就很纳闷，可是没仔细想。这次又碰到了，忍不住想弄个明白，问了几个大虾，没有答案。那就自己来吧。 追踪 经过分析发现，有这么几个特点（我们假定有三对.h/cpp文件名字是A，B，C。A和B都没有引入任何头文件）： “没有包含任何头文件”的头文件A.h和B.h，被其他头文件C.h包含了； B中引用了A中的内容，虽然没有引入A的头文件，但是在C的头文件中引入顺序在A的后面； A和B实现文件无一例外的引入了C的头文件。 这样问题就很明朗了，这里面有一个小小的trick，用一个公共的头文件C解决了引用的问题。再来看看预处理头StdAfx.h，该头文件被要求必须在使用了“预编译技术”的CPP文件中包含，而且一般情况还必须是第一个被包含的头文件。这两种方式显然有一点小小的区别：一个是通过在公共头文件中根据以来关系按顺序引入头文件，一个是通过公共文件引入系统文件和不常改动的文件，而免除了每个头文件都要引入一堆头文件的烦恼，关键是还提高了编译速度哦！ 为什么？ 我个人的一个习惯是，凡事都喜欢问个为什么，此事的缘起也是因为我爱刨根问底。现在让我来回答一下到底是为什么吧。已经理解的不需要继续看了，呵呵。首先我们必须明确的几个问题是： 什么文件需要被编译？ #include是如何起作用的？ 编译器是如何扫描处理代码的？ 我们连起来回答是，你可以指定被编译的文件，一般是c/cpp文件，#include在编译的时候会将引入的文件读入展开在#include所在位置，然后由编译器逐行扫描处理代码，一般现代编译器都是扫描两次。也就是说头文件一般不会被直接进行编译的，而是通过展开在c/cpp文件对应的#include处来起它所应有的作用的。所以说，只要在c/cpp文件中#include全部被展开的时候，声明和定义能够根据依赖关系按顺序排好，就可以编译成功。 好，这就是答案！为什么有的头文件并没有包含任何头文件就不难理解了吧？]]></description>
			<content:encoded><![CDATA[<p><span style="color: #990000;"><span style="color: #990000;"><span style="font-weight: bold;">缘起</span></span></span><br />
最近几天奉老大之命学习研究了一下<a href="http://vcf-online.org" target="_blank">VCF</a>和<a href="http://vcfbuilder.org/" target="_blank">VCFBuilder</a>。我在修改编译错误的时候发现有些头文件里面引用了其他头文件里面的类，但是在该头文件里面有没有引入任何其他头文件。编译的时候也没有提示这个错误，按照我的惯性思维，这很不可思议啊！这也让我想起了VC编译环境提供的预编译头StdAfx.h也是这个现象，当时就很纳闷，可是没仔细想。这次又碰到了，忍不住想弄个明白，问了几个大虾，没有答案。那就自己来吧。</p>
<p><span id="more-53"></span><span style="color: #990000;"><span style="color: #990000;"><span style="font-weight: bold;">追踪</span></span></span><br />
经过分析发现，有这么几个特点（我们假定有三对.h/cpp文件名字是A，B，C。A和B都没有引入任何头文件）：</p>
<ol>
<li>“没有包含任何头文件”的头文件A.h和B.h，被其他头文件C.h包含了；</li>
<li>B中引用了A中的内容，虽然没有引入A的头文件，但是在C的头文件中引入顺序在A的后面；</li>
<li>A和B实现文件无一例外的引入了C的头文件。</li>
</ol>
<p>这样问题就很明朗了，这里面有一个小小的trick，用一个公共的头文件C解决了引用的问题。再来看看预处理头StdAfx.h，该头文件被要求必须在使用了“预编译技术”的CPP文件中包含，而且一般情况还必须是第一个被包含的头文件。这两种方式显然有一点小小的区别：一个是通过在公共头文件中根据以来关系按顺序引入头文件，一个是通过公共文件引入系统文件和不常改动的文件，而免除了每个头文件都要引入一堆头文件的烦恼，关键是还提高了编译速度哦！</p>
<p><span style="color: #990000;"><span style="color: #990000;"><span style="font-weight: bold;">为什么？</span></span></span><br />
我个人的一个习惯是，凡事都喜欢问个为什么，此事的缘起也是因为我爱刨根问底。现在让我来回答一下到底是为什么吧。已经理解的不需要继续看了，呵呵。首先我们必须明确的几个问题是：</p>
<ol>
<li> 什么文件需要被编译？</li>
<li>#include是如何起作用的？</li>
<li>编译器是如何扫描处理代码的？</li>
</ol>
<p>我们连起来回答是，你可以指定被编译的文件，一般是c/cpp文件，#include在编译的时候会将引入的文件读入展开在#include所在位置，然后由编译器逐行扫描处理代码，一般现代编译器都是扫描两次。也就是说头文件一般不会被直接进行编译的，而是通过展开在c/cpp文件对应的#include处来起它所应有的作用的。所以说，只要在c/cpp文件中#include全部被展开的时候，声明和定义能够根据依赖关系按顺序排好，就可以编译成功。</p>
<p>好，这就是答案！为什么有的头文件并没有包含任何头文件就不难理解了吧？</p>
]]></content:encoded>
			<wfw:commentRss>http://wyj.zhuwo.info/2008/05/%e4%b8%ba%e4%bb%80%e4%b9%88%e5%8f%af%e4%bb%a5%e5%bc%95%e7%94%a8%e6%9c%aa%e5%8c%85%e5%90%ab%e7%9a%84%e5%a4%b4%e6%96%87%e4%bb%b6%e5%86%85%e5%ae%b9%ef%bc%9f/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CTreeCtrl 树状控件显示展开和折叠的按钮“+/-”</title>
		<link>http://wyj.zhuwo.info/2008/04/ctreectrl-%e6%a0%91%e7%8a%b6%e6%8e%a7%e4%bb%b6%e6%98%be%e7%a4%ba%e5%b1%95%e5%bc%80%e5%92%8c%e6%8a%98%e5%8f%a0%e7%9a%84%e6%8c%89%e9%92%ae%e2%80%9c-%e2%80%9d/</link>
		<comments>http://wyj.zhuwo.info/2008/04/ctreectrl-%e6%a0%91%e7%8a%b6%e6%8e%a7%e4%bb%b6%e6%98%be%e7%a4%ba%e5%b1%95%e5%bc%80%e5%92%8c%e6%8a%98%e5%8f%a0%e7%9a%84%e6%8c%89%e9%92%ae%e2%80%9c-%e2%80%9d/#comments</comments>
		<pubDate>Mon, 14 Apr 2008 13:35:42 +0000</pubDate>
		<dc:creator>王永杰</dc:creator>
				<category><![CDATA[C&C++]]></category>

		<guid isPermaLink="false">http://wyj.zhuwo.info/?p=43</guid>
		<description><![CDATA[让树状控件显示展开和折叠的按钮其实是很简单的，把 Style 设置成TVS_HASBUTTONS就可以了。不过你可能会发现根节点却没有展开折叠按钮，咋回事呢？折腾半天也没作用，还是看看MSDN的文档吧。 TVS_HASBUTTONS Displays plus (+) and minus (-) buttons next to parent items. The user clicks the buttons to expand or collapse a parent item&#8217;s list of child items. To include buttons with items at the root of &#8230; <a href="http://wyj.zhuwo.info/2008/04/ctreectrl-%e6%a0%91%e7%8a%b6%e6%8e%a7%e4%bb%b6%e6%98%be%e7%a4%ba%e5%b1%95%e5%bc%80%e5%92%8c%e6%8a%98%e5%8f%a0%e7%9a%84%e6%8c%89%e9%92%ae%e2%80%9c-%e2%80%9d/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>让树状控件显示展开和折叠的按钮其实是很简单的，把 Style 设置成TVS_HASBUTTONS就可以了。不过你可能会发现根节点却没有展开折叠按钮，咋回事呢？折腾半天也没作用，还是看看MSDN的文档吧。</p>
<p>TVS_HASBUTTONS<br />
Displays plus (+) and minus (-) buttons next to parent items. The user clicks the buttons to expand or collapse a parent item&#8217;s list of child items. To include buttons with items at the root of the tree view, TVS_LINESATROOT must also be specified.</p>
<p><span id="more-43"></span>呵呵，注意到了吧，最后一句，还需要 TVS_LINESATROOT。这就够了吗？再看看 TVS_LINESATROOT</p>
<p>TVS_LINESATROOT<br />
Uses lines to link items at the root of the tree-view control. This value is ignored if TVS_HASLINES is not also specified.</p>
<p>如果 TVS_HASLINES 没有设置，那么 TVS_LINESATROOT将会被忽略，所以也别忘了 TVS_HASLINES。再看TVS_HASLINES。</p>
<p>TVS_HASLINES<br />
Uses lines to show the hierarchy of items.</p>
<p>看来不需要其他的了，试一试，可以了吧。呵呵。</p>
]]></content:encoded>
			<wfw:commentRss>http://wyj.zhuwo.info/2008/04/ctreectrl-%e6%a0%91%e7%8a%b6%e6%8e%a7%e4%bb%b6%e6%98%be%e7%a4%ba%e5%b1%95%e5%bc%80%e5%92%8c%e6%8a%98%e5%8f%a0%e7%9a%84%e6%8c%89%e9%92%ae%e2%80%9c-%e2%80%9d/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>解析命令行参数规则 (Parsing C Command-Line Arguments)</title>
		<link>http://wyj.zhuwo.info/2008/01/%e8%a7%a3%e6%9e%90%e5%91%bd%e4%bb%a4%e8%a1%8c%e5%8f%82%e6%95%b0%e8%a7%84%e5%88%99-parsing-c-command-line-arguments/</link>
		<comments>http://wyj.zhuwo.info/2008/01/%e8%a7%a3%e6%9e%90%e5%91%bd%e4%bb%a4%e8%a1%8c%e5%8f%82%e6%95%b0%e8%a7%84%e5%88%99-parsing-c-command-line-arguments/#comments</comments>
		<pubDate>Thu, 31 Jan 2008 02:24:13 +0000</pubDate>
		<dc:creator>王永杰</dc:creator>
				<category><![CDATA[C&C++]]></category>
		<category><![CDATA[技术为本]]></category>

		<guid isPermaLink="false">http://wyj.zhuwo.info/2008/01/31/%e8%a7%a3%e6%9e%90%e5%91%bd%e4%bb%a4%e8%a1%8c%e5%8f%82%e6%95%b0%e8%a7%84%e5%88%99-parsing-c-command-line-arguments/</guid>
		<description><![CDATA[这里说的解析命令行参数，并不是说类似getopt的解析函数，而是说win平台的命令行参数是按什么规则传入程序的。前两天我写了个命令行的程序，程序对根目录的处理总是有问题。经过跟踪，发现当输入参数是(&#8220;D:\&#8221;)的时候，实际程序读到的参数是(D:&#8221;)。在路径的两端加上引号，是为了让路径名称中出现空格的时候不会作为参数分隔符处理。可是显然最后一个引号被\转移为 &#8221; 了。 求助于MSDN，终于找到了命令行解析的规则，原文链接：http://msdn2.microsoft.com/en-us/library/aa243471.aspx。这里我做一下翻译： 参数用空格或者TAB进行分割。 一个字符串若被两个双引号包含，则即使其中包含空格或TAB字符也会被视为一个参数。被引起来的字符串可以嵌入参数内。 字符串中存在的双引号可以通过前置反斜杠进行转义。 反斜杠会被解释成单个字符，除非后面紧接着一个双引号。 如果偶数个反斜杠后面跟随一个双引号，每对反斜杠放一个反斜杠到参数中，双引号被解释为一个字符串界定符。 如果奇数个反斜杠后面跟随一个双引号，每对反斜杠放一个反斜杠到argv数组中，双引号则被剩下的反斜杠转义放入到argv中，而不会作文字符串界定符。 这里有几个例子，一看就明白了： Command-Line Input argv[1] argv[2] argv[3] &#8220;a b c&#8221; d e a b c d e &#8220;ab\&#8221;c&#8221; &#8220;\\&#8221; d ab&#8221;c \ d a\\\b d&#8221;e f&#8221;g h a\\\b de fg h &#8230; <a href="http://wyj.zhuwo.info/2008/01/%e8%a7%a3%e6%9e%90%e5%91%bd%e4%bb%a4%e8%a1%8c%e5%8f%82%e6%95%b0%e8%a7%84%e5%88%99-parsing-c-command-line-arguments/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>这里说的解析命令行参数，并不是说类似getopt的解析函数，而是说win平台的命令行参数是按什么规则传入程序的。前两天我写了个命令行的程序，程序对根目录的处理总是有问题。经过跟踪，发现当输入参数是(&#8220;D:\&#8221;)的时候，实际程序读到的参数是(D:&#8221;)。在路径的两端加上引号，是为了让路径名称中出现空格的时候不会作为参数分隔符处理。可是显然最后一个引号被\转移为 &#8221; 了。</p>
<p>求助于MSDN，终于找到了命令行解析的规则，原文链接：<a href="http://msdn2.microsoft.com/en-us/library/aa243471.aspx" title="Parsing C Command-Line Arguments" target="_blank">http://msdn2.microsoft.com/en-us/library/aa243471.aspx</a>。这里我做一下翻译：</p>
<ul type="disc">
<li>参数用空格或者TAB进行分割。</li>
<li>一个字符串若被两个双引号包含，则即使其中包含空格或TAB字符也会被视为一个参数。被引起来的字符串可以嵌入参数内。</li>
<li>字符串中存在的双引号可以通过前置反斜杠进行转义。</li>
<li>反斜杠会被解释成单个字符，除非后面紧接着一个双引号。</li>
<li>如果偶数个反斜杠后面跟随一个双引号，每对反斜杠放一个反斜杠到参数中，双引号被解释为一个字符串界定符。</li>
<li>如果奇数个反斜杠后面跟随一个双引号，每对反斜杠放一个反斜杠到argv数组中，双引号则被剩下的反斜杠转义放入到argv中，而不会作文字符串界定符。</li>
</ul>
<p>这里有几个例子，一看就明白了：</p>
<table border="1" cols="4" frame="below" height="146" rules="rows" width="451">
<tr valign="top">
<td class="label" width="34%"><strong>Command-Line Input</strong></td>
<td class="label" width="20%"><strong>argv[1]</strong></td>
<td class="label" width="21%"><strong>argv[2]</strong></td>
<td class="label" width="25%"><strong>argv[3]</strong></td>
</tr>
<tr>
<td>&#8220;a b c&#8221; d e</td>
<td>a b c</td>
<td>d</td>
<td>e</td>
</tr>
<tr>
<td>&#8220;ab\&#8221;c&#8221; &#8220;\\&#8221; d</td>
<td>ab&#8221;c</td>
<td>\</td>
<td>d</td>
</tr>
<tr>
<td>a\\\b d&#8221;e f&#8221;g h</td>
<td>a\\\b</td>
<td>de fg</td>
<td>h</td>
</tr>
<tr>
<td>a\\\&#8221;b c d</td>
<td>a\&#8221;b</td>
<td>c</td>
<td>d</td>
</tr>
<tr>
<td>a\\\\&#8221;b c&#8221; d e</td>
<td>a\\b c</td>
<td>d</td>
<td>e</td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://wyj.zhuwo.info/2008/01/%e8%a7%a3%e6%9e%90%e5%91%bd%e4%bb%a4%e8%a1%8c%e5%8f%82%e6%95%b0%e8%a7%84%e5%88%99-parsing-c-command-line-arguments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>为发布自动化做点贡献——makefile 中使用 xcopy</title>
		<link>http://wyj.zhuwo.info/2007/12/makefile_xcopy/</link>
		<comments>http://wyj.zhuwo.info/2007/12/makefile_xcopy/#comments</comments>
		<pubDate>Sun, 16 Dec 2007 08:49:00 +0000</pubDate>
		<dc:creator>王永杰</dc:creator>
				<category><![CDATA[C&C++]]></category>
		<category><![CDATA[makefile]]></category>

		<guid isPermaLink="false">http://wyj.zhuwo.info/2007/12/16/%e4%b8%ba%e5%8f%91%e5%b8%83%e8%87%aa%e5%8a%a8%e5%8c%96%e5%81%9a%e7%82%b9%e8%b4%a1%e7%8c%ae%e2%80%94%e2%80%94makefile-%e4%b8%ad%e4%bd%bf%e7%94%a8-xcopy/</guid>
		<description><![CDATA[用makefile做好了一个工程，不同的模块源代码将会被置于不同的文件夹下，而编译后往往也都只是生成在当前编译的目录下。发布的时候就有点麻烦了，比较笨拙的方法就是，一个个的拷贝出来然后再进行打包。这样显然非常繁琐，如果工程的规模较大，这将是一件非常枯燥的事情。如果把这个枯燥的事情变得自动化是不是比较美好呢？ 嘿，这其实是很简单的，你只需要在每一个模块生成的命令的后面利用xcopy来拷贝到目的路径就可以了。这个命令是这么写的： DIST_PATH = D:\dist\bin xcopy /y /r /d /f .\*.dll $(DIST_PATH) 有了这句话，就会把当前编译文件夹下生成的所有DLL都拷贝到目的路径下。下面我来解释一下他们含义： &#8220;DIST_PATH = D:\dist\bin&#8221; 这样定义一个变量作为发布的路径。 好处是：可以做到一改全改，大家都可以理解咯。 需要注意的是：路径不允许用Unix的`/&#8217;来进行分割，xcopy是不认识的。 xcopy 语句的几个参数，可以在dos命令符下用xcopy /?得到帮助。 /y 关闭文件被覆盖的提示信息，保证流程自动化，避免流程被打断。 /r 可以覆盖只读文件，确保拷贝工作的顺利进行:-)。 /d 根据日期，以新文件覆盖旧文件，减少必要的拷贝。 /f 在拷贝的时候显示全部源文件名和目标文件名。 看了这个解释是不是已经能够透彻的理解啦？:-) 当然如果要让这个发布流程都自动化，这样简单的尝试显然是不够的，日后再慢慢探讨吧。]]></description>
			<content:encoded><![CDATA[<p>用makefile做好了一个工程，不同的模块源代码将会被置于不同的文件夹下，而编译后往往也都只是生成在当前编译的目录下。发布的时候就有点麻烦了，比较笨拙的方法就是，一个个的拷贝出来然后再进行打包。这样显然非常繁琐，如果工程的规模较大，这将是一件非常枯燥的事情。如果把这个枯燥的事情变得自动化是不是比较美好呢？</p>
<p>嘿，这其实是很简单的，你只需要在每一个模块生成的命令的后面利用xcopy来拷贝到目的路径就可以了。这个命令是这么写的：</p>
<ul>
<li>DIST_PATH = D:\dist\bin</li>
<li>xcopy /y /r /d /f .\*.dll $(DIST_PATH)</li>
</ul>
<p>有了这句话，就会把当前编译文件夹下生成的所有DLL都拷贝到目的路径下。下面我来解释一下他们含义：</p>
<ul>
<li>&#8220;DIST_PATH = D:\dist\bin&#8221; 这样定义一个变量作为发布的路径。
<ul>
<li>好处是：可以做到一改全改，大家都可以理解咯。</li>
<li>需要注意的是：路径不允许用Unix的`/&#8217;来进行分割，xcopy是不认识的。</li>
</ul>
</li>
<li>xcopy 语句的几个参数，可以在dos命令符下用xcopy /?得到帮助。
<ul>
<li>/y 关闭文件被覆盖的提示信息，保证流程自动化，避免流程被打断。</li>
<li>/r 可以覆盖只读文件，确保拷贝工作的顺利进行:-)。</li>
<li>/d 根据日期，以新文件覆盖旧文件，减少必要的拷贝。</li>
<li>/f 在拷贝的时候显示全部源文件名和目标文件名。</li>
</ul>
</li>
</ul>
<p>看了这个解释是不是已经能够透彻的理解啦？:-)</p>
<p>当然如果要让这个发布流程都自动化，这样简单的尝试显然是不够的，日后再慢慢探讨吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://wyj.zhuwo.info/2007/12/makefile_xcopy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VS2005 编译环境，解决 Runtime Error(运行时错误): R6034。</title>
		<link>http://wyj.zhuwo.info/2007/12/vs2005-%e7%bc%96%e8%af%91%e7%8e%af%e5%a2%83%ef%bc%8c%e8%a7%a3%e5%86%b3-runtime-error%e8%bf%90%e8%a1%8c%e6%97%b6%e9%94%99%e8%af%af-r6034%e3%80%82/</link>
		<comments>http://wyj.zhuwo.info/2007/12/vs2005-%e7%bc%96%e8%af%91%e7%8e%af%e5%a2%83%ef%bc%8c%e8%a7%a3%e5%86%b3-runtime-error%e8%bf%90%e8%a1%8c%e6%97%b6%e9%94%99%e8%af%af-r6034%e3%80%82/#comments</comments>
		<pubDate>Sat, 08 Dec 2007 13:58:00 +0000</pubDate>
		<dc:creator>王永杰</dc:creator>
				<category><![CDATA[C&C++]]></category>

		<guid isPermaLink="false">http://wyj.zhuwo.info/2007/12/08/vs2005-%e7%bc%96%e8%af%91%e7%8e%af%e5%a2%83%ef%bc%8c%e8%a7%a3%e5%86%b3-runtime-error%e8%bf%90%e8%a1%8c%e6%97%b6%e9%94%99%e8%af%af-r6034%e3%80%82/</guid>
		<description><![CDATA[问题：Runtime Error R6034在VS2005编译环境下，用makefile编译的程序爆出了一个可恶的Runtime Error。错误如下图：提示信息是：Runtime Error!R6034An application has made an attempt to load the C runtime library incorrectly. Please contact the application&#8217;s support team for more information.无法正常载入 C runtime library。 问题追因程序生成之后直接执行是没有问题的，而打包后的程序却有问题，看来应该是缺少了什么文件。于是我对编译程序生成的文件一个个删除，并查看检查程序的运行情况。在$(APP).exe.manifest被文件删除之后，R6034现身了，看来罪魁祸首就是它了。我又在MSDN上搜索R6034，得到了这个Error描述的： C Run-Time Error R6034Error Message An application has made an &#8230; <a href="http://wyj.zhuwo.info/2007/12/vs2005-%e7%bc%96%e8%af%91%e7%8e%af%e5%a2%83%ef%bc%8c%e8%a7%a3%e5%86%b3-runtime-error%e8%bf%90%e8%a1%8c%e6%97%b6%e9%94%99%e8%af%af-r6034%e3%80%82/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><span style="color: rgb(153, 0, 0); font-weight: bold;">问题：Runtime Error R6034</span><br />在VS2005编译环境下，用makefile编译的程序爆出了一个可恶的Runtime Error。<br />错误如下图：<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_5zne7wTLvT0/R1qFoS8n_3I/AAAAAAAAACs/x8GnG03Kx9g/s1600-h/R6034.PNG"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_5zne7wTLvT0/R1qFoS8n_3I/AAAAAAAAACs/x8GnG03Kx9g/s400/R6034.PNG" alt="" id="BLOGGER_PHOTO_ID_5141568851924221810" border="0" /></a><br />提示信息是：<br />Runtime Error!<br />R6034<br />An application has made an attempt to load the C runtime library incorrectly. Please contact the application&#8217;s support team for more information.<br />无法正常载入 C runtime library。</p>
<p><span style="color: rgb(153, 0, 0); font-weight: bold;">问题追因</span><br />程序生成之后直接执行是没有问题的，而打包后的程序却有问题，看来应该是缺少了什么文件。于是我对编译程序生成的文件一个个删除，并查看检查程序的运行情况。在$(APP).exe.manifest被文件删除之后，R6034现身了，看来罪魁祸首就是它了。<br />我又在MSDN上搜索R6034，得到了这个Error描述的：
<div class="title">C Run-Time Error R6034<br />Error Message</div>
</p>
<p> An application has made an attempt to load the C runtime library without using a manifest. This is an unsupported way to load Visual C++ DLLs. You need to modify your application to build with a manifest.</p>
<p>这么以来更确认了出现这个问题的原因：缺少了manifest，程序因此无法正常载入C runtime library。</p>
<p><span style="color: rgb(153, 0, 0); font-weight: bold;">解决办法</span><br />解决方法有两个：
<ol>
<li>将编译得到的 $(APP).exe.manifest 一并打包，即和应用程序放在同一个文件夹下；</li>
<li>将manifest文件直接嵌入到可执行文件。</li>
</ol>
<p>嵌入到可执行文件的方法是，需要在生成exe之后在执行下面的命令：
<p> <b>mt.exe –manifest $(APP).exe.manifest -outputresource:</b><b>$(APP)</b><b>.exe;1</b></p>
<p>编译DLL的话，有一点点小区别的。
<p> <b>mt.exe –manifest </b><b>$(LIB)</b><b>.dll.manifest -outputresource:</b><b>$(LIB)</b><b>.dll;2</b> </p>
<p> <span style="color: rgb(153, 0, 0); font-weight: bold;">后话</span><br />VC2005搞出个这玩意有什么好处？</p>
]]></content:encoded>
			<wfw:commentRss>http://wyj.zhuwo.info/2007/12/vs2005-%e7%bc%96%e8%af%91%e7%8e%af%e5%a2%83%ef%bc%8c%e8%a7%a3%e5%86%b3-runtime-error%e8%bf%90%e8%a1%8c%e6%97%b6%e9%94%99%e8%af%af-r6034%e3%80%82/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

