<?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>The 400 Blows</title>
	<atom:link href="http://cfz.cc/feed" rel="self" type="application/rss+xml" />
	<link>http://cfz.cc</link>
	<description>有些事，想不明白</description>
	<lastBuildDate>Thu, 12 Apr 2012 12:34:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Dropbox 各种分享文件的方式</title>
		<link>http://cfz.cc/share_files_in_dropbox.html</link>
		<comments>http://cfz.cc/share_files_in_dropbox.html#comments</comments>
		<pubDate>Mon, 13 Feb 2012 16:23:23 +0000</pubDate>
		<dc:creator>nirocfz</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[dropbox]]></category>
		<category><![CDATA[共享]]></category>
		<category><![CDATA[网盘]]></category>
		<category><![CDATA[软件]]></category>

		<guid isPermaLink="false">http://cfz.cc/?p=347</guid>
		<description><![CDATA[开始，事情是这样的，在网上看到 <a href="http://irising.me/2011/05/930/">Dropbox分享中的Kindle中文电子书单</a> , 是分享了一整个文件夹。之前我知道放在 Dropbox 目录的 public 下的文件可以获取到分享链接，可以分享给所有人，然而一直没弄明白怎么分享给所有人一整个文件夹（不是通过邮件邀请，分享文件夹的那种方式）。

查了下 Dropbox 的一些文档，总结了一些。

<hr />

<a href="https://www.dropbox.com/"><img class="bordernone" title="dropbox_logo" src="https://www.dropbox.com/static/images/dropbox_logo_home.png" alt="" width="290" height="75" /></a>
<h4><strong>1. 同其他 Dropbox 用户共享某个目录</strong></h4>
<h4></h4>
<h4>简单的共享方式。电脑上装了客户端后，在 Dropbox 里某个目录右键选择"Share This Folder", 然后弹出浏览器页面，(或者直接在网页进行该操作)填写要共享给某人的邮件地址(dropbox账号地址)就可以了。</h4>
共享之后，双方（或多方）都有读写权限，也就意味着有人在该目录内进行操作，都会同步给其他共享该目录的 Dropbox 用户。

相关的官方文档: <a href="http://www.dropbox.com/help/19">http://www.dropbox.com/help/19</a>
<h4><strong>2. Public, Photos 两个特殊目录的作用</strong></h4>
<ul>
	<li>如果要分享某个文件你可以获取到 Public 目录下任意文件(但不包括文件夹)的外链地址(可以分享给任何人，不限于 Dropbox 用户)，在本地或网页上选择文件的菜单里的"Copy Public Link"，之后就可以把复制的链接分享给其他人。Public 目录下的子目录，不能通过前面的方式共享给某个(某些)特定的账户。</li>
</ul>
相关的官方文档: <a href="http://www.dropbox.com/help/16">http://www.dropbox.com/help/16</a>
<ul>
	<li>如果你要分享一个相册你可以获取到 Photos 目录下任意目录(包括 Photo 自身)的链接，但不能获取到单个文件的链接。在本地或网页上选择文件的菜单里的"Copy Public Gallery Link"即可获得分享链接。Photos 下的子目录，可以共享给其他指定的 dropbox 用户，与家人、朋友分享 Photos 下某个目录，这样大家就可以一起添加，删除，维护，分享这个“相册”。</li>
</ul>
相关的官方文档: <a href="http://www.dropbox.com/help/18">http://www.dropbox.com/help/18</a>
<h4><strong>3. 分析任意文件夹给任何人</strong></h4>
这就是开头说的一直不知道怎么弄的。前两天终于明白为什么有的 dropbox 用户可以获取到整个文件夹的外链链接分享给所有人，而有人就不行。问题的关键在于"<strong>enable_shmodel</strong>“，默认的 dropbox 账号是没有这种新的分享模式的(这种模式是后来增加的功能，这个功能出现之后注册的 dropbox 账号是否默认启用该模式，不是很清楚)

开启这种模式的方法很简单，访问这个链接即可 <a href="http://www.dropbox.com/enable_shmodel">http://www.dropbox.com/enable_shmodel</a>，之后就可以获取到 dropbox 下任意文件夹，任意文件的链接，方法是选择文件或文件夹菜单的 “Get Shareable Link”

获取到某个文件(夹)的链接之后，它就是可以被任何一个知道该链接的人访问的，如果不想这样分享了，在网页上选择 “Sharing” 选项卡，选择 “Linked Items"，然后点击要终止分享的条目的"Remove"，之后再访问之前该条目的分享链接就会得到一个 404页面。

更具体的说明，应该去看官方的文档
<a href="http://www.dropbox.com/help/167">http://www.dropbox.com/help/167</a>]]></description>
			<content:encoded><![CDATA[<p>开始，事情是这样的，在网上看到 <a href="http://irising.me/2011/05/930/">Dropbox分享中的Kindle中文电子书单</a> , 是分享了一整个文件夹。之前我知道放在 Dropbox 目录的 public 下的文件可以获取到分享链接，可以分享给所有人，然而一直没弄明白怎么分享给所有人一整个文件夹（不是通过邮件邀请，分享文件夹的那种方式）。</p>
<p>查了下 Dropbox 的一些文档，总结了一些。</p>
<hr />
<p><a href="https://www.dropbox.com/"><img class="bordernone" title="dropbox_logo" src="https://www.dropbox.com/static/images/dropbox_logo_home.png" alt="" width="290" height="75" /></a></p>
<h4><strong>1. 同其他 Dropbox 用户共享某个目录</strong></h4>
<h4></h4>
<h4>简单的共享方式。电脑上装了客户端后，在 Dropbox 里某个目录右键选择”Share This Folder”, 然后弹出浏览器页面，(或者直接在网页进行该操作)填写要共享给某人的邮件地址(dropbox账号地址)就可以了。</h4>
<p>共享之后，双方（或多方）都有读写权限，也就意味着有人在该目录内进行操作，都会同步给其他共享该目录的 Dropbox 用户。</p>
<p>相关的官方文档: <a href="http://www.dropbox.com/help/19">http://www.dropbox.com/help/19</a></p>
<h4><strong>2. Public, Photos 两个特殊目录的作用</strong></h4>
<ul>
<li>如果要分享某个文件你可以获取到 Public 目录下任意文件(但不包括文件夹)的外链地址(可以分享给任何人，不限于 Dropbox 用户)，在本地或网页上选择文件的菜单里的”Copy Public Link”，之后就可以把复制的链接分享给其他人。Public 目录下的子目录，不能通过前面的方式共享给某个(某些)特定的账户。</li>
</ul>
<p>相关的官方文档: <a href="http://www.dropbox.com/help/16">http://www.dropbox.com/help/16</a></p>
<ul>
<li>如果你要分享一个相册你可以获取到 Photos 目录下任意目录(包括 Photo 自身)的链接，但不能获取到单个文件的链接。在本地或网页上选择文件的菜单里的”Copy Public Gallery Link”即可获得分享链接。Photos 下的子目录，可以共享给其他指定的 dropbox 用户，与家人、朋友分享 Photos 下某个目录，这样大家就可以一起添加，删除，维护，分享这个“相册”。</li>
</ul>
<p>相关的官方文档: <a href="http://www.dropbox.com/help/18">http://www.dropbox.com/help/18</a></p>
<h4><strong>3. 分析任意文件夹给任何人</strong></h4>
<p>这就是开头说的一直不知道怎么弄的。前两天终于明白为什么有的 dropbox 用户可以获取到整个文件夹的外链链接分享给所有人，而有人就不行。问题的关键在于”<strong>enable_shmodel</strong>“，默认的 dropbox 账号是没有这种新的分享模式的(这种模式是后来增加的功能，这个功能出现之后注册的 dropbox 账号是否默认启用该模式，不是很清楚)</p>
<p>开启这种模式的方法很简单，访问这个链接即可 <a href="http://www.dropbox.com/enable_shmodel">http://www.dropbox.com/enable_shmodel</a>，之后就可以获取到 dropbox 下任意文件夹，任意文件的链接，方法是选择文件或文件夹菜单的 “Get Shareable Link”</p>
<p>获取到某个文件(夹)的链接之后，它就是可以被任何一个知道该链接的人访问的，如果不想这样分享了，在网页上选择 “Sharing” 选项卡，选择 “Linked Items”，然后点击要终止分享的条目的”Remove”，之后再访问之前该条目的分享链接就会得到一个 404页面。</p>
<p>更具体的说明，应该去看官方的文档<br />
<a href="http://www.dropbox.com/help/167">http://www.dropbox.com/help/167</a><br />
<h3 class='related_post_title'>相关日志:</h3>
<ul class='related_post'>
<li><a href='http://cfz.cc/essential_tools_in_my_mac.html' title='MAC OS X 软件推荐'>MAC OS X 软件推荐</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://cfz.cc/share_files_in_dropbox.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>搞不懂的事</title>
		<link>http://cfz.cc/something_make_me_confused.html</link>
		<comments>http://cfz.cc/something_make_me_confused.html#comments</comments>
		<pubDate>Fri, 04 Nov 2011 15:53:10 +0000</pubDate>
		<dc:creator>nirocfz</dc:creator>
				<category><![CDATA[Vim]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://cfz.cc/?p=280</guid>
		<description><![CDATA[<h2>问题</h2>
<p>最近才想起来在 Mac 上使用 vimrepress 这个插件来利用 vim 写博客，结果出现了意料之外的事情。<br />
给该插件的作者发邮件描述了一下情况，不论是用自己编译的字符界面 vim, 还是下载的编译好的 macvim, 在执行 vimrepress 的命令时 vim 都会退出。<br />
退出时给出的信息是:</p>
<blockquote>
<p>Vim: Caught deadly signal SEGV<br />
Vim: Finished.<br />
Segmentation fault: 11<br />
</p>
</blockquote>
<p>然而，说问题出在插件上，是不恰当的。插件作者给了一些答案，vimpress 命令都是通过 'exec' 映射的。在这个有问题的 vim 里直接输入:exec py都会退出。<br />
后来我想，可不可以编译一个 debug 版本的 vim 用 gdb 来跑一下，通过查看 vim 崩溃退出时的堆栈信息，尝试找一下问题到底出在哪。</p>
<h2>编译</h2>
<p>首先是搜索到了这个文档 <a href="http://vimdoc.sourceforge.net/htmldoc/debug.html">Vim documentation: debug</a>, 在开头部分就讲了如何用 gcc 编译, gdb 调试、定位崩溃的位置。<br />
按照文档里的做法，把 vim (macvim) 源码目录 src/Makefile 的文件做了一些修改，以自己目前手头上的文件为例，在该文件 544 行有注释，如果没有指定下面的两个编译标志，对于 gcc, 会默认使用 -O2 -g<br />
于是我去掉了后面第 545 行 'CFLAGS = -g' 的注释，这样编译时就只有一个 '-g' 标志，没有任何优化(没有 '-O2')</p>
<p>要做的第二处修改是在 1052 行，文档中说把这一行('STRIP = /bin/true')的注释去掉，strip 的作用是去掉程序的一些调试信息、符号表等内容(给程序减肥), 把这一行注释去掉，就不会把调试信息、符号去掉了，另外需要注意的是在 mac 系统里, 这一行后半部分这个路径还要改一下， true 的路径是 /usr/bin/true<br />
</p>
<p>编译 vim 的过程跟大多数的 unix/linux 工具的编译过程类似, configure, make, make install 的过程，需要重点关注的是 configure 的参数设置。</p>
<p>编译字符界面的 vim<br />
<code>./configure --with-features=huge --enable-cscope --enable-pythoninterp --enable-multibyte --disable-gui --prefix=/usr/local --enable-rubyinterp --enable-perlinterp --enable-tclinterp --enable-xim --enable-fontset</code></p>
<p>编译图形界面的 macvim<br />
<code>./configure --with-features=huge --enable-cscope --enable-pythoninterp --enable-multibyte --enable-rubyinterp --enable-perlinterp --enable-tclinterp --enable-xim</code></p>
<p>经过多次修改 Makefile 编译参数，启动 debug 版本和 release 版本查看状况，发现了搞不懂的事情。不过，最开始提到的 vim 崩溃退出的问题倒也不再出现了。</p>
<h2>比较 dirty 的解决办法</h2>
<p>鼓捣了半天，发现了个现象，如果修改 src/Makefile 第 540 多行那两个编译标志，使编译时使用了 '-O2'(是否有 '-g' 标志并不影响，是否让 strip 执行，更不会影响), 这样编译出来的 vim 回崩溃，而如果没有进行优化，比如只有一个 '-g' 标志，或者是指定 '-O0', 这样编译出来的版本，就不会出现执行 vimpress 命令会崩溃的情况。</p>
<p>现在是可以用 vim 来发布博客了，解决办法那是相当“不干净”的，并且留下个问题，<strong> 为什么 -O2 优化编译的版本会崩溃，而没有优化编译的版本就不会崩溃呢，'-O' 参数起到的具体作用(优化的细节)是什么？</strong> 而优化了的版本崩溃时的堆栈信息，我也没能分析出啥，这里是崩溃时的信息</p>
<pre><code>Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x0000000100000000
0x00000001003cbc58 in PyEval_EvalFrameEx ()
(gdb) bt
#0  0x00000001003cbc58 in PyEval_EvalFrameEx ()
#1  0x00000001003cecd8 in PyEval_EvalCodeEx ()
#2  0x000000010036cabf in PyClassMethod_New ()
#3  0x000000010034bd32 in PyObject_Call ()
#4  0x00000001003cc5ec in PyEval_EvalFrameEx ()
#5  0x00000001003cecd8 in PyEval_EvalCodeEx ()
#6  0x00000001003cee6c in PyEval_EvalCode ()
#7  0x00000001003cbe0a in PyEval_EvalFrameEx ()
#8  0x00000001003cecd8 in PyEval_EvalCodeEx ()
#9  0x000000010036cabf in PyClassMethod_New ()
#10 0x000000010034bd32 in PyObject_Call ()
#11 0x00000001003cc5ec in PyEval_EvalFrameEx ()
#12 0x00000001003cecd8 in PyEval_EvalCodeEx ()
#13 0x000000010036cabf in PyClassMethod_New ()
#14 0x000000010034bd32 in PyObject_Call ()
#15 0x00000001003cc5ec in PyEval_EvalFrameEx ()
#16 0x00000001003cecd8 in PyEval_EvalCodeEx ()
#17 0x00000001003cee6c in PyEval_EvalCode ()
#18 0x00000001003cbe0a in PyEval_EvalFrameEx ()
#19 0x00000001003cecd8 in PyEval_EvalCodeEx ()
#20 0x00000001003ced4d in PyEval_EvalCode ()
#21 0x00000001003e608f in Py_CompileString ()
#22 0x00000001003e621b in PyRun_StringFlags ()
#23 0x00000001003e70d0 in PyRun_SimpleStringFlags ()
#24 0x0000000100163495 in ?? ()
#25 0x00000001001635d6 in ?? ()
#26 0x000000010005df03 in ?? ()
#27 0x000000010003e84e in ?? ()
#28 0x000000010005df03 in ?? ()
#29 0x000000010005b0f9 in ?? ()
#30 0x000000010005deae in ?? ()
#31 0x00000001000c1575 in ?? ()
#32 0x00000001000cbde0 in ?? ()
#33 0x000000010017521c in ?? ()
#34 0x0000000100177f3b in ?? ()
#35 0x0000000100001c54 in ?? ()
</code></pre>
<p>以后熟悉了 python, 有时间再慢慢琢磨</p><!-- #VIMPRESS_TAG# http://cfz.cc/wordpress/wp-content/uploads/2011/11/vimpress_4eb40a81_mkd.txt vimpress_4eb40a81_mkd.txt -->]]></description>
			<content:encoded><![CDATA[<h2>问题</h2>
<p>最近才想起来在 Mac 上使用 vimrepress 这个插件来利用 vim 写博客，结果出现了意料之外的事情。<br />
给该插件的作者发邮件描述了一下情况，不论是用自己编译的字符界面 vim, 还是下载的编译好的 macvim, 在执行 vimrepress 的命令时 vim 都会退出。<br />
退出时给出的信息是:</p>
<blockquote>
<p>Vim: Caught deadly signal SEGV<br />
Vim: Finished.<br />
Segmentation fault: 11
</p>
</blockquote>
<p>然而，说问题出在插件上，是不恰当的。插件作者给了一些答案，vimpress 命令都是通过 &#8216;exec&#8217; 映射的。在这个有问题的 vim 里直接输入:exec py都会退出。<br />
后来我想，可不可以编译一个 debug 版本的 vim 用 gdb 来跑一下，通过查看 vim 崩溃退出时的堆栈信息，尝试找一下问题到底出在哪。</p>
<h2>编译</h2>
<p>首先是搜索到了这个文档 <a href="http://vimdoc.sourceforge.net/htmldoc/debug.html">Vim documentation: debug</a>, 在开头部分就讲了如何用 gcc 编译, gdb 调试、定位崩溃的位置。<br />
按照文档里的做法，把 vim (macvim) 源码目录 src/Makefile 的文件做了一些修改，以自己目前手头上的文件为例，在该文件 544 行有注释，如果没有指定下面的两个编译标志，对于 gcc, 会默认使用 -O2 -g<br />
于是我去掉了后面第 545 行 &#8216;CFLAGS = -g&#8217; 的注释，这样编译时就只有一个 &#8216;-g&#8217; 标志，没有任何优化(没有 &#8216;-O2&#8242;)</p>
<p>要做的第二处修改是在 1052 行，文档中说把这一行(&#8216;STRIP = /bin/true&#8217;)的注释去掉，strip 的作用是去掉程序的一些调试信息、符号表等内容(给程序减肥), 把这一行注释去掉，就不会把调试信息、符号去掉了，另外需要注意的是在 mac 系统里, 这一行后半部分这个路径还要改一下， true 的路径是 /usr/bin/true
</p>
<p>编译 vim 的过程跟大多数的 unix/linux 工具的编译过程类似, configure, make, make install 的过程，需要重点关注的是 configure 的参数设置。</p>
<p>编译字符界面的 vim<br />
<code>./configure --with-features=huge --enable-cscope --enable-pythoninterp --enable-multibyte --disable-gui --prefix=/usr/local --enable-rubyinterp --enable-perlinterp --enable-tclinterp --enable-xim --enable-fontset</code></p>
<p>编译图形界面的 macvim<br />
<code>./configure --with-features=huge --enable-cscope --enable-pythoninterp --enable-multibyte --enable-rubyinterp --enable-perlinterp --enable-tclinterp --enable-xim</code></p>
<p>经过多次修改 Makefile 编译参数，启动 debug 版本和 release 版本查看状况，发现了搞不懂的事情。不过，最开始提到的 vim 崩溃退出的问题倒也不再出现了。</p>
<h2>比较 dirty 的解决办法</h2>
<p>鼓捣了半天，发现了个现象，如果修改 src/Makefile 第 540 多行那两个编译标志，使编译时使用了 &#8216;-O2&#8242;(是否有 &#8216;-g&#8217; 标志并不影响，是否让 strip 执行，更不会影响), 这样编译出来的 vim 回崩溃，而如果没有进行优化，比如只有一个 &#8216;-g&#8217; 标志，或者是指定 &#8216;-O0&#8242;, 这样编译出来的版本，就不会出现执行 vimpress 命令会崩溃的情况。</p>
<p>现在是可以用 vim 来发布博客了，解决办法那是相当“不干净”的，并且留下个问题，<strong> 为什么 -O2 优化编译的版本会崩溃，而没有优化编译的版本就不会崩溃呢，&#8217;-O&#8217; 参数起到的具体作用(优化的细节)是什么？</strong> 而优化了的版本崩溃时的堆栈信息，我也没能分析出啥，这里是崩溃时的信息</p>
<pre><code>Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x0000000100000000
0x00000001003cbc58 in PyEval_EvalFrameEx ()
(gdb) bt
#0  0x00000001003cbc58 in PyEval_EvalFrameEx ()
#1  0x00000001003cecd8 in PyEval_EvalCodeEx ()
#2  0x000000010036cabf in PyClassMethod_New ()
#3  0x000000010034bd32 in PyObject_Call ()
#4  0x00000001003cc5ec in PyEval_EvalFrameEx ()
#5  0x00000001003cecd8 in PyEval_EvalCodeEx ()
#6  0x00000001003cee6c in PyEval_EvalCode ()
#7  0x00000001003cbe0a in PyEval_EvalFrameEx ()
#8  0x00000001003cecd8 in PyEval_EvalCodeEx ()
#9  0x000000010036cabf in PyClassMethod_New ()
#10 0x000000010034bd32 in PyObject_Call ()
#11 0x00000001003cc5ec in PyEval_EvalFrameEx ()
#12 0x00000001003cecd8 in PyEval_EvalCodeEx ()
#13 0x000000010036cabf in PyClassMethod_New ()
#14 0x000000010034bd32 in PyObject_Call ()
#15 0x00000001003cc5ec in PyEval_EvalFrameEx ()
#16 0x00000001003cecd8 in PyEval_EvalCodeEx ()
#17 0x00000001003cee6c in PyEval_EvalCode ()
#18 0x00000001003cbe0a in PyEval_EvalFrameEx ()
#19 0x00000001003cecd8 in PyEval_EvalCodeEx ()
#20 0x00000001003ced4d in PyEval_EvalCode ()
#21 0x00000001003e608f in Py_CompileString ()
#22 0x00000001003e621b in PyRun_StringFlags ()
#23 0x00000001003e70d0 in PyRun_SimpleStringFlags ()
#24 0x0000000100163495 in ?? ()
#25 0x00000001001635d6 in ?? ()
#26 0x000000010005df03 in ?? ()
#27 0x000000010003e84e in ?? ()
#28 0x000000010005df03 in ?? ()
#29 0x000000010005b0f9 in ?? ()
#30 0x000000010005deae in ?? ()
#31 0x00000001000c1575 in ?? ()
#32 0x00000001000cbde0 in ?? ()
#33 0x000000010017521c in ?? ()
#34 0x0000000100177f3b in ?? ()
#35 0x0000000100001c54 in ?? ()
</code></pre>
<p>以后熟悉了 python, 有时间再慢慢琢磨</p>
<p><!-- #VIMPRESS_TAG# http://cfz.cc/wordpress/wp-content/uploads/2011/11/vimpress_4eb40a81_mkd.txt vimpress_4eb40a81_mkd.txt --><br />
<h3 class='related_post_title'>相关日志:</h3>
<ul class='related_post'>
<li><a href='http://cfz.cc/essential_tools_in_my_mac.html' title='MAC OS X 软件推荐'>MAC OS X 软件推荐</a></li>
<li><a href='http://cfz.cc/use_vim_to_blog_markdown_syntax.html' title='用 vim 写 markdown 语法 发布博客'>用 vim 写 markdown 语法 发布博客</a></li>
<li><a href='http://cfz.cc/some_tips_recently_met.html' title='最近碰到小问题汇总'>最近碰到小问题汇总</a></li>
<li><a href='http://cfz.cc/some_useful_commands_in_vim.html' title='VIM 中的几个有用操作'>VIM 中的几个有用操作</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://cfz.cc/something_make_me_confused.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MAC OS X 软件推荐</title>
		<link>http://cfz.cc/essential_tools_in_my_mac.html</link>
		<comments>http://cfz.cc/essential_tools_in_my_mac.html#comments</comments>
		<pubDate>Thu, 03 Nov 2011 02:59:08 +0000</pubDate>
		<dc:creator>nirocfz</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[mplayer]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[vim]]></category>
		<category><![CDATA[工具]]></category>
		<category><![CDATA[软件]]></category>

		<guid isPermaLink="false">http://cfz.cc/?p=265</guid>
		<description><![CDATA[<h2>个人必备</h2>
在<a href="http://cfz.cc/essential_tools_in_my_windows.html">自家 windows 系统必备工具</a>里说到了那么几个必备的工具，主要是为了满足这几点:

1. 快速找到想要的文件

2. 快速打开想要的程序

3. 多重剪切板

在 mac 系统里，这几点是可以轻易满足的，<strong>spotlight</strong> 是可以满足上面的1、2两点的，还有一个很老牌的 <strong>QuickSliver</strong>,比spotlight功能强大。多重剪切板的功能，可以由 <strong>ClipMenu</strong> 满足，ClipMenu 的功能比 Ditto 弱一些(功能少一些)，但也绝对足够好用了。

另外, mac os x 上想用 vim, 办法有很多，针对图形界面的，可以直接下载 <strong>MacVim</strong>, 也可以下载源代码自己编译。对于终端的字符界面，系统本身自带一个 Vim, 如果你觉得这个 Vim 缺少一些功能(比如缺少 python 支持等)，可以自己去下源代码编译一个，注意编译参数，把自己想加的功能添加上去。

系统说到底是 unix, 所以这些从源码编译的事，在 mac os x 里是相当方便的，以前使用 linux 的经验，命令，基本都可以直接用到这里来。更神奇的事，就算对终端、字符界面这些东西一窍不通，仍然可以很好地用这个系统。

系统本身的终端，多少有些不方便，可以用 <strong>iTerm</strong> 作为一个代替，它支持多标签页，支持鼠标选中即复制，中键粘贴等等。

<hr />

<h2>日常工具</h2>
除了上面几个，正常地使用电脑来上网、听音乐、看电影、打游戏之类，还是需要的。自己去 mac app store 里按分类自己去找就可以了，有收费 app, 也有免费 app。如果想找收费 app 的破解版本, 小偷们自己去网上搜吧。其实大部分情况下，免费工具可以满足要求，列举或者说是记录下自己用的一些东西，并不一定是别人常用的。
<ul>
	<li>浏览器
<ul>
	<li>Google Chrome 多平台支持，同步，扩展……</li>
	<li>Safari 系统自带，性能很好，有时候用用</li>
	<li>Firefox 现在比较少用了</li>
</ul>
</li>
	<li>聊天
<ul>
	<li>QQ 功能足够，也不像 windows 版本那样大而笨重</li>
	<li>iChat 系统自带，支持多种协议</li>
	<li>Facetime 跟其他用苹果设备的人视频通话</li>
</ul>
</li>
	<li>视频播放
<ul>
	<li>MplayerX 首选，支持多种格式</li>
	<li>Mplayer OSX Extend 备选,看名字也知道，这两个都是 mplayer 的前端</li>
	<li>QuickTime + Perian 后者号称瑞士军刀，专门配给系统的QuickTime</li>
</ul>
</li>
	<li>音频播放
<ul>
	<li>iTunes 没什么好说</li>
	<li>VOX 小巧</li>
	<li>打开浏览器听电台吧</li>
</ul>
</li>
	<li>压缩/打包/解压
<ul>
	<li>The Unarchiver 免费解压工具，足够好用</li>
	<li>系统自带文件压缩(后端应该就是 tar )</li>
</ul>
</li>
	<li>下载工具
<ul>
	<li>uTorrent 首选BT工具</li>
	<li>Transmission 备选BT工具，因为有些PT站不允许用 mac 版 utorrent。用它BT下载个大文件时，第一次暂停，会假死一小段时间。</li>
	<li>mldonkey 自己编译个吧，在网页上进行查看、管理、配置</li>
	<li>wget 命令行工具，老牌，最有保证，功能非常多</li>
	<li>axel 命令行工具，多线程下载</li>
</ul>
</li>
	<li>软件包管理(命令行)
<ul>
	<li>homebrew 刚才提到的 wget, axel 等都可以通过 ‘brew install xxx’ 的命令来安装。</li>
</ul>
</li>
</ul>

<hr />

[caption id="" align="aligncenter" width="600" caption="开会"]<img title="have a meeting" src="https://lh6.googleusercontent.com/-1neFayXT0d4/TrHm8-FhUkI/AAAAAAAAAt0/2TFVULirU5k/s600/p1186868241.jpg" alt="这才叫开会" width="600" height="411" />[/caption]]]></description>
			<content:encoded><![CDATA[<h2>个人必备</h2>
<p>在<a href="http://cfz.cc/essential_tools_in_my_windows.html">自家 windows 系统必备工具</a>里说到了那么几个必备的工具，主要是为了满足这几点:</p>
<p>1. 快速找到想要的文件</p>
<p>2. 快速打开想要的程序</p>
<p>3. 多重剪切板</p>
<p>在 mac 系统里，这几点是可以轻易满足的，<strong>spotlight</strong> 是可以满足上面的1、2两点的，还有一个很老牌的 <strong>QuickSliver</strong>,比spotlight功能强大。多重剪切板的功能，可以由 <strong>ClipMenu</strong> 满足，ClipMenu 的功能比 Ditto 弱一些(功能少一些)，但也绝对足够好用了。</p>
<p>另外, mac os x 上想用 vim, 办法有很多，针对图形界面的，可以直接下载 <strong>MacVim</strong>, 也可以下载源代码自己编译。对于终端的字符界面，系统本身自带一个 Vim, 如果你觉得这个 Vim 缺少一些功能(比如缺少 python 支持等)，可以自己去下源代码编译一个，注意编译参数，把自己想加的功能添加上去。</p>
<p>系统说到底是 unix, 所以这些从源码编译的事，在 mac os x 里是相当方便的，以前使用 linux 的经验，命令，基本都可以直接用到这里来。更神奇的事，就算对终端、字符界面这些东西一窍不通，仍然可以很好地用这个系统。</p>
<p>系统本身的终端，多少有些不方便，可以用 <strong>iTerm</strong> 作为一个代替，它支持多标签页，支持鼠标选中即复制，中键粘贴等等。</p>
<hr />
<h2>日常工具</h2>
<p>除了上面几个，正常地使用电脑来上网、听音乐、看电影、打游戏之类，还是需要的。自己去 mac app store 里按分类自己去找就可以了，有收费 app, 也有免费 app。如果想找收费 app 的破解版本, 小偷们自己去网上搜吧。其实大部分情况下，免费工具可以满足要求，列举或者说是记录下自己用的一些东西，并不一定是别人常用的。</p>
<ul>
<li>浏览器
<ul>
<li>Google Chrome 多平台支持，同步，扩展……</li>
<li>Safari 系统自带，性能很好，有时候用用</li>
<li>Firefox 现在比较少用了</li>
</ul>
</li>
<li>聊天
<ul>
<li>QQ 功能足够，也不像 windows 版本那样大而笨重</li>
<li>iChat 系统自带，支持多种协议</li>
<li>Facetime 跟其他用苹果设备的人视频通话</li>
</ul>
</li>
<li>视频播放
<ul>
<li>MplayerX 首选，支持多种格式</li>
<li>Mplayer OSX Extend 备选,看名字也知道，这两个都是 mplayer 的前端</li>
<li>QuickTime + Perian 后者号称瑞士军刀，专门配给系统的QuickTime</li>
</ul>
</li>
<li>音频播放
<ul>
<li>iTunes 没什么好说</li>
<li>VOX 小巧</li>
<li>打开浏览器听电台吧</li>
</ul>
</li>
<li>压缩/打包/解压
<ul>
<li>The Unarchiver 免费解压工具，足够好用</li>
<li>系统自带文件压缩(后端应该就是 tar )</li>
</ul>
</li>
<li>下载工具
<ul>
<li>uTorrent 首选BT工具</li>
<li>Transmission 备选BT工具，因为有些PT站不允许用 mac 版 utorrent。用它BT下载个大文件时，第一次暂停，会假死一小段时间。</li>
<li>mldonkey 自己编译个吧，在网页上进行查看、管理、配置</li>
<li>wget 命令行工具，老牌，最有保证，功能非常多</li>
<li>axel 命令行工具，多线程下载</li>
</ul>
</li>
<li>软件包管理(命令行)
<ul>
<li>homebrew 刚才提到的 wget, axel 等都可以通过 ‘brew install xxx’ 的命令来安装。</li>
</ul>
</li>
</ul>
<hr />
<p><div class="wp-caption aligncenter" style="width: 610px"><img title="have a meeting" src="https://lh6.googleusercontent.com/-1neFayXT0d4/TrHm8-FhUkI/AAAAAAAAAt0/2TFVULirU5k/s600/p1186868241.jpg" alt="这才叫开会" width="600" height="411" /><p class="wp-caption-text">开会</p></div><br />
<h3 class='related_post_title'>相关日志:</h3>
<ul class='related_post'>
<li><a href='http://cfz.cc/some_tips_recently_met.html' title='最近碰到小问题汇总'>最近碰到小问题汇总</a></li>
<li><a href='http://cfz.cc/something_make_me_confused.html' title='搞不懂的事'>搞不懂的事</a></li>
<li><a href='http://cfz.cc/some_useful_commands_in_vim.html' title='VIM 中的几个有用操作'>VIM 中的几个有用操作</a></li>
<li><a href='http://cfz.cc/share_files_in_dropbox.html' title='Dropbox 各种分享文件的方式'>Dropbox 各种分享文件的方式</a></li>
<li><a href='http://cfz.cc/essential_tools_in_my_windows.html' title='自家 windows 系统必备工具'>自家 windows 系统必备工具</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://cfz.cc/essential_tools_in_my_mac.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C 和 Python 实现二分查找算法</title>
		<link>http://cfz.cc/binary_search_in_c_and_python.html</link>
		<comments>http://cfz.cc/binary_search_in_c_and_python.html#comments</comments>
		<pubDate>Sun, 25 Sep 2011 13:59:11 +0000</pubDate>
		<dc:creator>nirocfz</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://chy.cc/?p=233</guid>
		<description><![CDATA[<p>主要目的为熟悉一下 Python 语法，用 C 的代码跟 Python 的进行一下对比，代码用起来还行，并不是很严谨。下面是对二分查找算法本身的一点介绍。
二分查找算法在维基百科中的描述：</p>

<blockquote>
  <p>在一个有序的集合中查找元素，可以使用二分查找算法，也叫二分搜索。
二分查找算法先比较位于集合中间位置的元素与键的大小，有三种情况（假设集合是从小到大排列的）：
1.键小于中间位置的元素，则匹配元素必在左边（如果有的话），于是对左边的区域应用二分搜索。
2.键等于中间位置的元素，所以元素找到。
3.键大于中间位置的元素，则匹配元素必在右边（如果有的话），于是对右边的区域应用二分搜索。
另外，当集合为空，则代表找不到。</p>
</blockquote>

<p>先上 C 语言的版本</p>
<pre lang="c" line="1">
int binsearch(int *a, int n, int x)
{
    int low = 0;
    int high = n - 1;
    int mid = (low + high) / 2;

    while (a[mid] != x &#038;& low < high) {
        if (a[mid] > x)
            high = mid - 1;
        else
            low = mid + 1;

        mid = (low + high) / 2;
    }
    
    return a[mid] == x ? mid : -1;
}

</pre>
<p>然后是 Python 的代码</p>
<pre lang="python" line="1">
def binsearch(array, x):
    high = len(array) - 1
    low = 0
    mid = (high + low) / 2
    while array[mid] != x and low < high:
        if array[mid] > x:
            high = mid - 1
        else:
            low = mid + 1

        mid = (high + low) / 2
    
    return mid if array[mid] == x else -1

</pre>
<p>总结一下上面用到的需要记住的 Python 知识点：</p>

<ul>
<li>len(array) 返回序列array(或元组、字典)的长度</li>
<li>while 循环语句的多个判断条件，中间由 and 连接起来，Python 的逻辑运算符有 and, or, not (对应 C 语言中得 '&#38;&#38;', '&#124;&#124;', '!')</li>
<li>最后一句类似于 C 语言中的 xxx?xxx:xxx 这种形式的语句，跟上面 C 语言代码的最后一行语句的作用相同。满足条件返回 if 前面的值，否则返回 else 后面的值</li>
</ul>

<p>最后说一句，现在用的没经过修改的 wp_syntax 出来的代码效果真不好看……</p>]]></description>
			<content:encoded><![CDATA[<p>主要目的为熟悉一下 Python 语法，用 C 的代码跟 Python 的进行一下对比，代码用起来还行，并不是很严谨。下面是对二分查找算法本身的一点介绍。<br />
二分查找算法在维基百科中的描述：</p>
<blockquote>
<p>在一个有序的集合中查找元素，可以使用二分查找算法，也叫二分搜索。<br />
二分查找算法先比较位于集合中间位置的元素与键的大小，有三种情况（假设集合是从小到大排列的）：<br />
1.键小于中间位置的元素，则匹配元素必在左边（如果有的话），于是对左边的区域应用二分搜索。<br />
2.键等于中间位置的元素，所以元素找到。<br />
3.键大于中间位置的元素，则匹配元素必在右边（如果有的话），于是对右边的区域应用二分搜索。<br />
另外，当集合为空，则代表找不到。</p>
</blockquote>
<p>先上 C 语言的版本</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> binsearch<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> <span style="color: #339933;">*</span>a<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> n<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> x<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> low <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> high <span style="color: #339933;">=</span> n <span style="color: #339933;">-</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> mid <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>low <span style="color: #339933;">+</span> high<span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> <span style="color: #0000dd;">2</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#91;</span>mid<span style="color: #009900;">&#93;</span> <span style="color: #339933;">!=</span> x <span style="color: #339933;">&amp;&amp;</span> low <span style="color: #339933;">&lt;</span> high<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#91;</span>mid<span style="color: #009900;">&#93;</span> <span style="color: #339933;">&gt;</span> x<span style="color: #009900;">&#41;</span>
            high <span style="color: #339933;">=</span> mid <span style="color: #339933;">-</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">else</span>
            low <span style="color: #339933;">=</span> mid <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
&nbsp;
        mid <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>low <span style="color: #339933;">+</span> high<span style="color: #009900;">&#41;</span> <span style="color: #339933;">/</span> <span style="color: #0000dd;">2</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> a<span style="color: #009900;">&#91;</span>mid<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> x <span style="color: #339933;">?</span> mid <span style="color: #339933;">:</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>然后是 Python 的代码</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> binsearch<span style="color: black;">&#40;</span><span style="color: #dc143c;">array</span>, x<span style="color: black;">&#41;</span>:
    high = <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">array</span><span style="color: black;">&#41;</span> - <span style="color: #ff4500;">1</span>
    low = <span style="color: #ff4500;">0</span>
    mid = <span style="color: black;">&#40;</span>high + low<span style="color: black;">&#41;</span> / <span style="color: #ff4500;">2</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #dc143c;">array</span><span style="color: black;">&#91;</span>mid<span style="color: black;">&#93;</span> <span style="color: #66cc66;">!</span>= x <span style="color: #ff7700;font-weight:bold;">and</span> low <span style="color: #66cc66;">&lt;</span> high:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">array</span><span style="color: black;">&#91;</span>mid<span style="color: black;">&#93;</span> <span style="color: #66cc66;">&gt;</span> x:
            high = mid - <span style="color: #ff4500;">1</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            low = mid + <span style="color: #ff4500;">1</span>
&nbsp;
        mid = <span style="color: black;">&#40;</span>high + low<span style="color: black;">&#41;</span> / <span style="color: #ff4500;">2</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> mid <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">array</span><span style="color: black;">&#91;</span>mid<span style="color: black;">&#93;</span> == x <span style="color: #ff7700;font-weight:bold;">else</span> -<span style="color: #ff4500;">1</span></pre></td></tr></table></div>

<p>总结一下上面用到的需要记住的 Python 知识点：</p>
<ul>
<li>len(array) 返回序列array(或元组、字典)的长度</li>
<li>while 循环语句的多个判断条件，中间由 and 连接起来，Python 的逻辑运算符有 and, or, not (对应 C 语言中得 &#8216;&amp;&amp;&#8217;, &#8216;||&#8217;, &#8216;!&#8217;)</li>
<li>最后一句类似于 C 语言中的 xxx?xxx:xxx 这种形式的语句，跟上面 C 语言代码的最后一行语句的作用相同。满足条件返回 if 前面的值，否则返回 else 后面的值</li>
</ul>
<p>最后说一句，现在用的没经过修改的 wp_syntax 出来的代码效果真不好看……</p>
<h3 class='related_post_title'>相关日志:</h3>
<ul class='related_post'>
<li><a href='http://cfz.cc/variable_argument_list_in_c.html' title='C 语言可变长参数'>C 语言可变长参数</a></li>
<li><a href='http://cfz.cc/plan_of_reading_programming_books.html' title='读书计划 &#8211; 编程技术'>读书计划 &#8211; 编程技术</a></li>
<li><a href='http://cfz.cc/high_low_byte_order.html' title='高字节序和低字节序'>高字节序和低字节序</a></li>
<li><a href='http://cfz.cc/use_of_typedef.html' title='typedef的用法'>typedef的用法</a></li>
<li><a href='http://cfz.cc/array_pointer.html' title='指针数组和数组指针'>指针数组和数组指针</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://cfz.cc/binary_search_in_c_and_python.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C 语言可变长参数</title>
		<link>http://cfz.cc/variable_argument_list_in_c.html</link>
		<comments>http://cfz.cc/variable_argument_list_in_c.html#comments</comments>
		<pubDate>Sun, 11 Sep 2011 16:07:25 +0000</pubDate>
		<dc:creator>nirocfz</dc:creator>
				<category><![CDATA[编程]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[字节]]></category>
		<category><![CDATA[学习]]></category>
		<category><![CDATA[数据结构]]></category>

		<guid isPermaLink="false">http://chy.cc/?p=185</guid>
		<description><![CDATA[printf 函数可能是学C语言遇到的第一个函数，这必然是可以接收变长参数的函数，才可以被用来 printf("Hello World!\n"), 被用来 printf("%d\n", n) …… 在可变长参数的函数实现中，有几个宏是很重要的， va_start, va_arg, va_end.

在 redis 的代码中，看到了一段用来写日志的可接受变长参数的函数的实现，代码还是比较简单的，实现的重点在代码的 15 ~ 17 这三行
<!--more-->
<pre lang="c" line="1">
void redisLog(int level, const char *fmt, ...) {
    const int syslogLevelMap[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_WARNING };
    const char *c = ".-*#";
    time_t now = time(NULL);
    va_list ap;
    FILE *fp;
    char buf[64];
    char msg[REDIS_MAX_LOGMSG_LEN];

    if (level &#60; server.verbosity) return;

    fp = (server.logfile == NULL) ? stdout : fopen(server.logfile,"a");
    if (!fp) return;

    va_start(ap, fmt);
    vsnprintf(msg, sizeof(msg), fmt, ap);
    va_end(ap);

    strftime(buf,sizeof(buf),"%d %b %H:%M:%S",localtime(&#38;now));
    fprintf(fp,"[%d] %s %c %s\n",(int)getpid(),buf,c[level],msg);
    fflush(fp);

    if (server.logfile) fclose(fp);

    if (server.syslog_enabled) syslog(syslogLevelMap[level], "%s", msg);
}</pre>


在上面 redis 的代码中，用到了 va_start, vsnprintf, va_end， 一般的实现应该是 va_start 和 va_end 是宏，vsnprintf 是一个函数。

在描述这几个宏或者函数的作用之前，有必要知道一下函数的参数传递的方式。调用一个函数时，传递若干参数，在正常情况下，按照代码中参数的顺序从右到左依次入栈。

要实现可以接收变长的参数，问题就是怎样确定这些参数的地址。像上面 redis 的代码中，在栈顶的参数也就是第一个参数 level 的地址是可以确定的，第二个参数 fmt 的地址同样可以确定，在 fmt 之后，是不确定的参数，如果跳过 fmt 变量占用的空间大小，就知道了第三个参数，再跳过第三个参数……下面开始说下真正的实现的方法原理。

va_start 宏的实现如下
<pre lang="c">#define va_start(ap,v)  (ap = (va_list)&#038;v + _INTSIZEOF(v))</pre>
va_start(ap, fmt) 这行代码就是把 fmt 作为可变长参数的“头”，可变长参数的列表通过 ap 来获取，va_list 实际只是一个普通的指针，获取 fmt 之后的参数，就是要开始“跳”。

vsnprintf 函数类似于 snprintf, 把指定最多 sizeof(msg) 大小的内容输出到 msg 的那块空间里去，内容的格式由 fmt 控制，具体内容是由 ap 变量决定。在这个函数里需要实现这样的功能：1.知道 fmt 后面有多少参数，2.知道这些参数的类型是什么。这样才能知道每次跳多少才能得到正确的参数，并且要知道跳到什么时候是个头，千万不要越界。

一开始学C语言的时候，被告知 printf 的格式里， %d 表示整型， %s 表示字符串，%c 表示单个字符…… 稍微动下脑子应该知道为啥要有这么些个“规矩”了，有了这样一个协议，就可以通过分析 fmt 这个字符串中的 'd', 's', 'c', 'f' 等等字符(或者更复杂的 %.3f 这种格式)去很好的实现前面说到的两个功能。

根据得到的参数个数，然后是一个循环，每次循环就是取到一个参数，跳过这个参数，对取到的参数进行处理。在 C语言的实现中， va_arg 这个宏是专门来取这个参数并跳过这个参数的，它的实现(之一)是：
<pre lang="c">#define va_arg(ap,t) (*(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))</pre>
ap就是参数列表的地址， t 是参数的类型(int, double等)。上面的宏定义看上去怪怪的，乍看上去好像加了又减同一个值，稍微仔细看下就明白了。当前参数的地址其实就是 ap 当前指的地址，同时这个宏把 ap 的地址加上了 t 类型的大小，也就是跳过了当前参数到了下一个参数。

就这样，printf 函数的实现，或者上面 redis 这一部分代码的实现，应该了然了。

最后，还有 va_end 这个宏，上面已经把工作全做完了，va_end 是干嘛用的？实际上在一些 C语言实现中，这个宏就是几乎什么都不做的
<pre lang="c">#define va_end(ap) (ap = (va_list)0)</pre>
《C缺陷与陷阱》里有一段
<blockquote>在大多数C实现上，调用va_end与否并无区别。但是，某些版本的va_start宏为了方便对va_list的遍历，就给参数列表动态分配内存。
这样一种C实现很可能利用va_end宏来释放此前动态分配的内存。如果忘记调用宏va_end，最后得到的程序可能在某些机型上没有问题，而在另一些机型上则发生“内存泄露”。</blockquote>


最后一点，上面碰到的INISIZEOF这个宏的定义：
#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) - 1) &#38; ~(sizeof(int) - 1))
这个宏让“跳”的幅度都是4的倍数(或者8，不同平台结果不一样)，至于原因，涉及到参数传递时类型的自动提升，“栈帧”的大小，可以看这里http://hi.baidu.com/xyk34/blog/item/b4fd61351e63b50391ef3915.html

参考内容：
<a title="也谈C语言变长参数" href="http://bigwhite.blogbus.com/logs/20468193.html" target="_blank">也谈C语言变长参数</a>
<a title="可变长参数列表误区与陷阱——va_arg不可接受的类型" href="http://www.cppblog.com/ownwaterloo/archive/2009/04/21/unacceptable_type_in_va_arg.html" target="_blank">可变长参数列表误区与陷阱——va_arg不可接受的类型</a>
<a title="可变长参数列表误区与陷阱——va_end是必须的吗？" href="http://www.cppblog.com/ownwaterloo/archive/2009/04/21/is_va_end_necessary.html" target="_blank">可变长参数列表误区与陷阱——va_end是必须的吗？</a>
<a title="C语言中变长参数中的一个有趣的现象。关于默认参数提升" href="http://hi.baidu.com/xyk34/blog/item/b4fd61351e63b50391ef3915.html" target="_blank">C语言中变长参数中的一个有趣的现象。关于默认参数提升</a>]]></description>
			<content:encoded><![CDATA[<p>printf 函数可能是学C语言遇到的第一个函数，这必然是可以接收变长参数的函数，才可以被用来 printf(“Hello World!\n”), 被用来 printf(“%d\n”, n) …… 在可变长参数的函数实现中，有几个宏是很重要的， va_start, va_arg, va_end.</p>
<p>在 redis 的代码中，看到了一段用来写日志的可接受变长参数的函数的实现，代码还是比较简单的，实现的重点在代码的 15 ~ 17 这三行<br />
<span id="more-185"></span></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">void</span> redisLog<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> level<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>fmt<span style="color: #339933;">,</span> ...<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">const</span> <span style="color: #993333;">int</span> syslogLevelMap<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> LOG_DEBUG<span style="color: #339933;">,</span> LOG_INFO<span style="color: #339933;">,</span> LOG_NOTICE<span style="color: #339933;">,</span> LOG_WARNING <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>c <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;.-*#&quot;</span><span style="color: #339933;">;</span>
    time_t now <span style="color: #339933;">=</span> time<span style="color: #009900;">&#40;</span>NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    va_list ap<span style="color: #339933;">;</span>
    FILE <span style="color: #339933;">*</span>fp<span style="color: #339933;">;</span>
    <span style="color: #993333;">char</span> buf<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">64</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">char</span> msg<span style="color: #009900;">&#91;</span>REDIS_MAX_LOGMSG_LEN<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>level <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> server.<span style="color: #202020;">verbosity</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
&nbsp;
    fp <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>server.<span style="color: #202020;">logfile</span> <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> stdout <span style="color: #339933;">:</span> fopen<span style="color: #009900;">&#40;</span>server.<span style="color: #202020;">logfile</span><span style="color: #339933;">,</span><span style="color: #ff0000;">&quot;a&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>fp<span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
&nbsp;
    va_start<span style="color: #009900;">&#40;</span>ap<span style="color: #339933;">,</span> fmt<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    vsnprintf<span style="color: #009900;">&#40;</span>msg<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>msg<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> fmt<span style="color: #339933;">,</span> ap<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    va_end<span style="color: #009900;">&#40;</span>ap<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    strftime<span style="color: #009900;">&#40;</span>buf<span style="color: #339933;">,</span><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #ff0000;">&quot;%d %b %H:%M:%S&quot;</span><span style="color: #339933;">,</span>localtime<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;</span>now<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    fprintf<span style="color: #009900;">&#40;</span>fp<span style="color: #339933;">,</span><span style="color: #ff0000;">&quot;[%d] %s %c %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span>getpid<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>buf<span style="color: #339933;">,</span>c<span style="color: #009900;">&#91;</span>level<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>msg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    fflush<span style="color: #009900;">&#40;</span>fp<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>server.<span style="color: #202020;">logfile</span><span style="color: #009900;">&#41;</span> fclose<span style="color: #009900;">&#40;</span>fp<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>server.<span style="color: #202020;">syslog_enabled</span><span style="color: #009900;">&#41;</span> syslog<span style="color: #009900;">&#40;</span>syslogLevelMap<span style="color: #009900;">&#91;</span>level<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;%s&quot;</span><span style="color: #339933;">,</span> msg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>在上面 redis 的代码中，用到了 va_start, vsnprintf, va_end， 一般的实现应该是 va_start 和 va_end 是宏，vsnprintf 是一个函数。</p>
<p>在描述这几个宏或者函数的作用之前，有必要知道一下函数的参数传递的方式。调用一个函数时，传递若干参数，在正常情况下，按照代码中参数的顺序从右到左依次入栈。</p>
<p>要实现可以接收变长的参数，问题就是怎样确定这些参数的地址。像上面 redis 的代码中，在栈顶的参数也就是第一个参数 level 的地址是可以确定的，第二个参数 fmt 的地址同样可以确定，在 fmt 之后，是不确定的参数，如果跳过 fmt 变量占用的空间大小，就知道了第三个参数，再跳过第三个参数……下面开始说下真正的实现的方法原理。</p>
<p>va_start 宏的实现如下</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define va_start(ap,v)  (ap = (va_list)&amp;v + _INTSIZEOF(v))</span></pre></div></div>

<p>va_start(ap, fmt) 这行代码就是把 fmt 作为可变长参数的“头”，可变长参数的列表通过 ap 来获取，va_list 实际只是一个普通的指针，获取 fmt 之后的参数，就是要开始“跳”。</p>
<p>vsnprintf 函数类似于 snprintf, 把指定最多 sizeof(msg) 大小的内容输出到 msg 的那块空间里去，内容的格式由 fmt 控制，具体内容是由 ap 变量决定。在这个函数里需要实现这样的功能：1.知道 fmt 后面有多少参数，2.知道这些参数的类型是什么。这样才能知道每次跳多少才能得到正确的参数，并且要知道跳到什么时候是个头，千万不要越界。</p>
<p>一开始学C语言的时候，被告知 printf 的格式里， %d 表示整型， %s 表示字符串，%c 表示单个字符…… 稍微动下脑子应该知道为啥要有这么些个“规矩”了，有了这样一个协议，就可以通过分析 fmt 这个字符串中的 &#8216;d&#8217;, &#8216;s&#8217;, &#8216;c&#8217;, &#8216;f&#8217; 等等字符(或者更复杂的 %.3f 这种格式)去很好的实现前面说到的两个功能。</p>
<p>根据得到的参数个数，然后是一个循环，每次循环就是取到一个参数，跳过这个参数，对取到的参数进行处理。在 C语言的实现中， va_arg 这个宏是专门来取这个参数并跳过这个参数的，它的实现(之一)是：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define va_arg(ap,t) (*(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))</span></pre></div></div>

<p>ap就是参数列表的地址， t 是参数的类型(int, double等)。上面的宏定义看上去怪怪的，乍看上去好像加了又减同一个值，稍微仔细看下就明白了。当前参数的地址其实就是 ap 当前指的地址，同时这个宏把 ap 的地址加上了 t 类型的大小，也就是跳过了当前参数到了下一个参数。</p>
<p>就这样，printf 函数的实现，或者上面 redis 这一部分代码的实现，应该了然了。</p>
<p>最后，还有 va_end 这个宏，上面已经把工作全做完了，va_end 是干嘛用的？实际上在一些 C语言实现中，这个宏就是几乎什么都不做的</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define va_end(ap) (ap = (va_list)0)</span></pre></div></div>

<p>《C缺陷与陷阱》里有一段</p>
<blockquote><p>在大多数C实现上，调用va_end与否并无区别。但是，某些版本的va_start宏为了方便对va_list的遍历，就给参数列表动态分配内存。<br />
这样一种C实现很可能利用va_end宏来释放此前动态分配的内存。如果忘记调用宏va_end，最后得到的程序可能在某些机型上没有问题，而在另一些机型上则发生“内存泄露”。</p></blockquote>
<p>最后一点，上面碰到的INISIZEOF这个宏的定义：<br />
#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) &#8211; 1) &amp; ~(sizeof(int) &#8211; 1))<br />
这个宏让“跳”的幅度都是4的倍数(或者8，不同平台结果不一样)，至于原因，涉及到参数传递时类型的自动提升，“栈帧”的大小，可以看这里http://hi.baidu.com/xyk34/blog/item/b4fd61351e63b50391ef3915.html</p>
<p>参考内容：<br />
<a title="也谈C语言变长参数" href="http://bigwhite.blogbus.com/logs/20468193.html" target="_blank">也谈C语言变长参数</a><br />
<a title="可变长参数列表误区与陷阱——va_arg不可接受的类型" href="http://www.cppblog.com/ownwaterloo/archive/2009/04/21/unacceptable_type_in_va_arg.html" target="_blank">可变长参数列表误区与陷阱——va_arg不可接受的类型</a><br />
<a title="可变长参数列表误区与陷阱——va_end是必须的吗？" href="http://www.cppblog.com/ownwaterloo/archive/2009/04/21/is_va_end_necessary.html" target="_blank">可变长参数列表误区与陷阱——va_end是必须的吗？</a><br />
<a title="C语言中变长参数中的一个有趣的现象。关于默认参数提升" href="http://hi.baidu.com/xyk34/blog/item/b4fd61351e63b50391ef3915.html" target="_blank">C语言中变长参数中的一个有趣的现象。关于默认参数提升</a><br />
<h3 class='related_post_title'>相关日志:</h3>
<ul class='related_post'>
<li><a href='http://cfz.cc/high_low_byte_order.html' title='高字节序和低字节序'>高字节序和低字节序</a></li>
<li><a href='http://cfz.cc/plan_of_reading_programming_books.html' title='读书计划 &#8211; 编程技术'>读书计划 &#8211; 编程技术</a></li>
<li><a href='http://cfz.cc/use_of_typedef.html' title='typedef的用法'>typedef的用法</a></li>
<li><a href='http://cfz.cc/array_pointer.html' title='指针数组和数组指针'>指针数组和数组指针</a></li>
<li><a href='http://cfz.cc/binary_search_in_c_and_python.html' title='C 和 Python 实现二分查找算法'>C 和 Python 实现二分查找算法</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://cfz.cc/variable_argument_list_in_c.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>……</title>
		<link>http://cfz.cc/147.html</link>
		<comments>http://cfz.cc/147.html#comments</comments>
		<pubDate>Fri, 09 Sep 2011 17:36:08 +0000</pubDate>
		<dc:creator>nirocfz</dc:creator>
				<category><![CDATA[扯淡……]]></category>

		<guid isPermaLink="false">http://chy.cc/?p=147</guid>
		<description><![CDATA[上面几条，其实就是为了看下 twenty eleven 这个主题对发布文章时可选的各种“形式”]]></description>
			<content:encoded><![CDATA[<p>上面几条，其实就是为了看下 twenty eleven 这个主题对发布文章时可选的各种“形式”<br />
<h3 class='related_post_title'>相关日志:</h3>
<ul class='related_post'>
<li>没有相关日志</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://cfz.cc/147.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>两张电影截图</title>
		<link>http://cfz.cc/two_movie_snapshots.html</link>
		<comments>http://cfz.cc/two_movie_snapshots.html#comments</comments>
		<pubDate>Fri, 09 Sep 2011 17:21:23 +0000</pubDate>
		<dc:creator>nirocfz</dc:creator>
				<category><![CDATA[电影]]></category>

		<guid isPermaLink="false">http://chy.cc/?p=138</guid>
		<description><![CDATA[<p style="text-align: center;"><img class="aligncenter" title="在布鲁日" src="https://lh3.googleusercontent.com/-8J7LliBOqxA/TmS0a2xbDsI/AAAAAAAAAtE/D36KausjKIs/snapshot20110905192517.jpg" alt="字幕亮点，“伏地魔”卖萌" width="512" height="213" /><img class="aligncenter" title="X战警 第一战" src="https://lh5.googleusercontent.com/-WqCBiHRR2Vg/Tl0EKMLPHJI/AAAAAAAAAso/XK-zN4pJX4E/s912/snapshot20110830233731.jpg" alt="“金刚狼”打酱油" width="512" height="218" /></p>]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><img class="aligncenter" title="在布鲁日" src="https://lh3.googleusercontent.com/-8J7LliBOqxA/TmS0a2xbDsI/AAAAAAAAAtE/D36KausjKIs/snapshot20110905192517.jpg" alt="字幕亮点，“伏地魔”卖萌" width="512" height="213" /><img class="aligncenter" title="X战警 第一战" src="https://lh5.googleusercontent.com/-WqCBiHRR2Vg/Tl0EKMLPHJI/AAAAAAAAAso/XK-zN4pJX4E/s912/snapshot20110830233731.jpg" alt="“金刚狼”打酱油" width="512" height="218" /></p>
<h3 class='related_post_title'>相关日志:</h3>
<ul class='related_post'>
<li>没有相关日志</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://cfz.cc/two_movie_snapshots.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>孤胆特工……</title>
		<link>http://cfz.cc/the_man_from_nowhere.html</link>
		<comments>http://cfz.cc/the_man_from_nowhere.html#comments</comments>
		<pubDate>Fri, 09 Sep 2011 15:57:22 +0000</pubDate>
		<dc:creator>nirocfz</dc:creator>
				<category><![CDATA[扯淡……]]></category>
		<category><![CDATA[电影]]></category>

		<guid isPermaLink="false">http://chy.cc/?p=127</guid>
		<description><![CDATA[韩国版的《这个杀手不太冷》，也就是《大叔》，去年的片子，这个月要在中国大陆上映了，“汉化版”片名《孤胆特工》……]]></description>
			<content:encoded><![CDATA[<p>韩国版的《这个杀手不太冷》，也就是《大叔》，去年的片子，这个月要在中国大陆上映了，“汉化版”片名《孤胆特工》……<br />
<h3 class='related_post_title'>相关日志:</h3>
<ul class='related_post'>
<li>没有相关日志</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://cfz.cc/the_man_from_nowhere.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>自家 windows 系统必备工具</title>
		<link>http://cfz.cc/essential_tools_in_my_windows.html</link>
		<comments>http://cfz.cc/essential_tools_in_my_windows.html#comments</comments>
		<pubDate>Thu, 08 Sep 2011 13:01:18 +0000</pubDate>
		<dc:creator>nirocfz</dc:creator>
				<category><![CDATA[乱七八糟]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[发牢骚]]></category>
		<category><![CDATA[工具]]></category>

		<guid isPermaLink="false">http://cfz.cc/?p=94</guid>
		<description><![CDATA[自己办公用的windows系统的必备工具

&#160;

1. <a title="everything" href="http://www.voidtools.com/" target="_blank">everything</a>

瞬间从整个硬盘搜索到要找的文件，只支持 NTFS 格式分区，可以设置排除某个分区。可以用来在本机开 FTP, HTTP 服务(一般来说应该是方便共享)

&#160;

2. <a title="launchy" href="http://www.launchy.net/" target="_blank">lanuchy</a>

索引快捷方式，输入软件名称的若干字符，就能找到并打开该软件，推荐“<a title="launchy 中文修改版" href="http://code.google.com/p/launchy-chinese/" target="_blank">中文修改版</a>”，支持拼音，例如打开“谷歌浏览器”，输入 "guge" 可以识别到。另外具有记忆功能，用的时间长些，就更能感觉到方便。

&#160;

3. <a title="ditto" href="http://ditto-cp.sourceforge.net/" target="_blank">ditto</a>

没有多重剪贴板的系统真是弱爆了，复制，切换程序，粘贴，复制，切换程序，粘贴……这种方法弱智极了，在没有其他方便、高级的办法(专用工具，自己写脚本等等)的情况下，复制，复制，复制，复制……切换程序， 粘贴，粘贴，粘贴……这才是高效的好办法。

&#160;

另外， vim(gvim),  cygwin 必备！

另外，不让上网，啥都搞不来，给你用啥，你就用啥！！

另外，不让上网的公司，天天开会的公司……不做评价！！！]]></description>
			<content:encoded><![CDATA[<p>自己办公用的windows系统的必备工具</p>
<p>&nbsp;</p>
<p>1. <a title="everything" href="http://www.voidtools.com/" target="_blank">everything</a></p>
<p>瞬间从整个硬盘搜索到要找的文件，只支持 NTFS 格式分区，可以设置排除某个分区。可以用来在本机开 FTP, HTTP 服务(一般来说应该是方便共享)</p>
<p>&nbsp;</p>
<p>2. <a title="launchy" href="http://www.launchy.net/" target="_blank">lanuchy</a></p>
<p>索引快捷方式，输入软件名称的若干字符，就能找到并打开该软件，推荐“<a title="launchy 中文修改版" href="http://code.google.com/p/launchy-chinese/" target="_blank">中文修改版</a>”，支持拼音，例如打开“谷歌浏览器”，输入 “guge” 可以识别到。另外具有记忆功能，用的时间长些，就更能感觉到方便。</p>
<p>&nbsp;</p>
<p>3. <a title="ditto" href="http://ditto-cp.sourceforge.net/" target="_blank">ditto</a></p>
<p>没有多重剪贴板的系统真是弱爆了，复制，切换程序，粘贴，复制，切换程序，粘贴……这种方法弱智极了，在没有其他方便、高级的办法(专用工具，自己写脚本等等)的情况下，复制，复制，复制，复制……切换程序， 粘贴，粘贴，粘贴……这才是高效的好办法。</p>
<p>&nbsp;</p>
<p>另外， vim(gvim),  cygwin 必备！</p>
<p>另外，不让上网，啥都搞不来，给你用啥，你就用啥！！</p>
<p>另外，不让上网的公司，天天开会的公司……不做评价！！！<br />
<h3 class='related_post_title'>相关日志:</h3>
<ul class='related_post'>
<li><a href='http://cfz.cc/essential_tools_in_my_mac.html' title='MAC OS X 软件推荐'>MAC OS X 软件推荐</a></li>
<li><a href='http://cfz.cc/some_tips_recently_met.html' title='最近碰到小问题汇总'>最近碰到小问题汇总</a></li>
<li><a href='http://cfz.cc/linux_shell_audio_video_convert.html' title='Linux 终端下音视频简单转换、合并等处理'>Linux 终端下音视频简单转换、合并等处理</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://cfz.cc/essential_tools_in_my_windows.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>最近碰到小问题汇总</title>
		<link>http://cfz.cc/some_tips_recently_met.html</link>
		<comments>http://cfz.cc/some_tips_recently_met.html#comments</comments>
		<pubDate>Sat, 30 Jul 2011 03:36:24 +0000</pubDate>
		<dc:creator>nirocfz</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[怪东西]]></category>
		<category><![CDATA[ffmpeg]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mplayer]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[vim]]></category>
		<category><![CDATA[工具]]></category>
		<category><![CDATA[视频]]></category>
		<category><![CDATA[音频]]></category>

		<guid isPermaLink="false">http://cfz.cc/?p=67</guid>
		<description><![CDATA[<p>记录、备份之</p>

<h3>Cygwin 中 ctags 问题</h3>
<br />
<p>前两天在 cygwin 用 ctags 生成 tags 时发现，"ctag -R ." 这条命令用法不对，怎么也想不明白哪里不对了。'ctags --version' 查一下才知道，这个 ctags 根本不是 Exuberant Ctags，而是 xemacs-tags。然而 Exuberant Ctags 是已经装了的，<strong>当时的做法是用了 cygwin 的安装/卸载工具，其余保持 default， 搜索到 xemcas-tags, uninstall, 搜索到 Exuberant Ctags, reinstall</strong>。</p>

<p>忘了在问题解决前有没有查看两者的路径，我猜在 $PATH 中把 Exuberant Ctags 所在路径放到 xemacs-tags 之前应该可行，如果两者在同一路径，ctags 非要指向 xemacs-tags 那怎么办，搞不懂。反正放大招把 不用的 xemacs-tags 干掉是可以了。</p>
<hr />
<br />
<h3>Firefox 5 用 vimperator 或 Pentadactyl</h3>
<br />
<p>这两个东西可能是最让已经用 firefox 的不换其他浏览器的理由了，把整个浏览器 "vim 化"了， IE 以及其用其内核一系列垃圾低智商专用浏览器当然是不可能实现如此强悍的功能，对于 chrome， 我试过两个想实现这个功能的扩展，但是太难用了，完全比不了 vimperator 或 Pentadactyl。</p>

<p>前两天换用了 Pentadactyl, 发现在关闭最后一个标签页时，firefox 窗口就自动关闭了，以前用 vimperator 时，其他条件都一样，但是关闭最后一个标签页时，是出现一个空白页(我设置的主页)。以前用 tab mix plus 这个插件的时候，它是有这个可选项的，但是不想再去装它，特别是就为了那么一个小问题，更不值得。<strong>找到一个办法是进入 about:config, 搜索 browser.tab, 把 browser.tabs.closeWindowWithLastTab 这一项的值改为 false (双击那一项即可)</strong>。还不明白的是，即便该项值为 true, 用 vimperator 时，关闭最后一个标签页时，也不会关闭窗口的，可能跟 vimperator 自身的配置有关，不深究了。</p>
<hr />
<br />
<h3>Mac OS X 10.7 (Lion) 中编译 mplayer, ffmpeg</h3>
<br />
<p>我想找一个 mac 下的音视频处理工具，一般就用很简单的操作，合并裁剪什么的，不至于搞个 final cut pro，俺也没那个钱，更不想搞个盗版来用。既然有 mencoder 和 ffmpeg，一切就好了。</p>

<p>一开始我想用 macports 把这两个装上，结果出错，甚至干脆把 macports 和用它装上的工具一并删掉了，换用 homebrew，结果一样是安装失败。然后就是自己动手，丰衣足食了。把代码 git clone 下来，先是 ffmpeg, 仔细看了 ./configure --help 那一大长串结果，禁用掉不需要的功能，禁用掉编译时必要而自己不想额外装库的功能，然后 make， 到收尾的连接阶段，出问题了，Undefined symbols for architecture x86_64:"_MM_FIX_0_707106781" 等等一大串内容，看上去好像是跟64位有关系，这个问题在网上搜到不少，<strong>一个解决办法是不用默认的gcc，在 configure 时添加 --cc=clang 参数，用 clang 来编译</strong>，测试可行。如果觉得用 clang 不大安心的花(毕竟 configure 检查时说 clang 是 experimental Only)，暂时又没有其他办法时，就把 ffmpeg 编译成32位的吧，--arch=x86_32.</p>

<p>编译 mplayer 时出错，其实问题跟上面一样，编译 mplayer 时，mplayer 会自动把 ffmpeg 的代码 git clone 下来到自己的目录，在里面静态编译个 ffmpeg，所以也会出现上面的问题。同样指定用 clang 来编译即可。但是如果想用 -cc='gcc -m32' 参数来指定编译32位时，会编译失败。</p>

<p>这样先静态编译个ffmpeg，在编译 mplayer 时在里面又编译 ffmpeg 的静态库来用，感觉有些浪费。可以在先编译 ffmpeg 时，指定编译共享库，或者叫动态库(--enable-shared), 然后编译 mplayer 时禁用掉 ffmpeg 静态库(--disable-ffmpeg_a)。当然很重要的一点时，要让 mplayer 编译时能找得到编译好的 ffmpeg 共享库，要么是把 ffmpeg 共享库的路径添加到 ld.so.conf.d (有可能已经在里面了) 然后执行 ldconfig, 要么就是在编译时指定路径  --extra-cflags="-I ffmpeg头文件路径" --extra-ldflags="-L ffmpeg 共享库的路径"</p>
<hr />]]></description>
			<content:encoded><![CDATA[<p>记录、备份之</p>
<h3>Cygwin 中 ctags 问题</h3>
<p></p>
<p>前两天在 cygwin 用 ctags 生成 tags 时发现，”ctag -R .” 这条命令用法不对，怎么也想不明白哪里不对了。&#8217;ctags &#8211;version&#8217; 查一下才知道，这个 ctags 根本不是 Exuberant Ctags，而是 xemacs-tags。然而 Exuberant Ctags 是已经装了的，<strong>当时的做法是用了 cygwin 的安装/卸载工具，其余保持 default， 搜索到 xemcas-tags, uninstall, 搜索到 Exuberant Ctags, reinstall</strong>。</p>
<p>忘了在问题解决前有没有查看两者的路径，我猜在 $PATH 中把 Exuberant Ctags 所在路径放到 xemacs-tags 之前应该可行，如果两者在同一路径，ctags 非要指向 xemacs-tags 那怎么办，搞不懂。反正放大招把 不用的 xemacs-tags 干掉是可以了。</p>
<hr />
</p>
<h3>Firefox 5 用 vimperator 或 Pentadactyl</h3>
<p></p>
<p>这两个东西可能是最让已经用 firefox 的不换其他浏览器的理由了，把整个浏览器 “vim 化”了， IE 以及其用其内核一系列垃圾低智商专用浏览器当然是不可能实现如此强悍的功能，对于 chrome， 我试过两个想实现这个功能的扩展，但是太难用了，完全比不了 vimperator 或 Pentadactyl。</p>
<p>前两天换用了 Pentadactyl, 发现在关闭最后一个标签页时，firefox 窗口就自动关闭了，以前用 vimperator 时，其他条件都一样，但是关闭最后一个标签页时，是出现一个空白页(我设置的主页)。以前用 tab mix plus 这个插件的时候，它是有这个可选项的，但是不想再去装它，特别是就为了那么一个小问题，更不值得。<strong>找到一个办法是进入 about:config, 搜索 browser.tab, 把 browser.tabs.closeWindowWithLastTab 这一项的值改为 false (双击那一项即可)</strong>。还不明白的是，即便该项值为 true, 用 vimperator 时，关闭最后一个标签页时，也不会关闭窗口的，可能跟 vimperator 自身的配置有关，不深究了。</p>
<hr />
</p>
<h3>Mac OS X 10.7 (Lion) 中编译 mplayer, ffmpeg</h3>
<p></p>
<p>我想找一个 mac 下的音视频处理工具，一般就用很简单的操作，合并裁剪什么的，不至于搞个 final cut pro，俺也没那个钱，更不想搞个盗版来用。既然有 mencoder 和 ffmpeg，一切就好了。</p>
<p>一开始我想用 macports 把这两个装上，结果出错，甚至干脆把 macports 和用它装上的工具一并删掉了，换用 homebrew，结果一样是安装失败。然后就是自己动手，丰衣足食了。把代码 git clone 下来，先是 ffmpeg, 仔细看了 ./configure &#8211;help 那一大长串结果，禁用掉不需要的功能，禁用掉编译时必要而自己不想额外装库的功能，然后 make， 到收尾的连接阶段，出问题了，Undefined symbols for architecture x86_64:”_MM_FIX_0_707106781&#8243; 等等一大串内容，看上去好像是跟64位有关系，这个问题在网上搜到不少，<strong>一个解决办法是不用默认的gcc，在 configure 时添加 &#8211;cc=clang 参数，用 clang 来编译</strong>，测试可行。如果觉得用 clang 不大安心的花(毕竟 configure 检查时说 clang 是 experimental Only)，暂时又没有其他办法时，就把 ffmpeg 编译成32位的吧，&#8211;arch=x86_32.</p>
<p>编译 mplayer 时出错，其实问题跟上面一样，编译 mplayer 时，mplayer 会自动把 ffmpeg 的代码 git clone 下来到自己的目录，在里面静态编译个 ffmpeg，所以也会出现上面的问题。同样指定用 clang 来编译即可。但是如果想用 -cc=&#8217;gcc -m32&#8242; 参数来指定编译32位时，会编译失败。</p>
<p>这样先静态编译个ffmpeg，在编译 mplayer 时在里面又编译 ffmpeg 的静态库来用，感觉有些浪费。可以在先编译 ffmpeg 时，指定编译共享库，或者叫动态库(&#8211;enable-shared), 然后编译 mplayer 时禁用掉 ffmpeg 静态库(&#8211;disable-ffmpeg_a)。当然很重要的一点时，要让 mplayer 编译时能找得到编译好的 ffmpeg 共享库，要么是把 ffmpeg 共享库的路径添加到 ld.so.conf.d (有可能已经在里面了) 然后执行 ldconfig, 要么就是在编译时指定路径  &#8211;extra-cflags=”-I ffmpeg头文件路径” &#8211;extra-ldflags=”-L ffmpeg 共享库的路径”</p>
<hr />
<h3 class='related_post_title'>相关日志:</h3>
<ul class='related_post'>
<li><a href='http://cfz.cc/essential_tools_in_my_mac.html' title='MAC OS X 软件推荐'>MAC OS X 软件推荐</a></li>
<li><a href='http://cfz.cc/linux_shell_audio_video_convert.html' title='Linux 终端下音视频简单转换、合并等处理'>Linux 终端下音视频简单转换、合并等处理</a></li>
<li><a href='http://cfz.cc/some_useful_commands_in_vim.html' title='VIM 中的几个有用操作'>VIM 中的几个有用操作</a></li>
<li><a href='http://cfz.cc/plan_of_reading_programming_books.html' title='读书计划 &#8211; 编程技术'>读书计划 &#8211; 编程技术</a></li>
<li><a href='http://cfz.cc/use_vim_to_blog_markdown_syntax.html' title='用 vim 写 markdown 语法 发布博客'>用 vim 写 markdown 语法 发布博客</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://cfz.cc/some_tips_recently_met.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

