<?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>SpongeLiu的blog</title>
	<atom:link href="http://www.spongeliu.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.spongeliu.com</link>
	<description>Love what you do!</description>
	<lastBuildDate>Thu, 13 Oct 2011 06:16:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>一个十分有趣的字符串算法题目</title>
		<link>http://www.spongeliu.com/%e7%ae%97%e6%b3%95/findstring/</link>
		<comments>http://www.spongeliu.com/%e7%ae%97%e6%b3%95/findstring/#comments</comments>
		<pubDate>Tue, 19 Apr 2011 09:21:39 +0000</pubDate>
		<dc:creator>sponge</dc:creator>
				<category><![CDATA[算法]]></category>
		<category><![CDATA[blogspot]]></category>
		<category><![CDATA[字符串]]></category>
		<category><![CDATA[有趣的算法]]></category>

		<guid isPermaLink="false">http://www.spongeliu.com/?p=278</guid>
		<description><![CDATA[在blogspot上看到一个十分有趣的字符串算法题目，原文在这里。作者讲述了自己面试google的一次经历。本文不理会这个故事，只来讨论一下里面着个有趣的算法。

算法题目：有两个字符串由不同的字母组成，一长一短，长的为A短的为B。设计一个算法，如果所有在B中出现的字符都在A中出现，则返回true，否则返回false。
例子：

如下字符串：

字符串A: abddfdioegdddffsfagj
字符串B: dofsjadg

字符串B中每个字符都在A中出现，返回true。

如下字符串：

字符串A: aaaabbbbbbdddddd
字符串B: acc

字符串B中有字符没在A中出现，返回false。
]]></description>
			<content:encoded><![CDATA[<p>在blogspot上看到一个十分有趣的字符串算法题目，原文在<a href="http://paultyma.blogspot.com/2010/11/google-interviewing-story.html">这里</a>。作者讲述了自己面试google的一次经历。本文不理会这个故事，只来讨论一下里面着个有趣的算法。</p>
<p><span style="color: #ff0000;">算法题目：</span>有两个字符串由不同的字母组成，一长一短，长的为A短的为B。设计一个算法，如果所有在B中出现的字符都在A中出现，则返回true，否则返回false。<br />
<span style="color: #ff0000;">例子： </span></p>
<p><span style="color: #0000ff;">如下字符串：</span></p>
<p>字符串A: abddfdioegdddffsfagj<br />
字符串B: dofsjadg</p>
<p><span style="color: #0000ff;">字符串B中每个字符都在A中出现，返回true。</span></p>
<p><span style="color: #0000ff;">如下字符串：</span></p>
<p>字符串A: aaaabbbbbbdddddd<br />
字符串B: acc</p>
<p><span style="color: #0000ff;">字符串B中有字符没在A中出现，返回false。</span></p>
<p>这只是个很基础的算法题目，相信很多人都能够立刻想出答案。</p>
<p><span style="color: #ff0000;">答案1</span>：对字符串B中的每个字母在A中都遍历一遍。这个答案很烂，其时间复杂度为O(n*m)</p>
<p><span style="color: #ff0000;">答案2</span>：设一个哈希表，对字符串A的字符遍历，将每个字符对应的哈希表中的值设为1。然后对B中的字符进行遍历，如果所有字符对应的hash值都为1，则返回true，否则返回false。</p>
<p>这个答案的时间复杂度是<span style="color: #ff0000;">O(m+n)</span>，应该是大多数面试者想要的答案，相信大多数人也能想到。<span style="color: #ff0000;">这样结束了</span>？如果真结束了，那就谈不上有趣了！如果我们<span style="color: #ff0000;">对空间要求比较高该怎么办</span>？</p>
<p><span style="color: #ff0000;">答案3</span>：我们可以观察到，字母总共就有26个，而且在上面答案中，hash表的值只有1和0两种情况。那就好办了，我们知道int类型是32位，如果用1位(bit)来表示一个字母是否出现，那么只需1个int类型就能够表示所有的字母了。</p>
<p>答案3实际上跟答案2类似，换汤不换药。有趣的不是他，<span style="color: #ff0000;">实际上还存在一种更有意思的方法</span>：</p>
<p><span style="color: #ff0000;">答案4</span>：<span style="color: #0000ff;">我们为每个字母(假设字母的数量是一定的)分配一个不重复素数，比如a为2， b为3， c为5，以此类推。这样在对字符串A进行遍历时，将每个字符表示的素数相乘，最终得到一个比较大的整数。然后从字符串B中第一个字母开始，用每个字母所代表的数除这个整数，如果余数不为0，那么就返回false。如果整个遍历过程中都没有余数，则返回true。</span></p>
<p>在我第一次从原文中看到着个答案的时候，有一种眼前一亮的感觉。实际上仔细推敲，这种算法的效率并不一定比之前的答案要高，因为往往一个乘法/除法的效率要小于加减法或者比较运算。但是却给出了一种全新的考虑问题的角度，有种奇思妙想的感觉！这种方法更为巧妙，有趣！</p>
<p>在每个算法题目中，你在得到一个公认的比较有效的方法后，是否考虑过更简单、有趣的方法呢？</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spongeliu.com/%e7%ae%97%e6%b3%95/findstring/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>再一次安装gentoo过程中遇到的几个小问题</title>
		<link>http://www.spongeliu.com/gentoo/gentoo_reinstall/</link>
		<comments>http://www.spongeliu.com/gentoo/gentoo_reinstall/#comments</comments>
		<pubDate>Fri, 04 Mar 2011 15:44:52 +0000</pubDate>
		<dc:creator>sponge</dc:creator>
				<category><![CDATA[Gentoo]]></category>
		<category><![CDATA[Error 65280]]></category>
		<category><![CDATA[imagemagick]]></category>
		<category><![CDATA[openoffice]]></category>
		<category><![CDATA[问题]]></category>

		<guid isPermaLink="false">http://www.spongeliu.com/?p=266</guid>
		<description><![CDATA[<strong>1、<span style="color: #ff0000;">在安装openoffice过程中出现大致如下的错误</span></strong>
<pre lang="shell">ERROR: Error 65280 occurred while making /var/tmp/portage/app-office/openoffice-3.2.1-r1/work/ooo/build/OOO320_m19/desktop/zipintro 
rmdir /var/tmp/portage/app-office/openoffice-3.2.1-r1/temp/yERj5YXC9A 
make: *** [stamp/build] Error 1 
* ERROR: app-office/openoffice-3.2.1-r1 failed: 
* Build failed 
* 
* Call stack: 
* ebuild.sh, line 54: Called src_compile 
* environment, line 8141: Called die 
* The specific snippet of code: 
* make &#124;&#124; die "Build failed" 
* 
* If you need support, post the output of 'emerge --info =app-office/openoffice-3.2.1-r1', 
* the complete build log and the output of 'emerge -pqv =app-office/openoffice-3.2.1-r1'. 
!!! When you file a bug report, please include the following information: 
GENTOO_VM=sun-jdk-1.6 CLASSPATH="" JAVA_HOME="/opt/sun-jdk-1.6.0.22" 
JAVACFLAGS="-source 1.5 -target 1.5" COMPILER="" 
and of course, the output of emerge --info 
* The complete build log is located at '/var/log/portage/app-office:openoffice-3.2.1-r1:20101120-141010.log'. 
* The ebuild environment file is located at '/var/tmp/portage/app-office/openoffice-3.2.1-r1/temp/environment'. 
* S: '/var/tmp/portage/app-office/openoffice-3.2.1-r1/work/ooo' 

>>> Failed to emerge app-office/openoffice-3.2.1-r1, Log file: 

>>> '/var/log/portage/app-office:openoffice-3.2.1-r1:20101120-141010.log' 
</pre>

<strong>问题原因：</strong>openoffice依赖一个包imagemagick，该包编译时需要png。具体机制不详

<span style="color: #ff0000;">解决方法：</span>  USE="png"       emerge -av imagemagick openoffice
]]></description>
			<content:encoded><![CDATA[<p><strong>1、<span style="color: #ff0000;">在安装openoffice过程中出现大致如下的错误</span></strong></p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">ERROR: Error 65280 occurred while making /var/tmp/portage/app-office/openoffice-3.2.1-r1/work/ooo/build/OOO320_m19/desktop/zipintro 
rmdir /var/tmp/portage/app-office/openoffice-3.2.1-r1/temp/yERj5YXC9A 
make: *** [stamp/build] Error 1 
* ERROR: app-office/openoffice-3.2.1-r1 failed: 
* Build failed 
* 
* Call stack: 
* ebuild.sh, line 54: Called src_compile 
* environment, line 8141: Called die 
* The specific snippet of code: 
* make || die &quot;Build failed&quot; 
* 
* If you need support, post the output of 'emerge --info =app-office/openoffice-3.2.1-r1', 
* the complete build log and the output of 'emerge -pqv =app-office/openoffice-3.2.1-r1'. 
!!! When you file a bug report, please include the following information: 
GENTOO_VM=sun-jdk-1.6 CLASSPATH=&quot;&quot; JAVA_HOME=&quot;/opt/sun-jdk-1.6.0.22&quot; 
JAVACFLAGS=&quot;-source 1.5 -target 1.5&quot; COMPILER=&quot;&quot; 
and of course, the output of emerge --info 
* The complete build log is located at '/var/log/portage/app-office:openoffice-3.2.1-r1:20101120-141010.log'. 
* The ebuild environment file is located at '/var/tmp/portage/app-office/openoffice-3.2.1-r1/temp/environment'. 
* S: '/var/tmp/portage/app-office/openoffice-3.2.1-r1/work/ooo' 
&nbsp;
&gt;&gt;&gt; Failed to emerge app-office/openoffice-3.2.1-r1, Log file: 
&nbsp;
&gt;&gt;&gt; '/var/log/portage/app-office:openoffice-3.2.1-r1:20101120-141010.log'</pre></div></div>

<p><strong>问题原因：</strong>openoffice依赖一个包imagemagick，该包编译时需要png。具体机制不详</p>
<p><span style="color: #ff0000;">解决方法：</span>  USE="png"       emerge -av imagemagick openoffice</p>
<p><strong>2、<span style="color: #ff0000;">在root下面无法启动gedit等gui软件</span></strong><br />
错误提示为：</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">(gedit:5278): EggSMClient-WARNING **: Failed to connect to the session manager: None of the authentication protocols specified are supported 
&nbsp;
** 
GLib-GIO:ERROR:gdbusconnection.c:2271:initable_init: assertion failed: (connection-&gt;initialization_error == NULL) 
Aborted</pre></div></div>

<p><strong>问题原因：</strong>su进入root后，只是简单的切换user，并不能提供一个全root的运行环境<br />
<span style="color: #ff0000;">解决方法：</span>  使用 su - 代替 su。 注意su和-之间有个空格。</p>
<p><strong>3、<span style="color: #ff0000;">firefox字体模糊</span></strong><br />
<strong>问题原因：</strong>系统开启了抗锯齿效果<br />
<span style="color: #ff0000;">解决方法：</span>  在/etc/fonts/fonts.conf文件中添加：</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"> <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;match</span> <span style="color: #000066;">target</span>=<span style="color: #ff0000;">&quot;font&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;test</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;family&quot;</span> <span style="color: #000066;">compare</span>=<span style="color: #ff0000;">&quot;eq&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>SimSun<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>&quot;or&quot;
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Bitstream Cyberbit<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>&quot;or&quot;
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>AR PL KaitiM Big5<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>&quot;or&quot;
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>AR PL Mingti2L Big5<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>&quot;or&quot;
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>AR PL KaitiM GB<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>&quot;or&quot;
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>AR PL SungtiL GB<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/test<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;edit</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;hinting&quot;</span> <span style="color: #000066;">mode</span>=<span style="color: #ff0000;">&quot;assign&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bool<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bool<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/edit<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;edit</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;autohint&quot;</span> <span style="color: #000066;">mode</span>=<span style="color: #ff0000;">&quot;assign&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bool<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bool<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/edit<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;edit</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;antialias&quot;</span> <span style="color: #000066;">mode</span>=<span style="color: #ff0000;">&quot;assign&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bool<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>false<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bool<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/edit<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/match<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p><strong>4、<span style="color: #ff0000;">在安装klibc过程中出现大致如下的错误</span></strong></p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;"> * Applying klibc-1.5.11-x86_64-io.h-return.diff ...                                                                                                            [ ok ] 
&gt;&gt;&gt; Source unpacked in /var/tmp/portage/dev-libs/klibc-1.5.15-r1/work 
&gt;&gt;&gt; Compiling source in /var/tmp/portage/dev-libs/klibc-1.5.15-r1/work/klibc-1.5.15 ... 
make -j3 defconfig CC=x86_64-pc-linux-gnu-gcc HOSTCC=x86_64-pc-linux-gnu-gcc 
Makefile:434: *** mixed implicit and normal rules.  Stop. 
emake failed 
 * ERROR: dev-libs/klibc-1.5.15-r1 failed: 
 *   No defconfig 
 * 
 * Call stack: 
 *     ebuild.sh, line  56:  Called src_compile 
 *   environment, line 2425:  Called die 
 * The specific snippet of code: 
 *       emake ${defconfig} CC=&quot;${CC}&quot; HOSTCC=&quot;${HOSTCC}&quot; || die &quot;No defconfig&quot;; 
 * 
 * If you need support, post the output of 'emerge --info =dev-libs/klibc-1.5.15-r1', 
 * the complete build log and the output of 'emerge -pqv =dev-libs/klibc-1.5.15-r1'. 
 * The complete build log is located at '/var/tmp/portage/dev-libs/klibc-1.5.15-r1/temp/build.log'. 
 * The ebuild environment file is located at '/var/tmp/portage/dev-libs/klibc-1.5.15-r1/temp/environment'. 
 * S: '/var/tmp/portage/dev-libs/klibc-1.5.15-r1/work/klibc-1.5.15' 
&nbsp;
&gt;&gt;&gt; Failed to emerge dev-libs/klibc-1.5.15-r1, Log file: 
&nbsp;
&gt;&gt;&gt;  '/var/tmp/portage/dev-libs/klibc-1.5.15-r1/temp/build.log' 
&nbsp;
 * Messages for package dev-libs/klibc-1.5.15-r1: 
&nbsp;
 * ERROR: dev-libs/klibc-1.5.15-r1 failed: 
 *   No defconfig 
 * 
 * Call stack: 
 *     ebuild.sh, line  56:  Called src_compile 
 *   environment, line 2425:  Called die 
 * The specific snippet of code: 
 *       emake ${defconfig} CC=&quot;${CC}&quot; HOSTCC=&quot;${HOSTCC}&quot; || die &quot;No defconfig&quot;; 
 * 
 * If you need support, post the output of 'emerge --info =dev-libs/klibc-1.5.15-r1', 
 * the complete build log and the output of 'emerge -pqv =dev-libs/klibc-1.5.15-r1'. 
 * The complete build log is located at '/var/tmp/portage/dev-libs/klibc-1.5.15-r1/temp/build.log'. 
 * The ebuild environment file is located at '/var/tmp/portage/dev-libs/klibc-1.5.15-r1/temp/environment'. 
 * S: '/var/tmp/portage/dev-libs/klibc-1.5.15-r1/work/klibc-1.5.15'</pre></div></div>

<p><strong>问题原因：</strong>高版本make的一个bug<br />
<span style="color: #ff0000;">解决方法：</span>  编译klibc的时候先将make版本降低</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">emerge --oneshot =make-3.80-r4 
emerge --oneshot klibc</pre></div></div>

<p>编译完成后再将版本升级回来</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">emerge --update --oneshot make</pre></div></div>

<p>参考：</p>
<p>http://forums.gentoo.org/viewtopic-t-849190.html?sid=d33383354a919e3ebabba9b36edd2d4e</p>
<p>http://bugs.gentoo.org/345743</p>
<p>http://forums.fedoraforum.org/archive/index.php/t-255624.html</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spongeliu.com/gentoo/gentoo_reinstall/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>为什么C++中空类和空结构体大小为1？</title>
		<link>http://www.spongeliu.com/clanguage/why-not-null/</link>
		<comments>http://www.spongeliu.com/clanguage/why-not-null/#comments</comments>
		<pubDate>Wed, 17 Nov 2010 14:40:53 +0000</pubDate>
		<dc:creator>sponge</dc:creator>
				<category><![CDATA[C语言]]></category>
		<category><![CDATA[sizeof]]></category>
		<category><![CDATA[空类大小]]></category>
		<category><![CDATA[空结构体]]></category>

		<guid isPermaLink="false">http://www.spongeliu.com/?p=260</guid>
		<description><![CDATA[这篇文章是一篇<span style="color: #ff0000;">译文</span>，跟<a href="http://www.spongeliu.com/clanguage/sizeof/">上一篇文章</a>相呼应的，原文在<a href="http://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a">这里</a>。

对于结构体和空类大小是1这个问题，首先<span style="color: #ff0000;">这是一个C++问题</span>，在C语言下空结构体大小为0(当然这是编译器相关的)。这里的空类和空结构体是指类或结构体中没有任何成员。

<span style="color: #ff0000;">在C++下，空类和空结构体的大小是1</span>（编译器相关），这是为什么呢？为什么不是0？

这是因为，C++标准中规定，“<span style="color: #ff0000;">no object shall have the same address in memory as any other variable</span>” ，就是<span style="color: #ff0000;">任何不同的对象不能拥有相同的内存地址。</span> 如果空类大小为0，若我们声明一个这个类的对象数组，那么数组中的每个对象都拥有了相同的地址，这显然是违背标准的。

但是，也许你还有一个疑问，<span style="color: #ff0000;">为什么C++标准中会有这么无聊的规定呢？</span>]]></description>
			<content:encoded><![CDATA[<p>这篇文章是一篇<span style="color: #ff0000;">译文</span>，跟<a href="http://www.spongeliu.com/clanguage/sizeof/">上一篇文章</a>相呼应的，原文在<a href="http://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a">这里</a>。</p>
<p>对于结构体和空类大小是1这个问题，首先<span style="color: #ff0000;">这是一个C++问题</span>，在C语言下空结构体大小为0(当然这是编译器相关的)。这里的空类和空结构体是指类或结构体中没有任何成员。</p>
<p><span style="color: #ff0000;">在C++下，空类和空结构体的大小是1</span>（编译器相关），这是为什么呢？为什么不是0？</p>
<p>这是因为，C++标准中规定，“<span style="color: #ff0000;">no object shall have the same address in memory as any other variable</span>” ，就是<span style="color: #ff0000;">任何不同的对象不能拥有相同的内存地址。</span> 如果空类大小为0，若我们声明一个这个类的对象数组，那么数组中的每个对象都拥有了相同的地址，这显然是违背标准的。</p>
<p>但是，也许你还有一个疑问，<span style="color: #ff0000;">为什么C++标准中会有这么无聊的规定呢？</span></p>
<p>当然，这样规定显然是有原因的。我们假设C++中有一个类型T，我们声明一个类型T的数组，然后再声明一个T类型的指针指向数组中间某个元素，则我们将指针减去1，应该得到数组的另一个索引。如下代码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">T array<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">5</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">int</span> diff <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span>array<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">-</span> <span style="color: #339933;">&amp;</span>array<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
 <span style="color: #666666; font-style: italic;">// diff = 1</span></pre></td></tr></table></div>

<p>上面的代码是一种指针运算，将两个指针相减，编译器作出如下面式子所示的动作：</p>
<p><span style="color: #ff0000;">diff = ((char *)&amp;array[3] - (char *)&amp;array[2]) / sizeof T;</span></p>
<p>式子应该不难懂把，很明显的一点就是这个式子的计算依赖于sizeof T。虽然上面只是一个例子，但是<span style="color: #ff0000;">基本上所有的指针运算都依赖于sizeof T。</span></p>
<p>好，下面我们来看，如果允许不同的对象有相同的地址将会引发什么样的问题，看下面的例子：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"> <span style="color: #339933;">&amp;</span>array<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">-</span> <span style="color: #339933;">&amp;</span>array<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span>array<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">-</span> <span style="color: #339933;">&amp;</span>array<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span>
                       <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span>array<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">-</span> <span style="color: #339933;">&amp;</span>array<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span>
                       <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span>array<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">-</span> <span style="color: #339933;">&amp;</span>array<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span>
                       <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span></pre></td></tr></table></div>

<p>我们可以看到，在这个例子中，如果每个对象都拥有相同地址，我们将没有办法通过指针运算来区分不同的对象。还有一个更严重的问题，就是如果 sizeof T是0，就会<span style="color: #ff0000;">导致编译器产生一个除0的操作</span>，引发不可控的错误。</p>
<p>基于这个原因，如果允许结构体或者类的大小为0，编译器就需要实现一些复杂的代码来处理这些异常的指针运算。</p>
<p>所以，C++标准规定不同的对象不能拥有相同的地址。那么怎样才能保证这个条件被满足呢？最简单的方法莫过于不允许任何类型的大小为0。所以编译器为每个空类或者空结构体都增加了一个虚设的字节（有的编译器可能加的更多），这样这些空类和空结构的大小就不会是0，就可以保证他们的对象拥有彼此独立的地址。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spongeliu.com/clanguage/why-not-null/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>c关键字－sizeof的种种</title>
		<link>http://www.spongeliu.com/clanguage/sizeof/</link>
		<comments>http://www.spongeliu.com/clanguage/sizeof/#comments</comments>
		<pubDate>Sun, 14 Nov 2010 07:02:48 +0000</pubDate>
		<dc:creator>sponge</dc:creator>
				<category><![CDATA[C语言]]></category>
		<category><![CDATA[enum]]></category>
		<category><![CDATA[sizeof]]></category>
		<category><![CDATA[空类]]></category>
		<category><![CDATA[空结构体]]></category>

		<guid isPermaLink="false">http://www.spongeliu.com/?p=250</guid>
		<description><![CDATA[熟悉c的人都知道，sizeof是一个关键字而不是一个宏或者库函数什么的，他的值是在编译时确定的，如果这个不了解，可以现看看<a href="http://www.spongeliu.com/clanguage/ckeyword/">这篇文章</a>和<a href="http://www.spongeliu.com/clanguage/sizeof-struct/">这篇文章</a>。

既然如此，让我们先看下面几个小例子：
<pre lang="c">sizeof(int);
sizeof(char);
sizeof(double);</pre>
上面三行sizeof的值是多少呢？这里我们假定在32位的x86系统下。<span style="color: #ff0000;">我们会得到答案：4，1，8</span>。这个没什么吧，大多数人都应该知道。那么，下面这个：
<pre lang="c">sizeof(int);
sizeof(long);</pre>
在32位x86下，这两个是多少呢？4，8？<span style="color: #ff0000;">实际上，答案是4，4</span>。我们需要注意，long类型在32位系统下是32位的。那么，64位下结果又如何呢？8，8？<span style="color: #ff0000;">其实答案是4，8</span>。另一个需要注意的是，<span style="color: #ff0000;">64位下的int是32位的</span>。]]></description>
			<content:encoded><![CDATA[<p>熟悉c的人都知道，sizeof是一个关键字而不是一个宏或者库函数什么的，他的值是在编译时确定的，如果这个不了解，可以现看看<a href="http://www.spongeliu.com/clanguage/ckeyword/">这篇文章</a>和<a href="http://www.spongeliu.com/clanguage/sizeof-struct/">这篇文章</a>。  既然如此，让我们先看下面几个小例子：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">double</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>上面三行sizeof的值是多少呢？这里我们假定在32位的x86系统下。<span style="color: #ff0000;">我们会得到答案：4，1，8</span>。这个没什么吧，大多数人都应该知道。那么，下面这个：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">long</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>在32位x86下，这两个是多少呢？4，8？</p>
<p><span style="color: #ff0000;">实际上，答案是4，4</span>。我们需要注意，long类型在32位系统下是32位的。那么，64位下结果又如何呢？8，8？<span style="color: #ff0000;">其实答案是4，8</span>。另一个需要注意的是，<span style="color: #ff0000;">64位下的int是32位的</span>。</p>
<p>上面只是热热身，现在，让我们看sizeof的下面几种情形：</p>
<p>1、<span style="color: #ff0000;"><strong>sizeof一个结构体。</strong></span></p>
<p>这个我就不说啥了，具体的参考<a href="../clanguage/sizeof-struct/">这篇文章</a>。至于空的结构体，下面会解释。</p>
<p><span style="color: #ff0000;"><span style="color: #000000;">2、</span><strong>sizeof数组、指针等</strong></span> 先看下面两个例子：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">char</span> a<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">100</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">char</span> b<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">100</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #ff0000;">&quot;helloworld!&quot;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">char</span> c<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #ff0000;">&quot;helloworld!&quot;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">char</span><span style="color: #339933;">*</span> d<span style="color: #339933;">=</span>b<span style="color: #339933;">;</span>
<span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>c<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>d<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>在32位x86系统下，以上各是多少呢？</p>
<p><span style="color: #ff0000;">答案是：100，100，12，4。</span></p>
<p>为什么不是100，12，12，12呢？  sizeof一个数组名，返回的是数组的大小，不管你数组里面放的什么数据。所以，第一个数组大小是100，第二个数组大小是100，第三个数组大小是12（别忘记"\0"）。第四个呢？第四个不是一个数组名，而是一个指针！32位下指针大小永远是4，不管你是指向一个数组还是一个int还是一个char。  好，这个问题搞清楚之后，看下面这个程序：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> func<span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> a<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">100</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>m <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;helloworld!&quot;</span><span style="color: #339933;">;</span>
    func<span style="color: #009900;">&#40;</span>m<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">char</span> n<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">100</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #ff0000;">&quot;helloworld!&quot;</span><span style="color: #339933;">;</span>
    func<span style="color: #009900;">&#40;</span>n<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>这个程序会打印出什么结果呢？</p>
<p><span style="color: #ff0000;">答案是：4， 4。</span> 为什么结果都是4？不是应该返回数组长度么？</p>
<p><span style="color: #ff0000;">这里出现又一个需要注意的地方：在作为参数传递的时候，数组名会退化为指针。</span>也就是说，这里的func里的参数，虽然看上去是个数组名，但实际上还是个指针。  你了解了么？下面是几个练习，自己实验下^_^</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">char</span> <span style="color: #339933;">*</span>p <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
<span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>p<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">int</span> a<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">100</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">100</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>a<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>a<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>懒得实验？答案分别是4，1，400，4，4，4。为什么？自己想想。</p>
<p>3、<span style="color: #ff0000;"><strong>sizeof一些诡异的东西</strong></p>
<p>（enum，空类，空struct）</span> 所谓的诡异的东西，就是一些你想到的想不到的东西拿来sizeof。比如说sizeof一个enum类型是多少？一个空struct呢？一个空类呢？  这些诡异的东西在标准C中都没有作出规定，很大程度上都是编译器和系统结构相关的。  先来看一个：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">enum</span> week<span style="color: #009900;">&#123;</span>Mon<span style="color: #339933;">,</span> Tue<span style="color: #339933;">,</span> Wed<span style="color: #339933;">,</span> Thu<span style="color: #339933;">,</span> Fri<span style="color: #339933;">,</span> Sat<span style="color: #339933;">,</span> Sun<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">enum</span> week<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>这个你会得到什么样的结果呢？28？  在gcc或者vc下运行一把，<span style="color: #ff0000;">你会得到答案：4。</span></p>
<p>为什么呢？  实际上<span style="color: #ff0000;">，enum具体有多大取决于编译器的实现</span>，目前大多数的编译器都将其实现为int类型。也就是说这里的enum被当作int类型（当然，使用上不一样）。这不是一成不变的，有些编译器，如VC++允许下面这种定义：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//注意这是个cpp文件</span>
<span style="color: #000000; font-weight: bold;">enum</span> Color <span style="color: #339933;">:</span> <span style="color: #993333;">unsigned</span> <span style="color: #993333;">char</span>
<span style="color: #009900;">&#123;</span>
   red<span style="color: #339933;">,</span> green<span style="color: #339933;">,</span> blue
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// assert(sizeof(Color) == 1);</span></pre></div></div>

<p>enum先说到这里，那么<span style="color: #ff0000;">一个空的结构体是多大呢</span>？  如果你擅长C语言，你可以很快的写出下面的程序：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//this is a *.c file</span>
<span style="color: #993333;">struct</span> node<span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>Node<span style="color: #339933;">;</span>
<span style="color: #993333;">int</span> main
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>Node<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>很快，你可以验证出来<span style="color: #ff0000;">结果是0。</span> 没错，这很好理解。但是，如果你用的是c++呢？</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//this is a *.cpp file</span>
<span style="color: #993333;">struct</span> node<span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>Node<span style="color: #339933;">;</span>
&nbsp;
class node2<span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>Node2<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>Node<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>Node2<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>（不怎么会写c++的我表示压力很大）以上这个c++的例子结果是多少呢？</p>
<p><span style="color: #ff0000;">为什么会得到1，1这个结果呢？</span> 换句话说就是为什么sizeof一个空类和空结构体在c++下就是1呢？</p>
<p>这个原因要追朔到c++标准中的一句话：“<span style="color: #ff0000;">no object shall have the same address in memory as any other variable</span>”， 用中国话简单点说就是：<span style="color: #ff0000;">不同的对象之间应该有不同的地址</span>（为什么会有这样的规定？看<a href="http://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a">这里</a>）。</p>
<p>既然每个对象都必须有不同的地址，让我们假设上面代码中的Node的size是0，想想会出现什么样的后果？</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">Node a<span style="color: #339933;">;</span>
Node b<span style="color: #339933;">;</span></pre></div></div>

<p>a的大小是0，b的大小是0，那么，a和b的地址是不是很可能重复了？</p>
<p>所以，<span style="color: #ff0000;">为了保证不同的对象拥有不同的地址，最简单的方法就是保证所有类型的大小都不是0</span>。</p>
<p>所以，为了保证这点，大多数c++编译器都会给空结构或类加上一个冗余的字节保证类型不为空。</p>
<p>我的解释的清楚么？如果我的表达能力不够好，看<a href="http://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a">这里</a>，解释的足够详细。  当然，还有其他很多我没有想到的诡异的东西可以拿来sizeof，如果你想到了，欢迎跟我分享。至于c++中的sizeof类，基类，派生类，足够可以作为一个专门的文章了，先不再这里说，等我学会C++的再写一下相关内容（-_-"）。</p>
<p>最后，给一个稍微给力点的程序，大家看看最终得到的结果是什么(<span style="color: #ff0000;">注意这是一个c++程序</span>)：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//this is a cpp file</span>
<span style="color: #993333;">typedef</span>   <span style="color: #993333;">struct</span>   weekday_st
<span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">enum</span>   week     <span style="color: #009900;">&#123;</span>sun<span style="color: #339933;">=</span><span style="color: #0000dd;">123456789</span><span style="color: #339933;">,</span>mon<span style="color: #339933;">,</span>tue<span style="color: #339933;">,</span>wed<span style="color: #339933;">,</span>thu<span style="color: #339933;">,</span>fri<span style="color: #339933;">,</span>sat<span style="color: #339933;">,</span>a<span style="color: #339933;">,</span>b<span style="color: #339933;">,</span>c<span style="color: #339933;">,</span>d<span style="color: #339933;">,</span>e<span style="color: #339933;">,</span>f<span style="color: #339933;">,</span>g<span style="color: #339933;">,</span>h<span style="color: #339933;">,</span>i<span style="color: #339933;">,</span>j<span style="color: #339933;">,</span>k<span style="color: #339933;">,</span>l<span style="color: #339933;">,</span>m<span style="color: #339933;">,</span>n<span style="color: #339933;">,</span>o<span style="color: #339933;">,</span>p<span style="color: #339933;">,</span>q<span style="color: #339933;">,</span>r<span style="color: #339933;">,</span>s<span style="color: #339933;">,</span>t<span style="color: #339933;">,</span>u<span style="color: #339933;">,</span>v<span style="color: #339933;">,</span>w<span style="color: #339933;">,</span>x<span style="color: #339933;">,</span>y<span style="color: #339933;">,</span>z<span style="color: #339933;">,</span>aa<span style="color: #339933;">,</span>ab<span style="color: #339933;">,</span>ac<span style="color: #339933;">,</span>ad<span style="color: #339933;">,</span>ae<span style="color: #339933;">,</span>af<span style="color: #339933;">,</span>ag<span style="color: #339933;">,</span>ah<span style="color: #339933;">,</span>ai<span style="color: #339933;">,</span>aj<span style="color: #339933;">,</span>ak<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">enum</span>   day<span style="color: #009900;">&#123;</span>monring<span style="color: #339933;">,</span>   moon<span style="color: #339933;">,</span>   aftermoon<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>weekday_st<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">int</span>   main<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span>   argc<span style="color: #339933;">,</span>   <span style="color: #993333;">char</span>   <span style="color: #339933;">*</span>argv<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span> <span style="color: #ff0000;">&quot;sizeof(weekday_st)=%d<span style="color: #000099; font-weight: bold;">\n</span> &quot;</span><span style="color: #339933;">,</span>   <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>weekday_st<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span> <span style="color: #ff0000;">&quot;sizeof(weekday)=%d<span style="color: #000099; font-weight: bold;">\n</span> &quot;</span><span style="color: #339933;">,</span>   <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>weekday_st<span style="color: #339933;">::</span><span style="color: #202020;">week</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span> <span style="color: #ff0000;">&quot;sizeof(day)=%d<span style="color: #000099; font-weight: bold;">\n</span> &quot;</span><span style="color: #339933;">,</span>   <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>weekday_st<span style="color: #339933;">::</span><span style="color: #202020;">day</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span>  <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>参考书目：<a href="http://www.amazon.cn/exec/obidos/ASIN/B0012NIW9K/spongeliu-23"  target="_blank">《C专家编程》</a> <a href="http://www.amazon.cn/exec/obidos/ASIN/B003XF3GQO/spongeliu-23"  target="_blank">《C语言深度解剖:解开程序员面试笔试的秘密 》</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.spongeliu.com/clanguage/sizeof/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>gdb的基本工作原理是什么？</title>
		<link>http://www.spongeliu.com/linux/howgdbwork/</link>
		<comments>http://www.spongeliu.com/linux/howgdbwork/#comments</comments>
		<pubDate>Fri, 29 Oct 2010 05:38:02 +0000</pubDate>
		<dc:creator>sponge</dc:creator>
				<category><![CDATA[linux系统]]></category>
		<category><![CDATA[attach]]></category>
		<category><![CDATA[gdb基本工作原理]]></category>
		<category><![CDATA[gdb工作原理]]></category>
		<category><![CDATA[ptrace]]></category>

		<guid isPermaLink="false">http://www.spongeliu.com/?p=240</guid>
		<description><![CDATA[还是面某M的时候，面试官问我：“用过gdb么？” 答：“用过，调了两年bug了”。“那好，给我解释下gdb是怎么工作的？或者说跟内核什么地方有关系？”。

是阿，<span style="color: #ff0000;">gdb凭什么可以调试一个程序？凭什么能够接管一个程序的运行？</span>我以前也想过这样的问题，但是后来居然忘记去查看了。我想到了我们的二进制翻译器，想到了intel的pin，Dynamo。这些都是将翻译后的代码放到codecache中去运行，然后接管整个程序的执行。gdb是不是也一样呢？

如果真是这样，为什么我记得用gdb跑一个程序，这个程序会有一个单独的进程？gdb的attach功能又是怎么实现的？

想了想，我还是没有答上来。面试就是由这么一个又一个细节的小杯具最后汇集成一个大杯具。

那么，gdb到底是凭什么接管的一个进程的执行呢？其实，很简单，<span style="color: #ff0000;">通过一个系统调用：ptrace</span>。ptrace系统调用的原型如下：]]></description>
			<content:encoded><![CDATA[<p>还是面某M的时候，面试官问我：“用过gdb么？” 答：“用过，调了两年bug了”。“那好，给我解释下gdb是怎么工作的？或者说跟内核什么地方有关系？”。</p>
<p>是阿，<span style="color: #ff0000;">gdb凭什么可以调试一个程序？凭什么能够接管一个程序的运行？</span>我以前也想过这样的问题，但是后来居然忘记去查看了。我想到了我们的二进制翻译器，想到了intel的pin，Dynamo。这些都是将翻译后的代码放到codecache中去运行，然后接管整个程序的执行。gdb是不是也一样呢？</p>
<p>如果真是这样，为什么我记得用gdb跑一个程序，这个程序会有一个单独的进程？gdb的attach功能又是怎么实现的？</p>
<p>想了想，我还是没有答上来。面试就是由这么一个又一个细节的小杯具最后汇集成一个大杯具。</p>
<p>那么，gdb到底是凭什么接管的一个进程的执行呢？其实，很简单，<span style="color: #ff0000;">通过一个系统调用：ptrace</span>。ptrace系统调用的原型如下：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;sys/ptrace.h&gt;</span>
&nbsp;
<span style="color: #993333;">long</span> ptrace<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">enum</span> __ptrace_request request<span style="color: #339933;">,</span> pid_t pid<span style="color: #339933;">,</span>
                   <span style="color: #993333;">void</span> <span style="color: #339933;">*</span>addr<span style="color: #339933;">,</span> <span style="color: #993333;">void</span> <span style="color: #339933;">*</span>data<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p><strong><span style="color: #ff0000;">说明：ptrace系统调用提供了一种方法来让父进程可以观察和控制其它进程的执行，检查和改变其核心映像以及寄存器。 主要用来实现断点调试和系统调用跟踪。（man手册）</span></strong></p>
<p>其实，说到这里，一切原理层面应该都比较明朗了（且先不去管内核中是怎么实现ptrace的）。gdb就是调用这个系统调用，然后通过一些参数来控制其他进程的执行的。</p>
<p>下面我们来看ptrace函数中request参数的一些主要选项：</p>
<p><span style="color: #ff0000;">PTRACE_TRACEME： </span>表示本进程将被其父进程跟踪，交付给这个进程的所有信号，即使信号是忽略处理的（除SIGKILL之外），都将使其停止，父进程将通过wait()获知这一情况。</p>
<p>这是什么意思呢？我们可以结合到gdb上来看。如果在gdb中run一个程序，首先gdb会fork一个子进程，然后该子进程调用ptrace系统调用，参数就是PTRACE_TRACEME，然后调用一个exec执行程序。基本过程是这样，细节上可能会有出入。需要注意的是，<span style="color: #ff0000;">这个选项PTRACE_TRACEME是由子进程调用的而不是父进程！</span></p>
<p><span style="color: #ff0000;"><strong>以下选项都是由父进程调用：</strong><br />
</span></p>
<p><span style="color: #ff0000;">PTRACE_ATTACH：</span>attach到一个指定的进程，使其成为当前进程跟踪的子进程，而子进程的行为等同于它进行了一次PTRACE_TRACEME操作。但是，需要注意的是，虽然当前进程成为被跟踪进程的父进程，但是子进程使用getppid()的到的仍将是其原始父进程的pid。</p>
<p>这下子gdb的attach功能也就明朗了。当你在gdb中使用attach命令来跟踪一个指定进程/线程的时候，gdb就自动成为改进程的父进程，而被跟踪的进程则使用了一次PTRACE_TRACEME，gdb也就顺理成章的接管了这个进程。</p>
<p><span style="color: #ff0000;">PTRACE_CONT：</span>继续运行之前停止的子进程。可同时向子进程交付指定的信号。</p>
<p>这个选项呢，其实就相当于gdb中的continue命令。当你使用continue命令之后，一个被gdb停止的进程就能继续执行下去，如果有信号，信号也会被交付给子进程。</p>
<p>除了以上这几个选项，ptrace还有很多其他选项，可以在linux下阅读man手册：<span style="color: #0000ff;">man ptrace</span></p>
<p>需要注意的另一点是，使用gdb调试过多线程/进程的人应该都知道，当子进程遇到一个信号的时候，gdb就会截获这个信号，并将子进程暂停下来。这是为什么呢？</p>
<p>实际上，在使用参数为PTRACE_TRACEME或PTRACE_ATTACH的ptrace系统调用建立调试关系之后，交付给目标程序的任何信号（除SIGKILL之外）都将被gdb先行截获，或在远程调试中被gdbserver截获并通知gdb。gdb因此有机会对信号进行相应处理，并根据信号的属性决定在继续目标程序运行时是否将之前截获的信号实际交付给目标程序。</p>
<p>参考资料：<a href="http://www.docin.com/p-18618736.html">gdb的基本工作原理</a><br />
<a href="http://www.amazon.cn/gp/product/0596100272/ref=as_li_tf_mfw?&#038;linkCode=wey&#038;tag=spongeliu-23" target="_blank">《gdb pocket reference》</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.spongeliu.com/linux/howgdbwork/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>C语言的那些个关键字们</title>
		<link>http://www.spongeliu.com/clanguage/ckeyword/</link>
		<comments>http://www.spongeliu.com/clanguage/ckeyword/#comments</comments>
		<pubDate>Thu, 28 Oct 2010 14:09:35 +0000</pubDate>
		<dc:creator>sponge</dc:creator>
				<category><![CDATA[C语言]]></category>
		<category><![CDATA[const]]></category>
		<category><![CDATA[register]]></category>
		<category><![CDATA[sizeof]]></category>
		<category><![CDATA[static]]></category>
		<category><![CDATA[volatile]]></category>
		<category><![CDATA[关键字]]></category>

		<guid isPermaLink="false">http://www.spongeliu.com/?p=236</guid>
		<description><![CDATA[最近感冒，昨天流着鼻涕去一直很想去的某M面试，居然还迟到了，一紧张，鼻涕不流了－ －#

问的问题不难，都是基础，可是自己不争气，答的不怎么样，一直自诩C语言用的很不错，可是还是在基础上被鄙视－ －！都是那些个关键字们阿～今天，让我挨个把C的关键字给详细的整一整，加深一下印象～

首先，<span style="color: #ff0000;">C语言中到底有多少个关键字呢？木有错，ANSI C规定是32个！</span> 他们分别是：auto double int struct break else long switch case enum register typedef char extern return union const float short unsigned continue for signed void default goto sizeof volatile do if while static。

别看那一堆了字母了，直接看下面的分类介绍：

<strong><span style="color: #ff0000;">第一类：数据类型关键字</span></strong>
]]></description>
			<content:encoded><![CDATA[<p>最近感冒，昨天流着鼻涕去一直很想去的某M面试，居然还迟到了，一紧张，鼻涕不流了－ －#</p>
<p>问的问题不难，都是基础，可是自己不争气，答的不怎么样，一直自诩C语言用的很不错，可是还是在基础上被鄙视－ －！都是那些个关键字们阿～今天，让我挨个把C的关键字给详细的整一整，加深一下印象～</p>
<p>首先，<span style="color: #ff0000;">C语言中到底有多少个关键字呢？木有错，ANSI C规定是32个！</span> 他们分别是：auto double int struct break else long switch case enum register typedef char extern return union const float short unsigned continue for signed void default goto sizeof volatile do if while static。</p>
<p>别看那一堆了字母了，直接看下面的分类介绍：</p>
<p><strong><span style="color: #ff0000;">第一类：数据类型关键字</span></strong></p>
<p>这一类别的关键字有：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">char</span>          <span style="color: #666666; font-style: italic;">//声明字符型变量或函数</span>
<span style="color: #993333;">double</span>       <span style="color: #666666; font-style: italic;">//声明双精度变量或函数</span>
<span style="color: #000000; font-weight: bold;">enum</span>         <span style="color: #666666; font-style: italic;">//声明枚举类型</span>
<span style="color: #993333;">float</span>          <span style="color: #666666; font-style: italic;">//声明浮点型变量或函数</span>
<span style="color: #993333;">int</span>            <span style="color: #666666; font-style: italic;">//声明整型变量或函数</span>
<span style="color: #993333;">long</span>          <span style="color: #666666; font-style: italic;">//声明长整型变量或函数</span>
<span style="color: #993333;">short</span>         <span style="color: #666666; font-style: italic;">//声明短整型变量或函数</span>
<span style="color: #993333;">signed</span>       <span style="color: #666666; font-style: italic;">//声明有符号类型变量或函数</span>
<span style="color: #993333;">struct</span>        <span style="color: #666666; font-style: italic;">//声明结构体变量或函数</span>
<span style="color: #993333;">union</span>         <span style="color: #666666; font-style: italic;">//声明共用体数据类型</span>
<span style="color: #993333;">unsigned</span>     <span style="color: #666666; font-style: italic;">//声明无符号类型变量或函数</span>
<span style="color: #993333;">void</span>           <span style="color: #666666; font-style: italic;">//声明函数无返回值或无参数，声明无类型指针</span></pre></div></div>

<p>这一类别的关键字无需过多的说明，基本都是我们经常用到的，但是，<span style="color: #ff0000;">仍然有些是我们需要注意的东西</span>：</p>
<ol>
<li>C 标准并未定义指针、整数型（int）、长型（long）为特定的位数目。在32位体系结构下，一般int和long都是32位长；值得注意的是，64位机器下，很多程序设计环境，“int”变量仍然是 32 位宽，“long”和指针是 64 位宽。注意，<span style="color: #ff0000;">这里说的只是一般情况下</span>！详细的解释可以看<a href="http://baike.baidu.com/view/125381.htm">这里</a>。</li>
<li>union声明的联合数据结构，里面的数据是共享内存的，可以看<a href="http://www.spongeliu.com/clanguage/%E8%84%91%E8%A2%8B%E4%B8%80%E8%BF%B7%E7%B3%8A%EF%BC%8C%E4%BA%BA%E5%B0%B1%E5%AE%B9%E6%98%93%E7%8A%AF%E4%BA%8C-union%E9%A2%98%E7%9B%AE/">我的另一篇日志</a>。</li>
<li>unsigned声明的是一个无符号数据类型，也就是说，如果unsigned int i; 需要注意变量i永远不可能等于复数，除非强制类型转换。</li>
</ol>
<p><span style="color: #ff0000;"><strong>第二类：控制语句关键字</strong></span></p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #b1b100;">for</span>         <span style="color: #666666; font-style: italic;">//循环语句</span>
<span style="color: #b1b100;">do</span>         <span style="color: #666666; font-style: italic;">//循环语句的循环体</span>
<span style="color: #b1b100;">while</span>      <span style="color: #666666; font-style: italic;">//循环语句的循环条件</span>
<span style="color: #000000; font-weight: bold;">break</span>     <span style="color: #666666; font-style: italic;">//跳出当前循环</span>
<span style="color: #b1b100;">continue</span> <span style="color: #666666; font-style: italic;">//结束当前循环，开始下一次循环</span>
<span style="color: #b1b100;">if</span>           <span style="color: #666666; font-style: italic;">//条件分支语句</span>
<span style="color: #b1b100;">else</span>       <span style="color: #666666; font-style: italic;">//条件分支语句</span>
<span style="color: #b1b100;">goto</span>      <span style="color: #666666; font-style: italic;">//无条件跳转语句</span>
<span style="color: #b1b100;">switch</span>    <span style="color: #666666; font-style: italic;">//不解释</span>
<span style="color: #b1b100;">case</span>      <span style="color: #666666; font-style: italic;">//不解释</span>
<span style="color: #b1b100;">default</span>    <span style="color: #666666; font-style: italic;">//不解释</span>
<span style="color: #b1b100;">return</span>     <span style="color: #666666; font-style: italic;">//返回语句</span></pre></div></div>

<p>这些关键字估计都快被用烂了吧？不解释！</p>
<p><strong><span style="color: #ff0000;">下面，开始做点有意义的事情，着重解释以下的关键字：</span></strong></p>
<p><span style="color: #ff0000;"><strong>第三类：存储类型关键字 </strong></span></p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">auto</span>
<span style="color: #000000; font-weight: bold;">extern</span>
<span style="color: #993333;">register</span>
<span style="color: #993333;">static</span></pre></div></div>

<p>让我们一一来看这四个关键字：</p>
<p><span style="color: #ff0000;">1、auto关键字：</span> 声明变量的生存期为自动，即将不在任何类、结构、枚举、联合和函数中定义的变量视为全局变量，而在函数中定义的变量视为局部变量。不明白？无视他好了，编译器默认的缺省情况下，所有的变量都是auto的。</p>
<p><span style="color: #ff0000;">2、extern关键字：</span> 我们都知道，一个变量或函数，可以在a.c文件中定义，而在b.c文件中使用，这个时候，b.c就需要使用extern关键字来声明这个变量和函数，目的是为了告诉编译器，这个函数在b.c之外，别让我编译不过！</p>
<p><span style="color: #ff0000;">3、register关键字：</span> 这个关键字就很少用到了，但是却十分有用。它的目的是告诉编译器尽量把这个变量放到寄存器中，这样提高存取速度，但是不是能真的放到寄存器中却不一定，毕竟寄存器的数量是有限的。在我们的二进制翻译器中，这个关键字被巧妙的用于线程切换。</p>
<p><span style="color: #ff0000;">4、static关键字：</span> 好吧，我承认我土了，我就是栽在这个关键字上的。static有两种修饰，分别如下：</p>
<p>(1)<span style="color: #ff0000;">修饰变量</span>：变量分为全局变量和静态变量，都存储在内存的静态区中。</p>
<p>首先，当static修饰全局变量的时候，<span style="color: #ff0000;">该变量的作用域仅被限定在当前文件中</span>，别的文件即使使用extern关键字也无法使用这个变量。</p>
<p>其次，当static修饰局部变量的时候，该变量在哪个函数体中定义，就只能在哪个函数体中使用。也许你会说，这不跟普通局部变量一样么？不一样！别忘了他是被存储在内存的静态区中<span style="color: #ff0000;">，所谓的静态区就是全局区</span>，用来存放全局变量和静态变量的，程序不结束，这个区是不会被释放的，所以即使定义静态局部变量的函数结束，改静态局部变量仍然存在，下次访问改函数的时候，这个变量的值仍然是上次的值！举个例子把：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">void</span> foo<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">static</span> <span style="color: #993333;">int</span> i<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    i<span style="color: #339933;">++;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    foo<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    foo<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>这个小例子的执行结果是什么呢？答案是：</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000;">1</span>
<span style="color: #000000;">2</span></pre></div></div>

<p>对的，静态局部变量只能被初始化一次，并且值会被保留，使用这个有两个好处，一个是可以计算函数被调用的次数，一个是可以减少函数构建局部变量的开销，自己体会一下把。</p>
<p>(2)<span style="color: #ff0000;">修饰函数：</span> 经常见这种形式，但没怎么用过，也就没去想。其实这个作用跟静态全局变量相似，也是限定函数的作用域为本文件。这样作的好处就是不用操心是否会跟别人编写的文件里的函数重名。（我这里栽了一下，太弱了～不甘心阿！）</p>
<p><strong><span style="color: #ff0000;">第四类：</span><span style="color: #ff0000;">其他关键字 </span></strong></p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">const</span>
<span style="color: #993333;">sizeof</span>
<span style="color: #993333;">typedef</span>
<span style="color: #993333;">volatile</span></pre></div></div>

<p>下面，也是一样，一一解释下这些关键字：</p>
<p><span style="color: #ff0000;">1、const关键字：</span> 这是一个很有意思的关键字，他修饰的变量是只读的，不能被修改；很多时候，编译器会将其优化成一个常量。const经常被用来修饰函数的参数，表示不希望这个参数值被函数体内的代码意外的改变。其实，<span style="color: #ff0000;">最有意思的是用const修饰一个指针</span>，让我们看下面这个例子：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">const</span> <span style="color: #993333;">int</span> <span style="color: #339933;">*</span>p<span style="color: #339933;">;</span>   <span style="color: #666666; font-style: italic;">//p可变，p指向的对象不可变</span>
<span style="color: #993333;">int</span> <span style="color: #993333;">const</span> <span style="color: #339933;">*</span>p<span style="color: #339933;">;</span>   <span style="color: #666666; font-style: italic;">//同上</span>
<span style="color: #993333;">int</span> <span style="color: #339933;">*</span><span style="color: #993333;">const</span> p<span style="color: #339933;">;</span>   <span style="color: #666666; font-style: italic;">//p不可变，p指向的对象可变</span>
<span style="color: #993333;">const</span> <span style="color: #993333;">int</span> <span style="color: #339933;">*</span><span style="color: #993333;">const</span> p<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//p和p指向的对象都不可变</span></pre></div></div>

<p>这些各表示什么呢？注释里面给出了答案！是不是很不好记？<span style="color: #ff0000;">我们只需要记得，const修饰的是*p的时候，p指向的内容不可变；const修饰的是p的时候，p就不可变！</span></p>
<p><span style="color: #ff0000;">2、sizeof关键字：</span>很多人也许会大吃一斤，我类个去，sizeof居然是关键字？（高手请无视这里，我当初就是这种表现）。不错，sizeof确实是关键字，而不是库函数！所以，如果编译时得不到一个数组的大小，那么就不能使用sizeof关键字来获取改数组的大小！</p>
<p><span style="color: #ff0000;">3、typedef关键字：</span> typedef说白了就是给一个已知的类型起一个外号。让我们考虑一个问题：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define PCHAR char*</span>
<span style="color: #993333;">typedef</span> <span style="color: #993333;">char</span><span style="color: #339933;">*</span> pchar<span style="color: #339933;">;</span></pre></div></div>

<p><span style="color: #ff0000;">这两个语句都是给char*类型起一个别名，那么哪个比较好呢</span>？ 要想知道答案，看下面：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">PCHAR p1<span style="color: #339933;">,</span> p2<span style="color: #339933;">;</span>
pchar p3<span style="color: #339933;">,</span> p4<span style="color: #339933;">;</span></pre></div></div>

<p>看代码的意思，我们是想将p1,p2,p3,p4都赋成char*类型的，但是，事实是如此么？<span style="color: #ff0000;">p2是么</span>？</p>
<p><span style="color: #ff0000;">注意，p2并没有预期成为一个char*类型，因为define会在预编译阶段展开，所以语句1就相当于 char* p1, p2；而在这条语句下，p2不是一个指针，而是一个char类型的！这个错误经常会被忽略，所以一定要注意！</span></p>
<p><span style="color: #ff0000;">4、volatile关键字：</span> 也许你见过这个关键字，但一般你都没有用过。哈哈，我用过！这个关键字表示改变量的值可能在外部被改变，编译器在用到这个变量时不能过度的优化，必须每次都重新从内存中读取这个变量的值，而不是将其优化在寄存器中。这个可以用来防止编译器优化产生的内存屏障，详细的看<a href="http://www.spongeliu.com/clanguage/memorybarrier/">这里</a>。</p>
<p>好吧，32个关键字介绍完了，我自恃很了解，也从中学了不少东西，但愿下次不要再犯这种低级的错误！没关系，一切都会好起来的！<span style="color: #ff0000;">Success is going from failure to failure without losing enthusiasm！<br />
</span></p>
<p>参考书目：<a href="http://www.amazon.cn/gp/product/B003XF3GQO/ref=as_li_tf_mfw?&#038;linkCode=wey&#038;tag=spongeliu-23" target="_blank">《C语言深度解剖:解开程序员面试笔试的秘密 》</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.spongeliu.com/clanguage/ckeyword/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>内存屏障什么的</title>
		<link>http://www.spongeliu.com/clanguage/memorybarrier/</link>
		<comments>http://www.spongeliu.com/clanguage/memorybarrier/#comments</comments>
		<pubDate>Wed, 27 Oct 2010 16:15:32 +0000</pubDate>
		<dc:creator>sponge</dc:creator>
				<category><![CDATA[C语言]]></category>
		<category><![CDATA[linux系统]]></category>
		<category><![CDATA[体系结构]]></category>
		<category><![CDATA[内存屏障]]></category>

		<guid isPermaLink="false">http://www.spongeliu.com/?p=233</guid>
		<description><![CDATA[当你看到“<span style="color: #ff0000;">内存屏障</span>”四个字的时候，你的第一反应是什么？寄存器里取出了错误的值？ifence,sfence之类的指令？还是诸如volatile之类的关键字？好吧，我第一次看到这四个字的时候，脑子里浮现出的是魔兽争霸里绿油油的铺满苔藓的<span style="color: #ff0000;">岩石屏障</span>－ －#，并且，当我搞明白内存屏障具体是什么，而且自认为对其很熟悉之后，我的第一反应依然是那几块绿油油的石头，而且很想上去A一把！

言归正传，先解释下什么是内存屏障。内存屏障是指“<span style="color: #ff0000;">由于编译器的优化和缓存的使用，导致对内存的写入操作不能及时的反应出来，也就是说当完成对内存的写入操作之后，读取出来的可能是旧的内容</span>”（摘自《独辟蹊径品内核》）。

概念就是概念，生硬的东西，懂的人能从中悟出点什么，不懂的人还是一头雾水。不要着急，我们先给内存屏障分下类，然后挨个来研究一番，等看完这篇文章，再回来读读概念，你就懂了！

<strong><span style="color: #ff0000;">内存屏障的分类：</span></strong>
<ol>
	<li>编译器引起的内存屏障</li>
	<li>缓存引起的内存屏障</li>
	<li>乱序执行引起的内存屏障</li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>当你看到“<span style="color: #ff0000;">内存屏障</span>”四个字的时候，你的第一反应是什么？寄存器里取出了错误的值？ifence,sfence之类的指令？还是诸如volatile之类的关键字？好吧，我第一次看到这四个字的时候，脑子里浮现出的是魔兽争霸里绿油油的铺满苔藓的<span style="color: #ff0000;">岩石屏障</span>－ －#，并且，当我搞明白内存屏障具体是什么，而且自认为对其很熟悉之后，我的第一反应依然是那几块绿油油的石头，而且很想上去A一把！</p>
<p>言归正传，先解释下什么是内存屏障。内存屏障是指“<span style="color: #ff0000;">由于编译器的优化和缓存的使用，导致对内存的写入操作不能及时的反应出来，也就是说当完成对内存的写入操作之后，读取出来的可能是旧的内容</span>”（摘自<a href="http://www.amazon.cn/exec/obidos/ASIN/B002JM12S6/spongeliu-23" target="_blank">《独辟蹊径品内核》</a>）。（这里概念貌似不是很准确，正确的定义：为了防止编译器和硬件的不正确优化，使得对存储器的访问顺序（其实就是变量）和书写程序时的访问顺序不一致而提出的一种解决办法。 它不是一种错误的现象，而是一种对错误现象提出的解决方发－－－－欢迎指正！！）</p>
<p>概念就是概念，生硬的东西，懂的人能从中悟出点什么，不懂的人还是一头雾水。不要着急，我们先给内存屏障分下类，然后挨个来研究一番，等看完这篇文章，再回来读读概念，你就懂了！</p>
<p><strong><span style="color: #ff0000;">内存屏障的分类：</span></strong></p>
<ol>
<li>编译器引起的内存屏障</li>
<li>缓存引起的内存屏障</li>
<li>乱序执行引起的内存屏障</li>
</ol>
<p><strong><span style="color: #ff0000;">1、编译器引起的内存屏障：</span></strong></p>
<p>我们都知道，从寄存器里面取一个数要比从内存中取快的多，所以有时候编译器为了编译出优化度更高的程序，就会把一些常用变量放到寄存器中，下次使用该变量的时候就直接从寄存器中取，而不再访问内存，这就出现了问题，当其他线程把内存中的值改变了怎么办？也许你会想，编译器怎么会那么笨，犯这种低级错误呢！是的，编译器没你想象的那么聪明！让我们看下面的代码：（代码摘自<a href="http://www.amazon.cn/exec/obidos/ASIN/B002JM12S6/spongeliu-23" target="_blank">《独辟蹊径品内核》</a>）</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> flag<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">void</span> wait<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span> flag <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span> <span style="color: #009900;">&#41;</span>
        sleep<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1000</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    ......
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">void</span> wakeup<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    flag<span style="color: #339933;">=</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>这段代码表示一个线程在循环等待另一个线程修改flag。 Gcc等编译器在编译的时候发现，sleep()不会修改flag的值，所以，为了提高效率，它就会把某个寄存器分配给flag，于是编译后就生成了这样的伪汇编代码：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">void</span> wait<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    movl  flag<span style="color: #339933;">,</span> <span style="color: #339933;">%</span>eax<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">%</span>eax <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
        sleep<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1000</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>这时，当wakeup函数修改了flag的值，wait函数还在傻乎乎的读寄存器的值而不知道其实flag已经改变了，线程就会死循环下去。由此可见，编译器的优化带来了相反的效果！</p>
<p>但是，你又不能说是让编译器放弃这种优化，因为在很多场合下，这种优化带来的性能是十分可观的！那我们该怎么办呢？有没有什么办法可以避免这种情况？答案必须是肯定的，<span style="color: #ff0000;">我们可以使用关键字volatile来避免这种情况</span>。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">volatile</span> <span style="color: #993333;">int</span> flag <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span></pre></div></div>

<p>这样，我们就能避免编译器把某个寄存器分配给flag了。</p>
<p>好，上面所描述这些，就叫做“编译器优化引起的内存屏障”，<span style="color: #ff0000;">是不是懂了点什么？再回去看看概念？</span></p>
<p><strong><span style="color: #ff0000;">2、缓存引起的内存屏障</span></strong></p>
<p>好，既然寄存器能够引起这样的问题，那么缓存呢？我们都知道，CPU会把数据取到一个叫做cache的地方，然后下次取的时候直接访问cache，写入的时候，也先将值写入cache。</p>
<p>那么，先让我们考虑，在单核的情况下会不会出现问题呢？先想一下，单核情况下，除了CPU还会有什么会修改内存？对了，是<span style="color: #ff0000;">外部设备的DMA</span>！那么，DMA修改内存，会不会引起内存屏障的问题呢？答案是，在现在的体系结构中，不会。</p>
<p>当外部设备的DMA操作结束的时候，会有一种机制保证CPU知道他对应的缓存行已经失效了；而当CPU发动DMA操作时，在想外部设备发送启动命令前，需要把对应cache中的内容写回内存。在大多数RISC的架构中，这种机制是通过一写个特殊指令来实现的。在X86上，采用一种叫做<span style="color: #ff0000;">总线监测技术</span>的方法来实现。就是CPU和外部设备访问内存的时候都需要经过总线的仲裁，有一个专门的硬件模块用于记录cache中的内存区域，当外部设备对内存写入的时候，就通过这个硬件来判断下改内存区域是否在cache中，然后再进行相应的操作。</p>
<p>那么，什么时候才能产生cache引起的内存屏障呢？<span style="color: #ff0000;">多CPU？</span> 是的，在多CPU的系统里面，每个CPU都有自己的cache，当同一个内存区域同时存在于两个CPU的cache中时，CPU1改变了自己cache中的值，但是CPU2却仍然在自己的cache中读取那个旧值，这种结果是不是很杯具呢？因为没有访存操作，总线也是没有办法监测的，这时候怎么办？</p>
<p>对阿，怎么办呢？我们需要在CPU2读取操作之前使自己的cache失效，x86下，很多指令能做到这点，<span style="color: #ff0000;">如lock前缀的指令，cpuid, iret等</span>。内核中使用了一些函数来完成这个功能：mb(), rmb(), wmb()。用的也是以上那些指令，感兴趣可以去看下内核代码。</p>
<p><span style="color: #ff0000;"><strong>3、乱序执行引起的内存屏障：</strong></span></p>
<p>我们都知道，超标量处理器越来越流行，连龙芯都是四发射的。超标量实际上就是一个CPU拥有多条独立的流水线，一次可以发射多条指令，因此，很多允许指令的乱序执行，具体怎么个乱序方法，可以去看体系结构方面的书，这里只说内存屏障。</p>
<p>指令乱序执行了，就会出现问题，假设指令1给某个内存赋值，指令2从该内存取值用来运算。如果他们两个颠倒了，指令2先从内存中取值运算，是不是就错了？</p>
<p><span style="color: #ff0000;">对于这种情况，x86上专门提供了lfence，sfence,和mfence 指令来停止流水线：</span></p>
<p>lfence:停止相关流水线，知道lfence之前对内存进行的读取操作指令全部完成</p>
<p>sfence:停止相关流水线，知道lfence之前对内存进行的写入操作指令全部完成</p>
<p>mfence:停止相关流水线，知道lfence之前对内存进行的读写操作指令全部完成</p>
<p>好，将完这三种类型，再回去看看概念，清晰了么？如果还不明白，那就是我的表达能力太有限了，自己网上再搜搜把！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spongeliu.com/clanguage/memorybarrier/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>一个百度笔试中的首尾相连的珠子问题解法</title>
		<link>http://www.spongeliu.com/%e7%ae%97%e6%b3%95/baidu2011/</link>
		<comments>http://www.spongeliu.com/%e7%ae%97%e6%b3%95/baidu2011/#comments</comments>
		<pubDate>Tue, 19 Oct 2010 16:30:59 +0000</pubDate>
		<dc:creator>sponge</dc:creator>
				<category><![CDATA[笔试面试]]></category>
		<category><![CDATA[算法]]></category>
		<category><![CDATA[动态规划]]></category>
		<category><![CDATA[百度笔试]]></category>
		<category><![CDATA[百度面试]]></category>
		<category><![CDATA[首尾相连的珠子]]></category>

		<guid isPermaLink="false">http://www.spongeliu.com/?p=221</guid>
		<description><![CDATA[之所以说是一个解法，是因为这是我暂时能想到的线性时间复杂度的算法，需要遍历约2m遍，这里把算法列出来，仅供参考。
<h2><span style="color: #ff0000;">题目：</span></h2>
有一串首尾相连的珠子，共有m个，每一个珠子有一种颜色，并且颜色的总数不超过n(n&#60;=10)，求连续的珠子的颜色总数为n时，长度最小的区间。可简述思路或者给出伪代码，并且给出时间和空间复杂度分析。（baidu 2011校园招聘笔试题目）

拿到这个题目，我首先想到的是<span style="color: #ff0000;">暴力搜索</span>。即对每个珠子，都搜索以该珠子为结尾的最短符合题意的序列。但是这样比较的时间复杂度特别高，应该是m的指数，显然是不可取的，通过简单的分析我们能够发现，在搜索过程中，我们进行了许多冗余的比较。本着空间换时间的想法，我们有没有办法把这些比较记录下来，然后去掉这些冗余呢？答案是肯定的。
]]></description>
			<content:encoded><![CDATA[<p>之所以说是一个解法，是因为这是我暂时能想到的线性时间复杂度的算法，需要遍历约2m遍，这里把算法列出来，仅供参考。</p>
<h2><span style="color: #ff0000;">题目：</span></h2>
<p>有一串首尾相连的珠子，共有m个，每一个珠子有一种颜色，并且颜色的总数不超过n(n&lt;=10)，求连续的珠子的颜色总数为n时，长度最小的区间。可简述思路或者给出伪代码，并且给出时间和空间复杂度分析。（baidu 2011校园招聘笔试题目）</p>
<p>拿到这个题目，我首先想到的是<span style="color: #ff0000;">暴力搜索</span>。即对每个珠子，都搜索以该珠子为结尾的最短符合题意的序列。但是这样比较的时间复杂度特别高，应该是m的指数，显然是不可取的，通过简单的分析我们能够发现，在搜索过程中，我们进行了许多冗余的比较。本着空间换时间的想法，我们有没有办法把这些比较记录下来，然后去掉这些冗余呢？答案是肯定的。</p>
<p><span style="color: #ff0000;">我想到的一个算法，里面用到了一些动态规划的思想，可以在线性时间内完成题目</span>。首先为了方便描述，让我们假设珠子不是首尾相连。让我们以数组a[m]来表示珠子的序列，用1-n数字来表示颜色，则算法思路如下：</p>
<ol>
<li>定义一个数组least[m]；对于a[i]的元素，least[i]表示珠子序列中以珠子a[i]为结尾的包含所有颜色的最短序列的长度；</li>
<li>定义一个数组save[n+1]; 这个数组的元素save[i]表示颜色i上一次出现的位置，初始化为－1；注意这里的i表示颜色而不是珠子！</li>
<li>定义一个数组next[m]；对于a[i]的元素，next[i]表示当前珠子的颜色下一次出现的位置；初始化为－1；</li>
<li>定义两个指针 i 和 j ，初始化为0，即指向a[0]；</li>
<li>首先遍历一遍a[m]，将每个珠子的颜色下一次出现的位置填充到next[i]中；具体做法是利用数组save[n+1]保存颜色c上一次出现的位置d，当再次出现c时，将next[d]设置为当前位置。这部分可以在O(m)时间内完成，具体代码中还可以优化。</li>
<li>将指针j向右滑动</li>
<li>判断 i&lt;j 和 ( a[i]==a[j] 或者 next[i] &lt; j ) 两个条件是否成立，如果不成立，least[j]=j-i+1 ，然后执行6；如果成立，i++，继续执行7。（ 判断a[i]==a[j]是因为如果a[i]==a[j]，则a[i]-a[j]之间的序列不够成最短序列；判断next[i]&lt;j的因为在a[i]到a[j]之间存在颜色a[i]，因此a[i]也不应该被包括在最短序列里。）</li>
<li>如果j = n，则遍历完成，找到least[m]中最小的数的位置，则就能找到符合题意的最小序列。</li>
</ol>
<p>当然，我们需要考虑到珠子首尾相连。我们可以让j=n之后，从0开始重新循环，直到 i=n 或 j到达位置s，位置s表示从a[0]开始，第一个出现所有颜色的位置。</p>
<p>下面是我使用C语言实现的代码，在实际代码中，next[j]我是一边挪动 j 一边填充的。代码如下：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdio.h&gt;</span>
<span style="color: #339933;">#define CNUMBER 4   //颜色的个数</span>
<span style="color: #993333;">int</span> find<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: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #993333;">int</span> number <span style="color: #339933;">=</span> CNUMBER<span style="color: #339933;">;</span>  <span style="color: #666666; font-style: italic;">//定义一个计数器，目的是找到上面所说的第一个出现所有颜色的位置s</span>
	<span style="color: #993333;">int</span> save<span style="color: #009900;">&#91;</span>number<span style="color: #339933;">+</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>  <span style="color: #666666; font-style: italic;">//颜色上一次出现的位置</span>
	<span style="color: #993333;">int</span> next<span style="color: #009900;">&#91;</span>n<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>  <span style="color: #666666; font-style: italic;">//元素颜色下一次出现的位置 </span>
	<span style="color: #993333;">int</span> least<span style="color: #009900;">&#91;</span>n<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>  <span style="color: #666666; font-style: italic;">//以该元素结尾的最短序列</span>
	<span style="color: #993333;">int</span> i<span style="color: #339933;">,</span> j<span style="color: #339933;">;</span>
	<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>i<span style="color: #339933;">&lt;</span>CNUMBER<span style="color: #339933;">+</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>  <span style="color: #666666; font-style: italic;">//初始化</span>
		save<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">=-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>i<span style="color: #339933;">&lt;</span>n<span style="color: #339933;">;</span>i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>  <span style="color: #666666; font-style: italic;">//初始化</span>
		next<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">=-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>j<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>j<span style="color: #339933;">&lt;</span>n<span style="color: #339933;">;</span>j<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>number<span style="color: #339933;">!=</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>  
			least<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #339933;">=-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>  <span style="color: #666666; font-style: italic;">//将还没有出现所有颜色的位置的least设为－1，下面会用到</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>save<span style="color: #009900;">&#91;</span>a<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">==-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> <span style="color: #666666; font-style: italic;">//save[i]为-1表明该颜色i第一次出现</span>
			save<span style="color: #009900;">&#91;</span>a<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span>j<span style="color: #339933;">;</span> 
			number<span style="color: #339933;">--;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
			next<span style="color: #009900;">&#91;</span>save<span style="color: #009900;">&#91;</span>a<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span>j<span style="color: #339933;">;</span>  <span style="color: #666666; font-style: italic;">//设置next</span>
			save<span style="color: #009900;">&#91;</span>a<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span>j<span style="color: #339933;">;</span>  <span style="color: #666666; font-style: italic;">//把save[i]设为当前位置，用于下一次使用</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">&lt;</span>j<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>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">==</span>a<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #339933;">||</span>next<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">!=-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">//i++的条件</span>
				i<span style="color: #339933;">++;</span>
			<span style="color: #b1b100;">else</span>
				<span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>number <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span> <span style="color: #009900;">&#41;</span>
			least<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span>j<span style="color: #339933;">-</span>i<span style="color: #339933;">+</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//计算least</span>
&nbsp;
	<span style="color: #009900;">&#125;</span>
&nbsp;
	j<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>least<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #339933;">==-</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">&amp;&amp;</span>i<span style="color: #339933;">&lt;</span>n <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> <span style="color: #666666; font-style: italic;">//这个循环的目的是为了满足首尾相接的条件而让j从头开始</span>
		next<span style="color: #009900;">&#91;</span>save<span style="color: #009900;">&#91;</span>a<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span>j<span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">&lt;</span>n<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>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">==</span>a<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #339933;">||</span><span style="color: #009900;">&#40;</span>next<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">&gt;</span>i<span style="color: #339933;">||</span>next<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">&lt;</span>j<span style="color: #009900;">&#41;</span><span style="color: #339933;">&amp;&amp;</span>next<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">!=-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span>
                        <span style="color: #666666; font-style: italic;">//next[i]&gt;i||next[i]&lt;j 表示a[i]表示的颜色下次出现在i和j之间</span>
				i<span style="color: #339933;">++;</span>
			<span style="color: #b1b100;">else</span>
				<span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
&nbsp;
		least<span style="color: #009900;">&#91;</span>j<span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span>j<span style="color: #339933;">+</span>n<span style="color: #339933;">-</span>i<span style="color: #339933;">+</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
&nbsp;
		j<span style="color: #339933;">++;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>i<span style="color: #339933;">&lt;</span>n<span style="color: #339933;">;</span>i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
		<span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d &quot;</span><span style="color: #339933;">,</span> least<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//我这里最终将所有least打印出来，可以更改下让把符合题意的序列打印出来</span>
	<span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #993333;">int</span> n<span style="color: #339933;">;</span>
	<span style="color: #993333;">int</span> a<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">100</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	scanf<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d&quot;</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>n<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//n表示珠子的长度</span>
	<span style="color: #993333;">int</span> i<span style="color: #339933;">;</span>
	<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>i<span style="color: #339933;">&lt;</span>n<span style="color: #339933;">;</span>i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
		scanf<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d&quot;</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>a<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//输入珠子</span>
	find<span style="color: #009900;">&#40;</span>a<span style="color: #339933;">,</span> n<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>当然，这个算法未必就是一个很好的算法，如果你有更好的方法，欢迎留言讨论。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spongeliu.com/%e7%ae%97%e6%b3%95/baidu2011/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>结构体的sizeof到底多大？</title>
		<link>http://www.spongeliu.com/clanguage/sizeof-struct/</link>
		<comments>http://www.spongeliu.com/clanguage/sizeof-struct/#comments</comments>
		<pubDate>Tue, 19 Oct 2010 13:56:26 +0000</pubDate>
		<dc:creator>sponge</dc:creator>
				<category><![CDATA[C语言]]></category>
		<category><![CDATA[体系结构]]></category>
		<category><![CDATA[笔试面试]]></category>
		<category><![CDATA[sizeof]]></category>
		<category><![CDATA[内存对齐]]></category>
		<category><![CDATA[结构体]]></category>

		<guid isPermaLink="false">http://www.spongeliu.com/?p=218</guid>
		<description><![CDATA[文章开始，先看一个结构体的代码：   //爱立信2011笔试   360 2011笔试均涉及
<pre lang="c">
struct node{
    int a;
    int b;
};
</pre>
问：<span style="color: #ff0000;">sizeof(Node)是多少？</span> 答案很简单，在32位机器上，一个int是4个字节，两个int就是8个字节，sizeof(Node)就是8。

好的，上面那个答案确实是8，那么再看下面这个结构体：
<pre lang="c">
struct node{
    char a;
    int b;
};
</pre>
问：这个时候<span style="color: #ff0000;">sizeof(Node)又是多少呢？</span> int是4个字节，char是1个字节，答案是5？]]></description>
			<content:encoded><![CDATA[<p>文章开始，先看一个结构体的代码：   //爱立信2011笔试   360 2011笔试均涉及</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> node<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> a<span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> b<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>

<p>问：<span style="color: #ff0000;">sizeof(Node)是多少？</span> 答案很简单，在32位机器上，一个int是4个字节，两个int就是8个字节，sizeof(Node)就是8。</p>
<p>好的，上面那个答案确实是8，那么再看下面这个结构体：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> node<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">char</span> a<span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> b<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>

<p>问：这个时候<span style="color: #ff0000;">sizeof(Node)又是多少呢？</span> int是4个字节，char是1个字节，答案是5？</p>
<p>这回，没有那么幸运，经过在机器上的操作，<span style="color: #ff0000;">答案是8</span>！ Why？</p>
<p>实际上，这不是语言的问题，你在ANSI C中找不到为什么会这样！甚至你在不同的体系结构、不同的编译器下会得到不同的答案。那么，到底是谁把5改成了8呢？</p>
<p>这就引入了一个概念，叫做“内存对齐”。所谓的内存对齐，是指一种计算机体系结构（如X86）对基本数据类型的存储位置有限制，要求其地址为某个数的倍数，通常这个数为4或8。这种要求会简化处理器的设计以及提升数据访问的效率。至于为什么会有这样的设计，简单的说访存总线的位数固定，以32位总线为例，地址总线的地址总是4对齐的，所以数据也四对齐的话，一个周期内就可以把数据读出。这里不理解的话可以跳过去，只要记得对齐这回事儿就行了。如果想更深入的理解，可以看<a href="http://my.unix-center.net/~Simon_fu/?p=262">这里另一篇文章</a>。</p>
<p>知道这个之后，那么我们就可以理解，<span style="color: #ff0000;">实际上是编译器为了效率，在相邻的变量之间放置了一些填充字节来保证数据的对齐</span>。X86结构是4对齐的，所以sizeof(Node)是8不是5。</p>
<p>再来看一个例子：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> node<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> a<span style="color: #339933;">;</span>
    <span style="color: #993333;">char</span> b<span style="color: #339933;">;</span>
    <span style="color: #993333;">char</span> c<span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> d<span style="color: #339933;">;</span>
    <span style="color: #993333;">char</span> d<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>

<p>这时的sizeof(Node)是多少呢？没错，是16。</p>
<p>好的，<span style="color: #ff0000;">既然我们知道对齐是由编译器来作的，那么我们可不可以更改对齐数呢？</span> 答案是可以的，在C语言中，我们可以通过</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#pragma pack(n)</span></pre></div></div>

<p>来更改对齐模数。</p>
<p>注：以上都是在现x86 linux下使用gcc编译器验证，不乏有其他系统和编译器会得到不同的结果。</p>
<p>再让我们来看个例子：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">        <span style="color: #993333;">struct</span> node <span style="color: #009900;">&#123;</span>
                <span style="color: #993333;">double</span> a<span style="color: #339933;">;</span>
                <span style="color: #993333;">int</span> b<span style="color: #339933;">;</span>
                <span style="color: #993333;">int</span> c<span style="color: #339933;">;</span>
                <span style="color: #993333;">char</span> d<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>

<p>这个时候的sizeof(node)是多少？20？24？</p>
<p>其实，这个时候你会发现，当你在windows上使用VC编译的时候，你会得到24；当你在linux上使用gcc编译的时候，你会得到20！其实，这恰好说明这种数据的对齐是由编译器决定的！<span style="color: #ff0000;">在VC中规定， 结构体变量的首地址能够被其最宽基本类型成员的大小所整除；而在gcc中规定对齐模数最大只能是4，也就是说，即使结构体中有double类型，对齐模数还是4，所以数据是按照1，2，4对齐的。</span>所以，在两个不同编译器上，你得到了不同的答案！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spongeliu.com/clanguage/sizeof-struct/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>打印经过限定后的数字排列</title>
		<link>http://www.spongeliu.com/%e7%ae%97%e6%b3%95/%e6%89%93%e5%8d%b0%e7%bb%8f%e8%bf%87%e9%99%90%e5%ae%9a%e5%90%8e%e7%9a%84%e6%95%b0%e5%ad%97%e6%8e%92%e5%88%97/</link>
		<comments>http://www.spongeliu.com/%e7%ae%97%e6%b3%95/%e6%89%93%e5%8d%b0%e7%bb%8f%e8%bf%87%e9%99%90%e5%ae%9a%e5%90%8e%e7%9a%84%e6%95%b0%e5%ad%97%e6%8e%92%e5%88%97/#comments</comments>
		<pubDate>Mon, 18 Oct 2010 06:13:20 +0000</pubDate>
		<dc:creator>sponge</dc:creator>
				<category><![CDATA[笔试面试]]></category>
		<category><![CDATA[算法]]></category>
		<category><![CDATA[sohu笔试]]></category>
		<category><![CDATA[排列组合]]></category>

		<guid isPermaLink="false">http://www.spongeliu.com/?p=204</guid>
		<description><![CDATA[题目：给定6个数字，1，2，2，3，4，5，打印所有的排列

要求：
<ol>
	<li>所有的4均不会出现在排列的第4个位置</li>
	<li>数字3和数字5不能相邻</li>
	<li>排列不能重复。</li>
</ol>
实现思想：

采用回朔的方法便利所有可能的排列，其中把不符合题目要求的去除。需要额外注意的是，数字中出现了两个2，如果单纯的遍历，会打印两次2在某个位置的排列，要注意把这个重复给去除。]]></description>
			<content:encoded><![CDATA[<p>题目：给定6个数字，1，2，2，3，4，5，打印所有的排列</p>
<p>要求：</p>
<ol>
<li>所有的4均不会出现在排列的第4个位置</li>
<li>数字3和数字5不能相邻</li>
<li>排列不能重复。</li>
</ol>
<p>实现思想：</p>
<p>采用回朔的方法便利所有可能的排列，其中把不符合题目要求的去除。需要额外注意的是，数字中出现了两个2，如果单纯的遍历，会打印两次2在某个位置的排列，要注意把这个重复给去除。</p>
<p>C语言代码实现如下：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include&lt;stdlib.h&gt;</span>
<span style="color: #339933;">#include&lt;stdio.h&gt;</span>
&nbsp;
<span style="color: #993333;">int</span> a<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">6</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #009900;">&#123;</span><span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">2</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">2</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">3</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">4</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">5</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span> 
<span style="color: #993333;">int</span> b<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">6</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//用来存放排列好的序列</span>
<span style="color: #993333;">int</span> pointer<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//回朔指针</span>
<span style="color: #993333;">int</span> total<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//总的排列个数</span>
<span style="color: #993333;">int</span> range<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #993333;">int</span> i<span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>pointer <span style="color: #339933;">==</span> <span style="color: #0000dd;">6</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
		<span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;total:%d, range: %d %d %d %d %d %d <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> 
		<span style="color: #339933;">++</span>total<span style="color: #339933;">,</span> b<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> b<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> b<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> b<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> b<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> b<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">5</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">=</span><span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i<span style="color: #339933;">&lt;</span><span style="color: #0000dd;">6</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><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>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
			<span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">!=</span><span style="color: #0000dd;">0</span> <span style="color: #339933;">&amp;&amp;</span> i<span style="color: #339933;">==</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#41;</span>
			<span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//防止重复使用2</span>
&nbsp;
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>pointer<span style="color: #339933;">&gt;</span><span style="color: #0000dd;">0</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span>b<span style="color: #009900;">&#91;</span>pointer<span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">==</span><span style="color: #0000dd;">3</span> <span style="color: #339933;">&amp;&amp;</span> a<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">5</span> 
		   <span style="color: #339933;">||</span> b<span style="color: #009900;">&#91;</span>pointer<span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">==</span><span style="color: #0000dd;">5</span> <span style="color: #339933;">&amp;&amp;</span> a<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">==</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">//防止3,5相邻</span>
			<span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>pointer <span style="color: #339933;">==</span> <span style="color: #0000dd;">3</span> <span style="color: #339933;">&amp;&amp;</span> a<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">==</span><span style="color: #0000dd;">4</span><span style="color: #009900;">&#41;</span>
			<span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//防止数字4出现在位置4</span>
&nbsp;
		b<span style="color: #009900;">&#91;</span>pointer<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> a<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
		pointer <span style="color: #339933;">++;</span>
		a<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//使用过的数字给设置成0，防止重复使用</span>
		range<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		pointer <span style="color: #339933;">--;</span>
		a<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> b<span style="color: #009900;">&#91;</span>pointer<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>		
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	range<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>	
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>这个题目是sohu2011笔试题，题目并不难，关键是细节要考律全面，如要去除因为两个2而导致的重复序列。<br />
我在笔试卷子上写的乱七八糟，而一在电脑上立马就写出来了，果然还是很不擅长笔试阿！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.spongeliu.com/%e7%ae%97%e6%b3%95/%e6%89%93%e5%8d%b0%e7%bb%8f%e8%bf%87%e9%99%90%e5%ae%9a%e5%90%8e%e7%9a%84%e6%95%b0%e5%ad%97%e6%8e%92%e5%88%97/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

