<?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>Dutor &#187; 之语言特性</title>
	<atom:link href="http://www.dutor.net/index.php/category/program/language/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dutor.net</link>
	<description>熟读而精思，循序而渐进，厚积而薄发。</description>
	<lastBuildDate>Tue, 17 Jan 2012 14:44:19 +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>[C++]对象中使用pthread线程</title>
		<link>http://www.dutor.net/index.php/2011/11/pthread-in-cpp-class/</link>
		<comments>http://www.dutor.net/index.php/2011/11/pthread-in-cpp-class/#comments</comments>
		<pubDate>Fri, 18 Nov 2011 08:50:37 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[pthread]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2671</guid>
		<description><![CDATA[　　我们还知道，类的静态成员函数是不需要绑定到特定对象上面的，所以我们就可以将worker声明为静态成员。
<pre lang="cpp" line="1">
class Thread
{
public:
    static void* worker(void* args) {
        //~ thread execution.
    }
private:
    //~ here some data member.
};
pthread_t tid;
pthread_create(&#038;tid, NULL, &#038;Thread::worker, NULL);
</pre>
　　我们又知道，静态成岩函数是不能'直接'访问类的非静态成员（包括函数），因此，上面代码中worker即使属于class Thread的类域，但却无法访问这个类的成员，这让人十分不爽。哪位大牛说过来着？任何一个复杂的计算机问题，都可以通过中间层来解决。这里也可以建立一个中间层：使用静态成员函数创建线程，给该函数传递某个对象的地址作为参数，在该静态函数中就可以通过所传递对象的使用它的任何成员了。]]></description>
			<content:encoded><![CDATA[<p>pthread中使用pthread_create创建线程：</p>

<div class="wp_codebox"><table><tr id="p26711"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p2671code1"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> worker<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span> <span style="color: #000040;">*</span>args<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #666666;">//~ thread execution.</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
pthread_t tid<span style="color: #008080;">;</span>
<span style="color: #666666;">//~ pthread_create(pthread_t*, pthread_attr_t*, void*(*)(void*), void*);</span>
pthread_create<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>tid, <span style="color: #0000ff;">NULL</span>, worker, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>　　其中，线程函数worker就是所创建线程将要执行的代码。当然，由于同一进程中各线程的代码段是共享的，所以在线程函数中可以像普通函数那样合法地调用其他函数。<br />
　　有时候，我们可能想要将一个类的成员函数作为一个单独的线程来执行，甚至在某个类中控制线程的执行。但我们并不能直接使用成员函数来创建线程，像下面一样，</p>

<div class="wp_codebox"><table><tr id="p26712"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p2671code2"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> Thread
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> worker<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> args<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #666666;">//~ thread execution.</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    <span style="color: #666666;">//~ here some data member.</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
pthread_t tid<span style="color: #008080;">;</span>
pthread_create<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>tid, <span style="color: #0000ff;">NULL</span>, <span style="color: #000040;">&amp;</span>Thread<span style="color: #008080;">::</span><span style="color: #007788;">worker</span>, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>　　编译上面代码，会得到类似</p>
<pre>
error: cannot convert ‘void* (Thread::*)(void*)’ to ‘void* (*)(void*)’ for argument ‘3’ to
‘int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)’
</pre>
<p>的错误信息，意思是说，对于pthread_create的第三个参数，无法将void* (Thread::*)(void*)转化为void* (*)(void*)类型。我们知道，类的普通成员函数的执行是绑定到某一个具体的对象上面的，除了我们声明的参数之外，还需要一个&#8217;多余&#8217;的参数this来指明该函数的本次执行所绑定到的对象。<br />
　　我们还知道，类的静态成员函数是不需要绑定到特定对象上面的，所以我们就可以将worker声明为静态成员。</p>

<div class="wp_codebox"><table><tr id="p26713"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p2671code3"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> Thread
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> worker<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> args<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #666666;">//~ thread execution.</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    <span style="color: #666666;">//~ here some data member.</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
pthread_t tid<span style="color: #008080;">;</span>
pthread_create<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>tid, <span style="color: #0000ff;">NULL</span>, <span style="color: #000040;">&amp;</span>Thread<span style="color: #008080;">::</span><span style="color: #007788;">worker</span>, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>　　我们又知道，静态成岩函数是不能&#8217;直接&#8217;访问类的非静态成员（包括函数），因此，上面代码中worker即使属于class Thread的类域，但却无法访问这个类的成员，这让人十分不爽。哪位大牛说过来着？任何一个复杂的计算机问题，都可以通过中间层来解决。这里也可以建立一个中间层：使用静态成员函数创建线程，给该函数传递某个对象的地址作为参数，在该静态函数中就可以通过所传递对象的使用它的任何成员了。<br />
　　我比较喜欢使用的是类似这样的一个抽象类，</p>

<div class="wp_codebox"><table><tr id="p26714"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code" id="p2671code4"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> Thread
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">virtual</span> ~Thread<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    pthread_t start<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        pthread_t tid<span style="color: #008080;">;</span>
        pthread_create<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>tid, <span style="color: #0000ff;">NULL</span>, hook, <span style="color: #0000dd;">this</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> tid<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> hook<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> args<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">reinterpret_cast</span><span style="color: #000080;">&lt;</span>Thread<span style="color: #000040;">*</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>args<span style="color: #008000;">&#41;</span><span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>worker<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">protected</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> worker<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>继承这个类，实现worker函数就行了。调用start启动线程，各线程共享对象的数据。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2011/11/pthread-in-cpp-class/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>关于变参</title>
		<link>http://www.dutor.net/index.php/2011/08/variadic/</link>
		<comments>http://www.dutor.net/index.php/2011/08/variadic/#comments</comments>
		<pubDate>Sun, 07 Aug 2011 02:32:20 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[可变参数]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2626</guid>
		<description><![CDATA[<h4>使用变参</h4>
　　C/C++提供了函数的可变参数(variadic)机制，大部分人写的第一个C程序恐怕就是Hello World吧，使用的应该也是printf("Hello, World\n")。printf就是一个使用可变参数的典型，它的原型声明为，
<pre lang="C">
int printf(const char *fmt, ...);
</pre>
　　其中返回值为实际输出字符个数，fmt为格式控制字符串，而"..."便声明了一个可变参数，你可以根据传递0个或多个参数给printf。printf内部会根据格式控制串中的格式指定符号（d, f, p等等）来逐个解析通过可变参数传进的实参变量。
　　为解析可变参数，C语言提供了一个va_list类型和四个宏，分别是va_start, va_arg, va_end, 和va_copy，这些宏声明在stdarg.h中。]]></description>
			<content:encoded><![CDATA[<h4>使用变参</h4>
<p>　　C/C++提供了函数的可变参数(variadic)机制，大部分人写的第一个C程序恐怕就是Hello World吧，使用的应该也是printf(&#8220;Hello, World\n&#8221;)。printf就是一个使用可变参数的典型，它的原型声明为，</p>

<div class="wp_codebox"><table><tr id="p26265"><td class="code" id="p2626code5"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>fmt<span style="color: #339933;">,</span> ...<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>　　其中返回值为实际输出字符个数，fmt为格式控制字符串，而&#8221;&#8230;&#8221;便声明了一个可变参数，你可以根据传递0个或多个参数给printf。printf内部会根据格式控制串中的格式指定符号（d, f, p等等）来逐个解析通过可变参数传进的实参变量。<br />
　　为解析可变参数，C语言提供了一个va_list类型和四个宏，分别是va_start, va_arg, va_end, 和va_copy，这些宏声明在stdarg.h中。为了方便描述，下面实现一个简单的类似printf的函数：</p>

<div class="wp_codebox"><table><tr id="p26266"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
</pre></td><td class="code" id="p2626code6"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">void</span> mockprintf<span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>fmt<span style="color: #339933;">,</span> ...<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    va_list ap<span style="color: #339933;">;</span>
    va_start<span style="color: #009900;">&#40;</span>ap<span style="color: #339933;">,</span> fmt<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>s <span style="color: #339933;">=</span> fmt<span style="color: #339933;">;</span> <span style="color: #339933;">*</span>s<span style="color: #339933;">;</span> <span style="color: #339933;">++</span>s<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">switch</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span>s<span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">case</span> <span style="color: #ff0000;">'d'</span><span style="color: #339933;">:</span>
                <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;meet d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #993333;">int</span> d <span style="color: #339933;">=</span> va_arg<span style="color: #009900;">&#40;</span>ap<span style="color: #339933;">,</span> <span style="color: #993333;">int</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> d<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">case</span> <span style="color: #ff0000;">'s'</span><span style="color: #339933;">:</span>
                <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;meet s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str <span style="color: #339933;">=</span> va_arg<span style="color: #009900;">&#40;</span>ap<span style="color: #339933;">,</span> <span style="color: #993333;">char</span><span style="color: #339933;">*</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;%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> str<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">case</span> <span style="color: #ff0000;">'c'</span><span style="color: #339933;">:</span>
                <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;meet c<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #993333;">char</span> c <span style="color: #339933;">=</span> va_arg<span style="color: #009900;">&#40;</span>ap<span style="color: #339933;">,</span> <span style="color: #993333;">int</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;%c<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> c<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">default</span><span style="color: #339933;">:</span>
                <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;unknown format specifier<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    va_end<span style="color: #009900;">&#40;</span>ap<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>
    mockprintf<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;cdfs&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">'A'</span><span style="color: #339933;">,</span> <span style="color: #208080;">0x45</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;string&quot;</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></td></tr></table></div>

<p>　　va_list的实现与编译器和平台相关，通常是一个指向参数栈的指针。va_start使用变参列表前的最后一个命名参数（named argument）作为参数，以此定位变参列表的第一个参数的地址，并将ap指向该参数（此处假设va_list实现为指针）。宏va_arg需要两个参数，va_list变量和下一个预期的参数的类型，该宏以指定类型返回（展开为）对应的参数值，并调整va_list指向下一个参数。最后，每一个va_start需要一个va_end作为结束。另外，示例函数中没有用到va_copy，这是一个用来复制va_list变量到另一个va_list变量的宏，目的是应对平台间va_list实现的差异。<br />
　　值得一提的是，va_start和va_end可以重复调用，用以多次对变参列表进行解析。</p>
<h4>printf家族</h4>
<p>　　C的printf家族包含8个成员，原型如下，</p>

<div class="wp_codebox"><table><tr id="p26267"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p2626code7"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdio.h&gt;</span>
<span style="color: #993333;">int</span> <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>fmt<span style="color: #339933;">,</span> ...<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">int</span> fprintf<span style="color: #009900;">&#40;</span>FILE <span style="color: #339933;">*</span>stream<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>fmt<span style="color: #339933;">,</span> ...<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">int</span> sprintf<span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>fmt<span style="color: #339933;">,</span> ...<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">int</span> snprintf<span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str<span style="color: #339933;">,</span> size_t size<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>fmt<span style="color: #339933;">,</span> ...<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #339933;">#include &lt;stdarg.h&gt;</span>
<span style="color: #993333;">int</span> vprintf<span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>fmt<span style="color: #339933;">,</span> va_list ap<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">int</span> vfprintf<span style="color: #009900;">&#40;</span>FILE <span style="color: #339933;">*</span>stream<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>fmt<span style="color: #339933;">,</span> va_list ap<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">int</span> vsprintf<span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>fmt<span style="color: #339933;">,</span> va_list ap<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">int</span> vsnprintf<span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str<span style="color: #339933;">,</span> size_t size<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>fmt<span style="color: #339933;">,</span> va_list ap<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>　　前四个函数没有什么特殊的。后面四个v系列可以接受va_list变量，通常用在对可变参数输出的包装，在日志记录系统中较为常用。比如下面代码，</p>

<div class="wp_codebox"><table><tr id="p26268"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code" id="p2626code8"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">enum</span> LogLevel <span style="color: #008000;">&#123;</span> ERROR, WARN, INFO, DEBUG <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> <span style="color: #0000dd;">log</span><span style="color: #008000;">&#40;</span>LogLevel level, <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>fmt, ...<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">va_list</span> ap<span style="color: #008080;">;</span>
    <span style="color: #0000dd;">va_start</span><span style="color: #008000;">&#40;</span>ap, fmt<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    vsnprintf<span style="color: #008000;">&#40;</span>buf, <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>buf<span style="color: #008000;">&#41;</span>, fmt, ap<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">va_end</span><span style="color: #008000;">&#40;</span>ap<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #666666;">//~ write buf to file, or do something else.</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　v系列函数并不会调用va_end宏，因此在这些函数返回后，需要调用函数自己进行va_end。若要再次解析变参列表，就需要重新va_start, va_end。</p>
<h4>宏变参</h4>
<p>　　除了函数，在C/C++中，带参宏定义也可以接受变参，使用方法和函数类似。比如，若将上面的log函数的某个级别的日志输入定义成宏，</p>

<div class="wp_codebox"><table><tr id="p26269"><td class="code" id="p2626code9"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define log_warn(fmt, ...) log(WARN, fmt, __VA_ARGS__)</span></pre></td></tr></table></div>

<p>　　__VA_ARGS__只是被预处理器简单的展开为传递给宏log_warn的变参列表，包括逗号分隔符。若想使用具有鲜明意义的名字，而不是统一的__VA_ARGS__，可以这样，</p>

<div class="wp_codebox"><table><tr id="p262610"><td class="code" id="p2626code10"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define log_warn(fmt, args...) log(WARN, fmt, args)</span></pre></td></tr></table></div>

<p>　　上述宏定义中，有一个问题值得注意，就是当变参列表为空时，log函数调用的参数列表会有一个结尾的逗号，这在某些编译器中会被诊断为错误（据说MSVC不会），这种情况下可以将fmt也纳入变参列表，</p>

<div class="wp_codebox"><table><tr id="p262611"><td class="code" id="p2626code11"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define log_warn(...) log(WARN, __VA_ARGS__)</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2011/08/variadic/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>[C++]对虚函数的一次把玩</title>
		<link>http://www.dutor.net/index.php/2011/05/stuff-about-vptr-vtbl/</link>
		<comments>http://www.dutor.net/index.php/2011/05/stuff-about-vptr-vtbl/#comments</comments>
		<pubDate>Thu, 05 May 2011 16:01:30 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[虚函数]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2583</guid>
		<description><![CDATA[　　关于虚函数，需要知道：

<ul>
	<li> 多态在C++中借助虚函数实现 </li>
	<li> 多态只在指针或者引用上发生 </li>
	<li> 虚函数机制（通常）借助虚指针vptr支持 </li>
	<li> 虚函数地址保存在虚函数表中 </li>
	<li> 一个类的所有对象共有一张vtbl </li>
	<li> vtbl由vptr指向，vptr保存在每一个对象中，多继承时可能有多个vptr </li>
	<li> vptr由构造函数（普通构造/copy构造）在对象初始化时隐式设定 </li>
</ul>]]></description>
			<content:encoded><![CDATA[<p>以下代码，</p>

<div class="wp_codebox"><table><tr id="p258312"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code" id="p2583code12"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> B
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    B<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    B<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> B<span style="color: #000040;">&amp;</span> b<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">memcpy</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">this</span>, <span style="color: #000040;">&amp;</span>b, <span style="color: #0000dd;">sizeof</span> b<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;B::foo()&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">class</span> D<span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> B
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;D::foo()&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">void</span> bar<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> B<span style="color: #000040;">&amp;</span> b<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    b.<span style="color: #007788;">foo</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　类D继承自类B，并重写了virtual函数foo()。特殊的是B的copy构造函数，它将参数b按位copy到自身。由于B中没有任何数据成员（除了vptr，即虚函数表指针），如果b所关联的就是一个B对象，这没有任何问题。但b还以关联到B的子类，这时问题就来了，因为此时由copy构造出的对象的vptr指向的并不是B的vtbl（虚函数表），而是指向b实际类型的vtbl。</p>

<div class="wp_codebox"><table><tr id="p258313"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code" id="p2583code13"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    D d<span style="color: #008080;">;</span>
    B b <span style="color: #000080;">=</span> d<span style="color: #008080;">;</span>
    B <span style="color: #000040;">&amp;</span>r <span style="color: #000080;">=</span> b<span style="color: #008080;">;</span>
    r.<span style="color: #007788;">foo</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　执行这个代码片段，会输出什么？<br />
　　出乎意料，输出的仍然是B::foo()。可是为什么呢？使用GDB调试，</p>
<pre>
(gdb) x/xg &#038;d
0x7fffffffe000: 0x0000000000400bf0
(gdb) x/xg &#038;b
0x7fffffffdff0: 0x0000000000400bf0
(gdb) x/xg &#038;r
0x7fffffffdff0: 0x0000000000400bf0
(gdb)
</pre>
<p>　　发现b的vptr确实是和d相同。但r.foo()调用了B::foo()，唯一的解释就是，编译器看穿了我的伎俩，发现我是在一个b“对象”上面调用的虚函数，并没有使用vptr/vtbl调用foo，绕过了虚函数机制直接调用了B::foo()。有汇编为证，</p>
<pre>
   0x000000000040098c <+39>:    lea    -0x20(%rbp),%rax # 取b地址
   0x0000000000400990 <+43>:    mov    %rax,-0x28(%rbp) # 赋给r
   0x0000000000400994 <+47>:    mov    -0x28(%rbp),%rax
   0x0000000000400998 <+51>:    mov    %rax,%rdi # 以%rdi寄存器传递this
=> 0x000000000040099b <+54>:    callq  0x400a54 <B::foo() const>#调用B::foo()
</pre>
<p>　　吼吼，编译器知道的太多啦！咱们换种策略，</p>

<div class="wp_codebox"><table><tr id="p258314"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code" id="p2583code14"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> bar<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> B<span style="color: #000040;">&amp;</span> b<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    b.<span style="color: #007788;">foo</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    D d<span style="color: #008080;">;</span>
    B b <span style="color: #000080;">=</span> d<span style="color: #008080;">;</span> <span style="color: #666666;">//~ 调用B::B(const B&amp; b)</span>
    bar<span style="color: #008000;">&#40;</span>b<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>    嗯，这把行了，不信还看汇编，</p>
<pre>
Dump of assembler code for function main():
    ...
=> 0x000000000040098c <+39>:    lea    -0x20(%rbp),%rax #取b地址
   0x0000000000400990 <+43>:    mov    %rax,%rdi # 赋予%rdi
   0x0000000000400993 <+46>:    callq  0x400944 <bar(B const&#038;)>#调用bar
    ...
Dump of assembler code for function bar(B const&#038;):
    ...
   0x000000000040094c <+8>:     mov    %rdi,-0x8(%rbp) #获取&#038;b
   0x0000000000400950 <+12>:    mov    -0x8(%rbp),%rax
   0x0000000000400954 <+16>:    mov    (%rax),%rax # 获取vptr
   0x0000000000400957 <+19>:    mov    (%rax),%rdx # 获取foo地址
   0x000000000040095a <+22>:    mov    -0x8(%rbp),%rax #获取&#038;b
   0x000000000040095e <+26>:    mov    %rax,%rdi # 传递this
   0x0000000000400961 <+29>:    callq  *%rdx # 调用D::foo()
</pre>
<p>　　关于虚函数，需要知道：</p>
<ul>
<li> 多态在C++中借助虚函数实现 </li>
<li> 多态只在指针或者引用上发生 </li>
<li> 虚函数机制（通常）借助虚指针vptr支持 </li>
<li> 虚函数地址保存在虚函数表中 </li>
<li> 一个类的所有对象共有一张vtbl </li>
<li> vtbl由vptr指向，vptr保存在每一个对象中，多继承时可能有多个vptr </li>
<li> vptr由构造函数（普通构造/copy构造）在对象初始化时隐式设定 </li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2011/05/stuff-about-vptr-vtbl/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>reserve: 对老new的新认识</title>
		<link>http://www.dutor.net/index.php/2011/04/reserve-new-virtual-physical-memory/</link>
		<comments>http://www.dutor.net/index.php/2011/04/reserve-new-virtual-physical-memory/#comments</comments>
		<pubDate>Mon, 25 Apr 2011 13:43:16 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[new]]></category>
		<category><![CDATA[虚拟内存]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2568</guid>
		<description><![CDATA[　　reserve内部是怎么实现的呢？当然是new了。那么在reserve操作，也就是new之后，我们程序是否立即就占用了这些内存呢？这就要看我们这里说的“内存”是什么样的内存了。什么意思呢？我们知道，现代操作系统都采用了虚拟内存的机制，内存占用也就有了虚拟内存（virtual memory）和物理内存（physical memory）之分了。
　　我们又知道，Unix/Linux进程的虚拟地址空间被按用途被划分成了内核空间和用户空间。内核空间供操作系统的内核使用，用户空间供用户程序支配。其中用户空间又被划分为若干段，主要包括：代码段（.text），用来存放/映射用户程序的代码；数据段（.data），存放初始化的全局数据或静态数据，这部分在文件系统中也占据磁盘空间；.bss段（一直没找到一个亲切的翻译），存放为初始化的全局或静态数据，在程序加载时分配空间和初始化，这部分空间不占用磁盘空间（当然在可执行文件中要保留其大小）；堆栈段，用来保存程序执行时的上下文（局部变量、函数参数和返回地址等），在进程建立时由操作系统分配，空间较小且在运行时不可动态调整，增长方向因机器架构而异，IA上自高地址向下增长，堆栈不占用磁盘空间；堆，供用户在运行时动态地申请和使用，空间较大，未被申请的堆空间不可使用，也不会被映射到物理空间，堆随着用户程序申请向上增长，堆不占用磁盘空间。]]></description>
			<content:encoded><![CDATA[<p>　　C++ STL中的vector&lt;T>是一个变长“数组，在使用push_back等插入操作向vector中添加元素时可以动态地增长其容量(capacity)。然而，这种动态扩容的特性也带来了一定的性能负担。当vector当前容量不足以容纳待插入元素时，vector会另外开辟一段连续的内存，然后将原有元素拷贝(使用元素的copy构造)至新的内存区域，然后释放掉原先占据的内存，特定情况下，这可能是一笔不小的不必要的开销。vector的设计者当然也考虑到这一点，于是提供了reverve(ssize_t)成员函数。顾名思义，reserve为vector预定了一定大小的连续空间，使得在vector元素数量不超过当前容量的插入操作过程中，不会发生拷贝操作，原有迭代器、指针和引用当然也不会失效（insert类操作除外）。</p>
<p>　　reserve内部是怎么实现的呢？当然是new了。那么在reserve操作，也就是new之后，我们程序是否立即就占用了这些内存呢？这就要看我们这里说的“内存”是什么样的内存了。什么意思呢？我们知道，现代操作系统都采用了虚拟内存的机制，内存占用也就有了虚拟内存（virtual memory）和物理内存（physical memory）之分了。<br />
　　我们又知道，Unix/Linux进程的虚拟地址空间被按用途被划分成了内核空间和用户空间。内核空间供操作系统的内核使用，用户空间供用户程序支配。其中用户空间又被划分为若干段，主要包括：代码段（.text），用来存放/映射用户程序的代码；数据段（.data），存放初始化的全局数据或静态数据，这部分在文件系统中也占据磁盘空间；.bss段（一直没找到一个亲切的翻译），存放为初始化的全局或静态数据，在程序加载时分配空间和初始化，这部分空间不占用磁盘空间（当然在可执行文件中要保留其大小）；堆栈段，用来保存程序执行时的上下文（局部变量、函数参数和返回地址等），在进程建立时由操作系统分配，空间较小且在运行时不可动态调整，增长方向因机器架构而异，IA上自高地址向下增长，堆栈不占用磁盘空间；堆，供用户在运行时动态地申请和使用，空间较大，未被申请的堆空间不可使用，也不会被映射到物理空间，堆随着用户程序申请向上增长，堆不占用磁盘空间。</p>
<p>　　这么长的开场白之后，我们还知道，new负责在运行时（通过运行时库）为用户程序在堆上申请空间。但，而且，当然，new出的只是虚拟空间。在未对该空间进行读写时，这些空间并未被映射到物理空间，即操作系统还没有为这段空间分配物理内存。只有当程序开始对刚刚申请的虚拟空间进行访问时，被操作系统的虚拟内存机制觉察到（页中断）这一请求，才会为访问地址所在的虚存页面分配和映射物理页面，访问才得以进行。可以使用下面程序对此作出验证，</p>

<div class="wp_codebox"><table><tr id="p256815"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code" id="p2568code15"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    sleep<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">3</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;stage 1...&quot;</span><span style="color: #000080;">&lt;&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>p <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> <span style="color: #0000ff;">char</span><span style="color: #008000;">&#91;</span>1U<span style="color: #000080;">&lt;&lt;</span><span style="color: #0000dd;">30</span> <span style="color: #000040;">*</span> <span style="color: #0000dd;">2</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 2GB</span>
&nbsp;
    sleep<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">3</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;stage 2...&quot;</span><span style="color: #000080;">&lt;&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">unsigned</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> <span style="color: #008000;">&#40;</span>1U<span style="color: #000080;">&lt;&lt;</span><span style="color: #0000dd;">30</span><span style="color: #000040;">*</span><span style="color: #0000dd;">2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span> <span style="color: #666666;">//~ access</span>
    <span style="color: #008000;">&#123;</span>
        p<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
        usleep<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1000</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ per millisecond</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　运行此程序，同时使用top命令观察。主要观察两项，new前后程序的虚存占用，以及stage 2中程序驻留内存（REsident Size，即物理内存）的变化。另外，为了观察方便，最好调整top命令，使其按内存占用对进程排序。</p>
<p>　　上面虽然没有介绍太多东西，但由于本人水平有限，难免会有错误及不清楚之处，如果“不幸”被你发现了，还请指出和补充之。<br />
　　关于内存管理，学习过程中总会发现“惊喜”，若要做到对内存知根知底，对内核和语言运行时库的研究是必要的。对于这些个“小惊喜”，一方面说明俺是个小菜，另一方面也预示着俺是个成长中的小菜。各位看官您见笑了;-)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2011/04/reserve-new-virtual-physical-memory/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>[STL]vector和deque的内存释放(clear)</title>
		<link>http://www.dutor.net/index.php/2011/04/vector-deque-clear-reserve/</link>
		<comments>http://www.dutor.net/index.php/2011/04/vector-deque-clear-reserve/#comments</comments>
		<pubDate>Sun, 10 Apr 2011 13:56:22 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[STL]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2551</guid>
		<description><![CDATA[　　关于C++ STL容器的默认内存管理，需参考allocator。
　　关于deque的内存模型及其clear操作，我不甚了了，请参考您使用的标准库的代码。
　　若想深入了解STL的实现，侯捷大叔的《STL源码剖析》是不错的入门资料，希望能够拜读。
　　C++标准中并未对STL的实现细节做过多规定，因此不同实现的细节和表现可能不同。

　　C++很复杂，但也并非无底黑洞。学好C++很难，但这种学习过程也会使你收获颇丰。
　　学习任何一种技术，都需要热情、激情和足够的耐心。
　　做好一件事，需要激情，同时激情常常来源于做好一件事情的满足感。
　　满足感会增强人分享的欲望，分享的欲望也常常会使人具有亲和力和感染力，使人觉得你有激情，反过来更有利于人做好一件事。
　　blabla, over~
]]></description>
			<content:encoded><![CDATA[<p>　　vector的clear成员函数可以清除vector中的元素，使其大小减至0。但它却不能减小vector占用的内存。</p>

<div class="wp_codebox"><table><tr id="p255116"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p2551code16"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> v<span style="color: #008000;">&#40;</span>1U<span style="color: #000080;">&lt;&lt;</span><span style="color: #0000dd;">29</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;step into stage one...&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    sleep<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">30</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    v.<span style="color: #007788;">clear</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;step into stage two...&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    sleep<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">30</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　stage one定义了vector对象，含有2^29个int元素，占用2G内存。stage two调用vector对象的clear成员函数，清除其中所有对象。程序运行过程中，使用ps或者top或者其他工具查看内存占用，会发现，程序在stage one确实占用了大约2GB的内存，但在stage two，程序仍然占用着2G内存。事实上，vector的clear成员只负责对其中每一个元素调用其析构函数，将vector的size置零，并不负责释放vector本身占用的内存空间。</p>
<p>　　若想释放vector占用的空间，可以使用swap技巧，</p>

<div class="wp_codebox"><table><tr id="p255117"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p2551code17"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> v<span style="color: #008000;">&#40;</span>1U<span style="color: #000080;">&lt;&lt;</span><span style="color: #0000dd;">29</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;step into stage one...&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    sleep<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">30</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">swap</span><span style="color: #008000;">&#40;</span>v<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;step into stage two...&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    sleep<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">30</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　vector<int>()使用vector的默认构造函数建立临时vector对象，再在该临时对象上调用swap成员，swap调用之后对象v占用的空间就等于一个默认构造的对象的大小（寥寥），临时对象就具有原来对象v的大小，而该临时对象随即就会被析构，从而其占用的空间也被释放。</p>
<p>　　并不是所有的STL容器的clear成员的行为都和vector一样。事实上，其他容器的clear成员都会释放其内存。比如另一个和vector类似的顺序容器deque，</p>

<div class="wp_codebox"><table><tr id="p255118"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p2551code18"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    deque<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> dq<span style="color: #008000;">&#40;</span>1U<span style="color: #000080;">&lt;&lt;</span><span style="color: #0000dd;">29</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;step into stage one...&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    sleep<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">30</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    dq.<span style="color: #007788;">clear</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;step into stage two...&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    sleep<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">30</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　观察上面程序的行为，会发现程序在stage two的内存占用也是寥寥的了。</p>
<p>　　另外，值得一提的是vector具有reserve成员，会提前为容器预留一定的空间，以防止后的push_back操作导致频繁地重新分配内存和移动元素。然而，据我观察，reserve并没有向系统申请内存。</p>
<p>　　关于C++ STL容器的默认内存管理，需参考allocator。<br />
　　关于deque的内存模型及其clear操作，我不甚了了，请参考您使用的标准库的代码。<br />
　　若想深入了解STL的实现，侯捷大叔的《STL源码剖析》是不错的入门资料，希望能够拜读。<br />
　　C++标准中并未对STL的实现细节做过多规定，因此不同实现的细节和表现可能不同。</p>
<p>　　C++很复杂，但也并非无底黑洞。学好C++很难，但这种学习过程也会使你收获颇丰。<br />
　　学习任何一种技术，都需要热情、激情和足够的耐心。<br />
　　做好一件事，需要激情，同时激情常常来源于做好一件事情的满足感。<br />
　　满足感会增强人分享的欲望，分享的欲望也常常会使人具有亲和力和感染力，使人觉得你有激情，反过来更有利于人做好一件事。<br />
　　blabla, over~</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2011/04/vector-deque-clear-reserve/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>关于头文件</title>
		<link>http://www.dutor.net/index.php/2011/04/about-header-files/</link>
		<comments>http://www.dutor.net/index.php/2011/04/about-header-files/#comments</comments>
		<pubDate>Sat, 09 Apr 2011 03:23:02 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Cpp]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2547</guid>
		<description><![CDATA[　　头文件中通常包含有：函数原型（声明）、宏定义、内联函数定义。
　　头文件使用#include宏命令引入。有两种形式：#inlcude &#60;header.h>和#include "header.h". 两种形式的区别在于预处理器（preprocessor）查找头文件的方式的不同：对于前者，预处理器仅在系统预定义的标准路径中查找（标准查找路径由环境变量指明），比如/usr/include, /usr/local/include；对于后者，预处理器首先查找（源文件所在的）当前目录，若未找到，则到标准路径查找。另外，查找路径还可以通过编译器选项（-I for gcc）指定。通常，对于C/C++标准库和其他系统范围的程序库，使用&#60;>形式，对于程序本身定义的头文件，采用""形式。]]></description>
			<content:encoded><![CDATA[<p>　　头文件中通常包含有：函数原型（声明）、宏定义、内联函数定义。<br />
　　头文件使用#include宏命令引入。有两种形式：#inlcude &lt;header.h>和#include &#8220;header.h&#8221;. 两种形式的区别在于预处理器（preprocessor）查找头文件的方式的不同：对于前者，预处理器仅在系统预定义的标准路径中查找（标准查找路径由环境变量指明），比如/usr/include, /usr/local/include；对于后者，预处理器首先查找（源文件所在的）当前目录，若未找到，则到标准路径查找。另外，查找路径还可以通过编译器选项（-I for gcc）指定。通常，对于C/C++标准库和其他系统范围的程序库，使用&lt;>形式，对于程序本身定义的头文件，采用&#8221;"形式。<br />
　　编译器在传递参数给函数时，依据的是该函数的原型。因此，在调用外部函数时，务必包含其对应的头文件，否则，可能会出现传递的参数与函数实际使用的参数格式不一致的情况。瞧，</p>

<div class="wp_codebox"><table><tr id="p254719"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code" id="p2547code19"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//~ foo.c</span>
<span style="color: #993333;">float</span> 
foo<span style="color: #009900;">&#40;</span><span style="color: #993333;">float</span> f<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> f <span style="color: #339933;">*</span> f<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">//~ main.c</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;">double</span> d <span style="color: #339933;">=</span> foo<span style="color: #009900;">&#40;</span><span style="color:#800080;">3.1415926</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></td></tr></table></div>

<p>独立编译，</p>

<div class="wp_codebox"><table><tr id="p254720"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p2547code20"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">cc</span> foo.c main.c <span style="color: #660033;">-c</span>
$ <span style="color: #c20cb9; font-weight: bold;">cc</span> foo.o main.o <span style="color: #660033;">-omain</span>
$ .<span style="color: #000000; font-weight: bold;">/</span>main</pre></td></tr></table></div>

<p>　　你执行上面程序可能没发现什么问题，但在某些情况下，问题就来了。比如，如果编译器只使用栈来传递浮点数，main中向foo传递的是double（通常浮点字面常量被编译器解释为double），foo却按float处理参数，结果可想而知了。</p>
<p>　　对于内联函数（内联展开只是对编译器的建议），由于编译器在进行内联展开时需要看到函数的定义（而不仅仅是原<br />
型），所以，内联函数通常直接在头文件中声明和定义。如果把内联函数的定义同其他<br />
函数一样，将声明和定义分开（在单独的源文件中定义），那么该“内联”函数就只能在其所定义的文件中展开。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2011/04/about-header-files/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>何谓格式化输入/输出</title>
		<link>http://www.dutor.net/index.php/2010/10/format-stdio/</link>
		<comments>http://www.dutor.net/index.php/2010/10/format-stdio/#comments</comments>
		<pubDate>Fri, 22 Oct 2010 02:22:48 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[C]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2494</guid>
		<description><![CDATA[　　不多说，都在代码里了。
<pre lang="cpp" line="1">
#include <stdio.h>

int
main(int AC, char **AV)
{
    FILE *fd = fopen("data", "w+");
    fprintf(fd, "%x%c", 0x41, '1');
    fseek(fd, 0, SEEK_SET);
    int n;
    fscanf(fd, "%d", &#038;n);
    fseek(fd, 0, SEEK_SET);
    char s[4];
    int c = fread(s, 1, sizeof(s), fd);
    s[c] = '\0';
    printf("%d, %s\n", n, s);
    fclose(fd);
    return 0;
}
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　不多说，都在代码里了。</p>

<div class="wp_codebox"><table><tr id="p249421"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code" id="p2494code21"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;stdio.h&gt;</span>
&nbsp;
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> AC, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>AV<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">FILE</span> <span style="color: #000040;">*</span>fd <span style="color: #000080;">=</span> <span style="color: #0000dd;">fopen</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;data&quot;</span>, <span style="color: #FF0000;">&quot;w+&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">fprintf</span><span style="color: #008000;">&#40;</span>fd, <span style="color: #FF0000;">&quot;%x%c&quot;</span>, <span style="color: #208080;">0x41</span>, <span style="color: #FF0000;">'1'</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">fseek</span><span style="color: #008000;">&#40;</span>fd, <span style="color: #0000dd;">0</span>, <span style="color: #0000ff;">SEEK_SET</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">int</span> n<span style="color: #008080;">;</span>
    <span style="color: #0000dd;">fscanf</span><span style="color: #008000;">&#40;</span>fd, <span style="color: #FF0000;">&quot;%d&quot;</span>, <span style="color: #000040;">&amp;</span>n<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">fseek</span><span style="color: #008000;">&#40;</span>fd, <span style="color: #0000dd;">0</span>, <span style="color: #0000ff;">SEEK_SET</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">char</span> s<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">4</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">int</span> c <span style="color: #000080;">=</span> <span style="color: #0000dd;">fread</span><span style="color: #008000;">&#40;</span>s, <span style="color: #0000dd;">1</span>, <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>s<span style="color: #008000;">&#41;</span>, fd<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    s<span style="color: #008000;">&#91;</span>c<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> <span style="color: #FF0000;">'<span style="color: #006699; font-weight: bold;">\0</span>'</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%d, %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, n, s<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">fclose</span><span style="color: #008000;">&#40;</span>fd<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/10/format-stdio/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>没有malloc的单链表</title>
		<link>http://www.dutor.net/index.php/2010/10/linked-list-without-malloc/</link>
		<comments>http://www.dutor.net/index.php/2010/10/linked-list-without-malloc/#comments</comments>
		<pubDate>Tue, 05 Oct 2010 03:43:43 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[C]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2464</guid>
		<description><![CDATA[　　在StackOverflow上面看到的，分析一下下面的代码，对初学者理解什么是堆，什么是栈，对象是如何拷贝的有所帮助。
<pre lang="c" line="1">
#include <stdio.h>
typedef struct node
{
      int i;
      struct node *next;
}node;
node getnode(int a)
{
      struct node n;
      n.i=a;
      n.next=NULL;
      return n;
}
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　在StackOverflow上面看到的，分析一下下面的代码，对初学者理解什么是堆，什么是栈，对象是如何拷贝的有所帮助。</p>

<div class="wp_codebox"><table><tr id="p246422"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
</pre></td><td class="code" id="p2464code22"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdio.h&gt;</span>
<span style="color: #993333;">typedef</span> <span style="color: #993333;">struct</span> node
<span style="color: #009900;">&#123;</span>
      <span style="color: #993333;">int</span> i<span style="color: #339933;">;</span>
      <span style="color: #993333;">struct</span> node <span style="color: #339933;">*</span>next<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>node<span style="color: #339933;">;</span>
node getnode<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> a<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
      <span style="color: #993333;">struct</span> node n<span style="color: #339933;">;</span>
      n.<span style="color: #202020;">i</span><span style="color: #339933;">=</span>a<span style="color: #339933;">;</span>
      n.<span style="color: #202020;">next</span><span style="color: #339933;">=</span>NULL<span style="color: #339933;">;</span>
      <span style="color: #b1b100;">return</span> n<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
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> i<span style="color: #339933;">;</span>
     node newtemp<span style="color: #339933;">,</span>root<span style="color: #339933;">,</span>temp<span style="color: #339933;">;</span>
     scanf<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d&quot;</span><span style="color: #339933;">,&amp;</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
     root<span style="color: #339933;">=</span>getnode<span style="color: #009900;">&#40;</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
     temp<span style="color: #339933;">=</span>root<span style="color: #339933;">;</span>
&nbsp;
     <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">--</span><span style="color: #009900;">&#41;</span>
     <span style="color: #009900;">&#123;</span>
         newtemp<span style="color: #339933;">=</span>getnode<span style="color: #009900;">&#40;</span>i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
         temp.<span style="color: #202020;">next</span><span style="color: #339933;">=&amp;</span>newtemp<span style="color: #339933;">;</span>
         <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>root.<span style="color: #202020;">next</span><span style="color: #339933;">==</span>NULL<span style="color: #009900;">&#41;</span>
         <span style="color: #009900;">&#123;</span>
            root<span style="color: #339933;">=</span>temp<span style="color: #339933;">;</span>
         <span style="color: #009900;">&#125;</span>
        temp<span style="color: #339933;">=*</span><span style="color: #009900;">&#40;</span>temp.<span style="color: #202020;">next</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
     <span style="color: #009900;">&#125;</span>
     temp<span style="color: #339933;">=</span>root<span style="color: #339933;">;</span>
&nbsp;
     <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span> temp.<span style="color: #202020;">next</span> <span style="color: #339933;">!=</span> NULL <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 &quot;</span><span style="color: #339933;">,</span>temp.<span style="color: #202020;">i</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
         temp<span style="color: #339933;">=*</span><span style="color: #009900;">&#40;</span>temp.<span style="color: #202020;">next</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
     <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/10/linked-list-without-malloc/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>extern &#8220;C&#8221;</title>
		<link>http://www.dutor.net/index.php/2010/09/extern-c/</link>
		<comments>http://www.dutor.net/index.php/2010/09/extern-c/#comments</comments>
		<pubDate>Mon, 20 Sep 2010 03:17:23 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[mangling]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2443</guid>
		<description><![CDATA[　　在很多C/C++头文件中，你可能会经常看到使用extern "C"{}包含起来的代码。这种语法的存在是为了使C和C++代码能够兼容。兼容？C++对C本来不就是兼容的吗？确实，在语法层面，C++支持几乎所有C语法。但这里的兼容是目标文件或者库级别的兼容，包括两种情况下的兼容。一种是，在C++代码中调用已经存在的C代码写成的库；另一种是，使用C编写代码，而希望这些代码能够使C++可以调用。
　　若想继续讨论extern "C"，就不得不提name mangling。
　　我们知道，相比C，C++支持函数重载，支持命名空间，支持类以及成员函数。函数重载允许我们声明名字相同参数不同的函数，命名空间（namespace）和类为名字（或者说符号）划分了不同的域使得我们可以在不同域中使用完全相同的名字。而为了实现这种特性，C++就使用了name mangling。即是说，C++编译器在编译C++文件时，把每一个函数名“打乱”成与函数所在域、参数类型、调用约定相关的另外一个名字（因为汇编级别的代码中，所有符号都在同一个域）。由于C中并不存在这些特性，所以通常C编译器并不对符号进行mangling。]]></description>
			<content:encoded><![CDATA[<p>　　在很多C/C++头文件中，你可能会经常看到使用extern &#8220;C&#8221;{}包含起来的代码。这种语法的存在是为了使C和C++代码能够兼容。兼容？C++对C本来不就是兼容的吗？确实，在语法层面，C++支持几乎所有C语法。但这里的兼容是目标文件或者库级别的兼容，包括两种情况下的兼容。一种是，在C++代码中调用已经存在的C代码写成的库；另一种是，使用C编写代码，而希望这些代码能够使C++可以调用。<br />
　　若想继续讨论extern &#8220;C&#8221;，就不得不提name mangling。<br />
　　我们知道，相比C，C++支持函数重载，支持命名空间，支持类以及成员函数。函数重载允许我们声明名字相同参数不同的函数，命名空间（namespace）和类为名字（或者说符号）划分了不同的域使得我们可以在不同域中使用完全相同的名字。而为了实现这种特性，C++就使用了name mangling。即是说，C++编译器在编译C++文件时，把每一个函数名“打乱”成与函数所在域、参数类型、调用约定相关的另外一个名字（因为汇编级别的代码中，所有符号都在同一个域）。由于C中并不存在这些特性，所以通常C编译器并不对符号进行mangling。<br />
　　由于C++中这种mangling的存在，使C和C++在符号上不统一，无法直接相互调用。比如C中有这样一个函数，</p>

<div class="wp_codebox"><table><tr id="p244323"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p2443code23"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//~ add.h</span>
<span style="color: #993333;">int</span> add<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #339933;">,</span> <span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//~ add.c</span>
<span style="color: #993333;">int</span> add<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> a<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> b<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> a <span style="color: #339933;">+</span> b<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>使用gcc编译add.c。然后在C++代码中直接调用add函数，</p>

<div class="wp_codebox"><table><tr id="p244324"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p2443code24"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//~ main.cpp</span>
<span style="color: #339933;">#include &lt;add.h&gt;</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;">int</span> a <span style="color: #339933;">=</span> add<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">1</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></td></tr></table></div>

<p>这样编译main.cpp，</p>

<div class="wp_codebox"><table><tr id="p244325"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p2443code25"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">gcc</span> <span style="color: #660033;">-c</span> add.c
$ <span style="color: #c20cb9; font-weight: bold;">g++</span> <span style="color: #660033;">-c</span> main.cpp
$ <span style="color: #c20cb9; font-weight: bold;">g++</span> main.o add.o <span style="color: #660033;">-o</span> main
main.o: In <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #000000; font-weight: bold;">`</span>main<span style="color: #ff0000;">':
main.cpp:(.text+0x13): undefined reference to `add(int, int)'</span>
collect2: <span style="color: #c20cb9; font-weight: bold;">ld</span> returned <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">exit</span> status</pre></td></tr></table></div>

<p>错误提示add(int, int)为找到。将main.cpp编译成汇编后，查看调用add的代码为</p>

<div class="wp_codebox"><table><tr id="p244326"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p2443code26"><pre class="asm" style="font-family:monospace;">    movl    $<span style="color: #0000ff;">1</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esi</span> # 参数入栈
    movl    $<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">edi</span> # 参数入栈
    <span style="color: #00007f; font-weight: bold;">call</span>    _Z3addii # 调用<span style="color: #00007f; font-weight: bold;">add</span><span style="color: #339933;">,</span> 注意符号
    movl    <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span>rbp<span style="color: #009900; font-weight: bold;">&#41;</span> # 返回值赋给<span style="color: #00007f; font-weight: bold;">int</span> a</pre></td></tr></table></div>

<p>　　解决这种情况的方法就是使用extern &#8220;C&#8221;，在add.h中，把add的声明放入extern &#8220;C&#8221;{}中。这样，g++就不会对add进行mangling，链接器就会在add.o中找到add并链接到main.o。通常，C代码的头文件（包括libc的头文件，比如string.h）中，函数的声明通常是这样的，</p>

<div class="wp_codebox"><table><tr id="p244327"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p2443code27"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//~ add.h</span>
<span style="color: #339933;">#ifdef __cplusplus</span>
<span style="color: #000000; font-weight: bold;">extern</span> <span style="color: #ff0000;">&quot;C&quot;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #339933;">#endif</span>
<span style="color: #993333;">int</span> add<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #339933;">,</span> <span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">#ifdef __cplusplus</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #339933;">#endif</span></pre></td></tr></table></div>

<p>这样一来，如果是C代码包含add.h，那么将是直接包含add函数的声明。如果是C++代码包含add.h，那么extern &#8220;C&#8221;就将会被引入。关于name mangling，请参考<a href="http://en.wikipedia.org/wiki/Name_mangling" target="_blank">这里</a>，还有<a href="http://www.kegel.com/mangle.html" target="_blank">这里</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/09/extern-c/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>副作用与顺序点</title>
		<link>http://www.dutor.net/index.php/2010/09/side-effect-and-sequence-point/</link>
		<comments>http://www.dutor.net/index.php/2010/09/side-effect-and-sequence-point/#comments</comments>
		<pubDate>Sat, 18 Sep 2010 16:17:47 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[副作用]]></category>
		<category><![CDATA[顺序点]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2437</guid>
		<description><![CDATA[　　那么，C/C++中，哪些地方是顺序点呢？
<ul>
	<li>每个表达式的结束处；</li>
	<li>函数调用中，在所有参数求值完成后，函数体开始执行前有一个顺序点，而参数间的逗号处则没有顺序点。所以f(++i, ++i)的行为也是未定义的；</li>
	<li>逻辑运算符&#038;&、&#124;&#124;还有条件运算符?:的第一个参数末尾处有一个顺序点；</li>
	<li>逗号表达式中每一个逗号处有一个顺序点。因此x = (++i, ++i)是有确定行为的；</li>
	<li>在每一个完整的变量声明处有一个顺序点，例如int i, j;中逗号和分号处分别有一个顺序点；</li>
	<li>for循环控制条件中的两个分号处各有一个顺序点。</li>
</ul>
　　那么，现在，这个程序有问题吗？
<pre lang="c" line="1">
int
main()
{
    int m = 1, n = 0;
    printf("%d, %d\n", m, n);
    m ^= n ^= m ^= n;
    printf("%d, %d\n", m, n);
    return 0;
}
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　C/C++中有一个叫做<a href="http://en.wikipedia.org/wiki/Sequence_point" target="_blank">顺序点（Sequence Point）</a>的概念，通常我们并没有必要去了解和深究。但如果掌握了顺序点的概念，一些晦涩的表达式（比如某些无聊的面试题目）可能就会变得简单明了了。为了介绍顺序点，就不得不提到副作用（Side Effect）。<br />
　　所谓副作用，是相对于传统表达式而言的。例如，i = j * k没有副作用，而i = ++j * k++或者i = f(j) * g(k)就有副作用。即是说，如果变量在一个表达式的运算中改变了自己的值，则称这个表达式有副作用。而顺序点就是为限定这些副作用产生歧义或者不确定行为所设定的。程序或者表达式中，在任意一个顺序点，它之前的所有副作用都已经完成，它之后的所有副作用都尚未发生；任意两个顺序点之间的副作用的发生顺序都是未定义的。这样说可能并不太清楚，咱们来看一个例子，</p>

<div class="wp_codebox"><table><tr id="p243728"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p2437code28"><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: #993333;">int</span> n <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> m <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">++</span>n<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">++</span>n<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">++</span>n<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">++</span>n<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, %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> m<span style="color: #339933;">,</span> n<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></td></tr></table></div>

<p>　　上面代码的输出应该是什么呢？答案是，it depends. 可能因你所使用的编译器的不同（甚至是版本的不同）而产生较大的差异。用标准的话说，这样的行为是未定义的（undefined）。可是，为什么呢？<br />
　　这是因为赋值表达式int m = (++n) + (++n) + (++n) + (++n);没有顺序点，或者说只在表达式结尾的分号处有一个顺序点。因此，各副作用的计算顺序是不确定的。即是说，在计算第一个++n时，不知道其他++n是否已经被计算过（计算了几个）。使用gcc 4.2.4，上面程序输出11, 4，使用vs2008，程序输出16, 4。<br />
　　<br />
　　那么，C/C++中，哪些地方是顺序点呢？</p>
<ul>
<li>每个表达式的结束处；</li>
<li>函数调用中，在所有参数求值完成后，函数体开始执行前有一个顺序点，而参数间的逗号处则没有顺序点。所以f(++i, ++i)的行为也是未定义的；</li>
<li>逻辑运算符&#038;&#038;、||还有条件运算符?:的第一个参数末尾处有一个顺序点；</li>
<li>逗号表达式中每一个逗号处有一个顺序点。因此x = (++i, ++i)是有确定行为的；</li>
<li>在每一个完整的变量声明处有一个顺序点，例如int i, j;中逗号和分号处分别有一个顺序点；</li>
<li>for循环控制条件中的两个分号处各有一个顺序点。</li>
</ul>
<p>　　如果你打算规规矩矩的写你的代码，这些都是可以通过使用括号和临时变量来避免未定义的行为的。总之，要保证，在两个相邻顺序点之间同一个变量不可以被修改两次以上或者同时有读取和修改，否则，就会产生未定义的行为。例如，i = ++i。<br />
　　那么，现在，这个程序有问题吗？</p>

<div class="wp_codebox"><table><tr id="p243729"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code" id="p2437code29"><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: #993333;">int</span> m <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> n <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d, %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> m<span style="color: #339933;">,</span> n<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    m <span style="color: #339933;">^=</span> n <span style="color: #339933;">^=</span> m <span style="color: #339933;">^=</span> n<span style="color: #339933;">;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%d, %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> m<span style="color: #339933;">,</span> n<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></td></tr></table></div>

<p>除了顺序点，即把m ^= n ^= m ^= n;改做m^=n;n^=m;m^=n;上面程序还可能有其它问题。C++中，如果m和n如果是同一个整数的引用呢？C中，在操作类似数组之类的对象时，也有可能出现m,n指向同一对象的可能性，这时，这个对象就被清零了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/09/side-effect-and-sequence-point/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>优先级 &amp;&amp; 求值顺序</title>
		<link>http://www.dutor.net/index.php/2010/09/precedence-evaluation-order/</link>
		<comments>http://www.dutor.net/index.php/2010/09/precedence-evaluation-order/#comments</comments>
		<pubDate>Tue, 14 Sep 2010 06:54:16 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[运算符]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2426</guid>
		<description><![CDATA[See this,
<pre lang="c" line="1">
int
main()
{
    int x = -1,
        y = -1,
        z = 0;
    printf("%d\n", ++x &#124;&#124; ++y &#038;& ++z);
    printf("%d, %d, %d\n", x, y, z);
    return 0;
}
</pre>
　　别说我无聊，没人（正常人）会写出这样的式子，但有些细节知道总比不知道的好。
　　&#038;&比&#124;&#124;优先级高。
　　但优先级和求值顺序是两码事。
　　&#124;&#124;和&#038;&的求值顺序都是从左到右。其它运算符只有三目运算和逗号运算符有特定顺序，而+ - * /等的操作数均无特定的求值顺序，即f(x) + g(x++)中那个函数首先被调用是未定义的。顺便提一句，函数的参数的求值顺序与其入栈顺序也是无关的，所以f(i++, i++, i++)的行为也是未知的。]]></description>
			<content:encoded><![CDATA[<p>See this,</p>

<div class="wp_codebox"><table><tr id="p242630"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p2426code30"><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: #993333;">int</span> x <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">,</span>
        y <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">,</span>
        z <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</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: #339933;">++</span>x <span style="color: #339933;">||</span> <span style="color: #339933;">++</span>y <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">++</span>z<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, %d, %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> x<span style="color: #339933;">,</span> y<span style="color: #339933;">,</span> z<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></td></tr></table></div>

<p>and this,</p>

<div class="wp_codebox"><table><tr id="p242631"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p2426code31"><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: #993333;">int</span> x <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">,</span>
        y <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">,</span>
        z <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span>
        s <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</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: #339933;">++</span>x <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">++</span>y <span style="color: #339933;">||</span> <span style="color: #339933;">++</span>z <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">++</span>s<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, %d, %d, %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> x<span style="color: #339933;">,</span> y<span style="color: #339933;">,</span> z<span style="color: #339933;">,</span> s<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></td></tr></table></div>

<p>　　别说我无聊，没人（正常人）会写出这样的式子，但有些细节知道总比不知道的好。<br />
　　&#038;&#038;比||优先级高。<br />
　　但优先级和求值顺序是两码事。<br />
　　||和&#038;&#038;的求值顺序都是从左到右。其它运算符只有三目运算和逗号运算符有特定顺序，而+ &#8211; * /等的操作数均无特定的求值顺序，即f(x) + g(x++)中那个函数首先被调用是未定义的。顺便提一句，函数的参数的求值顺序与其入栈顺序也是无关的，所以f(i++, i++, i++)的行为也是未知的。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/09/precedence-evaluation-order/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>const在C和C++中的区别</title>
		<link>http://www.dutor.net/index.php/2010/08/const-c-cpp-difference/</link>
		<comments>http://www.dutor.net/index.php/2010/08/const-c-cpp-difference/#comments</comments>
		<pubDate>Tue, 17 Aug 2010 13:50:48 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[const]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2408</guid>
		<description><![CDATA[　　const在C，尤其是C++，是个老生常谈的问题，但这里不谈const具体有哪些特性，如何使用，而是说说const在C和C++中的区别。编译器，C使用gcc，C++使用g++，其它编译器（cl等）请自行验证。
　　在我的印象中，const就是<strong>常量</strong>（<em>const</em>ant）。但这并不是真的。在C中，const仅仅表示其所修饰对象<strong>不可修改</strong>。常量和所谓“不可修改”有什么区别呢？C中，const int N = 10; 这样的语句声明了一个<strong>整型数据</strong>，声明之后你不能再为其赋值，此即为<strong>不可修改</strong>。但在C中，N却不是常量，而诸如372, 3.72, 'A'之类才是常量，在C中定义常量通常使用#define。而在C++中，const int N = 10; 就会定义N为常量。
　　怎么证明呢？你可能知道，定义静态数组，必须使用整型常量指定其大小，那咱们就用这个特性来验证上面描述的观点。
<pre lang="c" line="1">
int
main(int argc, char **argv)
{
    const int N = 10;
    int a[N] = { 1, 2, 3 };
    return 0;
}
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　const在C，尤其是C++，是个老生常谈的问题，但这里不谈const具体有哪些特性，如何使用，而是说说const在C和C++中的区别。编译器，C使用gcc，C++使用g++，其它编译器（cl等）请自行验证。<br />
　　在我的印象中，const就是<strong>常量</strong>（<em>const</em>ant）。但这并不是真的。在C中，const仅仅表示其所修饰对象<strong>不可修改</strong>。常量和所谓“不可修改”有什么区别呢？C中，const int N = 10; 这样的语句声明了一个<strong>整型数据</strong>，声明之后你不能再为其赋值，此即为<strong>不可修改</strong>。但在C中，N却不是常量，而诸如372, 3.72, &#8216;A&#8217;之类才是常量，在C中定义常量通常使用#define。而在C++中，const int N = 10; 就会定义N为常量。<br />
　　怎么证明呢？你可能知道，定义静态数组，必须使用整型常量指定其大小，那咱们就用这个特性来验证上面描述的观点。</p>

<div class="wp_codebox"><table><tr id="p240832"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p2408code32"><pre class="c" style="font-family:monospace;"><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;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">const</span> <span style="color: #993333;">int</span> N <span style="color: #339933;">=</span> <span style="color: #0000dd;">10</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> a<span style="color: #009900;">&#91;</span>N<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;">3</span> <span style="color: #009900;">&#125;</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></td></tr></table></div>

<p>　　使用g++编译这个程序，没有问题。但若使用gcc，你会得到如下错误信息</p>
<pre>
main.c: In function ‘main’:
main.c:19: error: variable-sized object may not be initialized
main.c:19: warning: excess elements in array initializer
</pre>
<p>　　<br />
　　但事情并未到此结束，如果你把上面代码中int a[N] = { 1, 2, 3 };的初始化列表去掉，即int a[N]; 然后就也能通过gcc的编译，更有甚者，如果你把const int N = 10;的const去掉：int N = 10; 也能通过gcc的编译！这是gcc所支持的特性，即<strong>动态数组</strong>。但最好不要这样做，因为gcc会为此生成大量代码。例如，这段代码</p>

<div class="wp_codebox"><table><tr id="p240833"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p2408code33"><pre class="c" style="font-family:monospace;"><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;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">const</span> <span style="color: #993333;">int</span> N <span style="color: #339933;">=</span> <span style="color: #0000dd;">10</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> a<span style="color: #009900;">&#91;</span>N<span style="color: #009900;">&#93;</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></td></tr></table></div>

<p>使用gcc生成的汇编代码：</p>

<div class="wp_codebox"><table><tr id="p240834"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
</pre></td><td class="code" id="p2408code34"><pre class="asm" style="font-family:monospace;">&nbsp;
	<span style="color: #339933;">.</span>file	<span style="color: #7f007f;">&quot;main.c&quot;</span>
	<span style="color: #339933;">.</span>text
<span style="color: #339933;">.</span>globl main
	<span style="color: #339933;">.</span><span style="color: #000000; font-weight: bold;">type</span>	main<span style="color: #339933;">,</span> @function
main<span style="color: #339933;">:</span>
	leal	<span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span>
	andl	$<span style="color: #339933;">-</span><span style="color: #0000ff;">16</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	pushl	<span style="color: #339933;">-</span><span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span><span style="color: #009900; font-weight: bold;">&#41;</span>
	pushl	<span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span>
	pushl	<span style="color: #339933;">%</span><span style="color: #00007f;">esi</span>
	pushl	<span style="color: #339933;">%</span><span style="color: #00007f;">ebx</span>
	pushl	<span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span>
	subl	$<span style="color: #0000ff;">60</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span>
	movl	<span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #0000ff;">44</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span><span style="color: #009900; font-weight: bold;">&#41;</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">gs</span><span style="color: #339933;">:</span><span style="color: #0000ff;">20</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #0000ff;">28</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span><span style="color: #009900; font-weight: bold;">&#41;</span>
<span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span> # 此处略去n行
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	movl	<span style="color: #339933;">-</span><span style="color: #0000ff;">28</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">edx</span>
	xorl	<span style="color: #339933;">%</span><span style="color: #00007f;">gs</span><span style="color: #339933;">:</span><span style="color: #0000ff;">20</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">edx</span>
	<span style="color: #00007f; font-weight: bold;">je</span>	<span style="color: #339933;">.</span>L3
	<span style="color: #00007f; font-weight: bold;">call</span>	__stack_chk_fail
<span style="color: #339933;">.</span>L3<span style="color: #339933;">:</span>
	leal	<span style="color: #339933;">-</span><span style="color: #0000ff;">12</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	addl	$<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	popl	<span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span>
	popl	<span style="color: #339933;">%</span><span style="color: #00007f;">ebx</span>
	popl	<span style="color: #339933;">%</span><span style="color: #00007f;">esi</span>
	popl	<span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span>
	leal	<span style="color: #339933;">-</span><span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	<span style="color: #00007f; font-weight: bold;">ret</span></pre></td></tr></table></div>

<p>　　整个汇编文件有96行之多。而使用g++（<strong>N为常量</strong>）编译生成的汇编文件只有23行：</p>

<div class="wp_codebox"><table><tr id="p240835"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code" id="p2408code35"><pre class="asm" style="font-family:monospace;">	<span style="color: #339933;">.</span>file	<span style="color: #7f007f;">&quot;main.c&quot;</span>
	<span style="color: #339933;">.</span>text
<span style="color: #339933;">.</span>globl main
	<span style="color: #339933;">.</span><span style="color: #000000; font-weight: bold;">type</span>	main<span style="color: #339933;">,</span> @function
main<span style="color: #339933;">:</span>
<span style="color: #339933;">.</span>LFB0<span style="color: #339933;">:</span>
	<span style="color: #339933;">.</span>cfi_startproc
	<span style="color: #339933;">.</span>cfi_personality <span style="color: #0000ff;">0x0</span><span style="color: #339933;">,</span>__gxx_personality_v0
	pushl	<span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span>
	<span style="color: #339933;">.</span>cfi_def_cfa_offset <span style="color: #0000ff;">8</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span>
	<span style="color: #339933;">.</span>cfi_offset <span style="color: #0000ff;">5</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #0000ff;">8</span>
	<span style="color: #339933;">.</span>cfi_def_cfa_register <span style="color: #0000ff;">5</span>
	subl	$<span style="color: #0000ff;">48</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	movl	$<span style="color: #0000ff;">10</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span><span style="color: #009900; font-weight: bold;">&#41;</span>
	movl	$<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span>
	<span style="color: #00007f; font-weight: bold;">leave</span>
	<span style="color: #00007f; font-weight: bold;">ret</span>
	<span style="color: #339933;">.</span>cfi_endproc
<span style="color: #339933;">.</span>LFE0<span style="color: #339933;">:</span>
	<span style="color: #339933;">.</span><span style="color: #000000; font-weight: bold;">size</span>	main<span style="color: #339933;">,</span> <span style="color: #339933;">.-</span>main
	<span style="color: #339933;">.</span>ident	<span style="color: #7f007f;">&quot;GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3&quot;</span>
	<span style="color: #339933;">.</span>section	<span style="color: #339933;">.</span>note<span style="color: #339933;">.</span>GNU<span style="color: #339933;">-</span><span style="color: #000000; font-weight: bold;">stack</span><span style="color: #339933;">,</span><span style="color: #7f007f;">&quot;&quot;</span><span style="color: #339933;">,</span>@progbits</pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/08/const-c-cpp-difference/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>[C/C++]volatile</title>
		<link>http://www.dutor.net/index.php/2010/08/volatile-const/</link>
		<comments>http://www.dutor.net/index.php/2010/08/volatile-const/#comments</comments>
		<pubDate>Tue, 10 Aug 2010 12:05:25 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[const]]></category>
		<category><![CDATA[volatile]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2387</guid>
		<description><![CDATA[<h4>volatile</h4>
　　可能很多人都没用过<span class="word">C/C++</span>中的这个关键词，甚至不知道它的存在，本人以前也只是有所耳闻，但似懂非懂。
　　这是一个<strong>类型修饰符</strong>，位置同<span class="word">const</span>、<span class="word">static</span>等。一个使用<span class="word">volatile</span>修饰的变量，比如<em><span class="word">volatile int i;</span> </em>每次对该变量的直接引用，都会访问内存，而不是从寄存器中读取（如果其已经在寄存器中）。这样一来，<span class="word">volatile</span>似乎没什么用处，反倒会使数据的读取相对变慢很多。但是，如果没有<span class="word">volatile</span>，编译器可能会优化你的程序，使得数据从寄存器中读取，从而加快程序的运行，但如果这个变量是同其它进程/线程<strong>共享</strong>的，就可能造成数据的不一致。多线程情况下，你可以使用互斥机制来保证对共享数据访问的原子性。但是，在单片机等嵌入式环境中，硬件经常不会有这种<strong>互斥机制</strong>的支持，这时某些共享的数据（比如端口）就可能会产生不一致的情况。而使用<span class="word">volatile</span>就会使编译器不对代码进行优化，每次对该变量的访问都会从内存中读取。
　　下面通过观察使用<span class="word">volatile</span>前后编译产生的汇编代码的不同，来加深对<span class="word">volatile</span>关键词的理解。
<pre lang="asm" line="1">
[ ... ]
main:
[ ... ]
	call	foo # 调用函数foo，返回值保存至寄存器eax
	movl	%eax, 44(%esp) # 为i赋值
	movl	44(%esp), %edx # 读取i值
	movl	44(%esp), %ecx # 读取i值
	movl	44(%esp), %eax # 读取i值
	movl	%ecx, 16(%esp) # 参数k入栈，使用i值
	movl	%edx, 12(%esp) # 参数j入栈，使用i值
	movl	%eax, 8(%esp) # 参数i入栈
	movl	$.LC0, 4(%esp) # 格式字符串地址入栈
	call	__printf_chk
	movl	$0, %eax
	leave
	ret
[ ... ]
</pre>]]></description>
			<content:encoded><![CDATA[<h4>volatile</h4>
<p>　　可能很多人都没用过<span class="word">C/C++</span>中的这个关键词，甚至不知道它的存在，本人以前也只是有所耳闻，但似懂非懂。<br />
　　这是一个<strong>类型修饰符</strong>，位置同<span class="word">const</span>、<span class="word">static</span>等。一个使用<span class="word">volatile</span>修饰的变量，比如<em><span class="word">volatile int i;</span> </em>每次对该变量的直接引用，都会访问内存，而不是从寄存器中读取（如果其已经在寄存器中）。这样一来，<span class="word">volatile</span>似乎没什么用处，反倒会使数据的读取相对变慢很多。但是，如果没有<span class="word">volatile</span>，编译器可能会优化你的程序，使得数据从寄存器中读取，从而加快程序的运行，但如果这个变量是同其它进程/线程<strong>共享</strong>的，就可能造成数据的不一致。多线程情况下，你可以使用互斥机制来保证对共享数据访问的原子性。但是，在单片机等嵌入式环境中，硬件经常不会有这种<strong>互斥机制</strong>的支持，这时某些共享的数据（比如端口）就可能会产生不一致的情况。而使用<span class="word">volatile</span>就会使编译器不对代码进行优化，每次对该变量的访问都会从内存中读取。<br />
　　下面通过观察使用<span class="word">volatile</span>前后编译产生的汇编代码的不同，来加深对<span class="word">volatile</span>关键词的理解。<br />
　　对于下面的<span class="word">C</span>代码：</p>

<div class="wp_codebox"><table><tr id="p238736"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code" id="p2387code36"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;stdio.h&gt;</span>
&nbsp;
<span style="color: #0000ff;">int</span> foo<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span>i<span style="color: #000040;">++</span> <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">20</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> i<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">int</span> j <span style="color: #000080;">=</span> i<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">int</span> k <span style="color: #000080;">=</span> i<span style="color: #008080;">;</span>
    <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%d, %d, %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, i, j, k<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　代码中，使用<em>foo()</em>的返回值（20）来初始化整型变量<span class="word">i</span>。之所以不直接赋值，是为了<strong>防止</strong>编译器优化，下面对<span class="word">j,k</span>的赋值将直接使用<span class="word">20</span>，而不是<span class="word">i</span>，也不是寄存器。使用下面的命令编译：</p>

<div class="wp_codebox"><table><tr id="p238737"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2387code37"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">gcc</span> <span style="color: #660033;">-S</span> <span style="color: #660033;">-O1</span> main.c <span style="color: #666666; font-style: italic;"># 优化等级1</span></pre></td></tr></table></div>

<p>　　产生的汇编代码：</p>

<div class="wp_codebox"><table><tr id="p238738"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code" id="p2387code38"><pre class="asm" style="font-family:monospace;"><span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span>
<span style="color: #339933;">.</span>LC0<span style="color: #339933;">:</span>
	<span style="color: #339933;">.</span>string	<span style="color: #7f007f;">&quot;%d, %d, %d\n&quot;</span>
<span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span>
main<span style="color: #339933;">:</span>
<span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span>
	<span style="color: #00007f; font-weight: bold;">call</span>	foo # 调用函数foo，返回值保存至寄存器<span style="color: #00007f;">eax</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">16</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 参数k入栈
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">12</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 参数j入栈
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">8</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 参数i入栈
	movl	$<span style="color: #339933;">.</span>LC0<span style="color: #339933;">,</span> <span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 格式字符串地址入栈
	movl	$<span style="color: #0000ff;">1</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span>
	<span style="color: #00007f; font-weight: bold;">call</span>	__printf_chk
	movl	$<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span>
	<span style="color: #00007f; font-weight: bold;">leave</span>
	<span style="color: #00007f; font-weight: bold;">ret</span>
<span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span></pre></td></tr></table></div>

<p>　　可以看到，对<span class="word">j,k</span>的赋值都是由寄存器<span class="word">eax</span>进行的。下面把代码中的<em><span class="word">int i = foo();</span></em>换成<em><span class="word">volatile int i = foo();</span></em>，编译得到的汇编代码是：</p>

<div class="wp_codebox"><table><tr id="p238739"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code" id="p2387code39"><pre class="asm" style="font-family:monospace;"><span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span>
main<span style="color: #339933;">:</span>
<span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span>
	<span style="color: #00007f; font-weight: bold;">call</span>	foo # 调用函数foo，返回值保存至寄存器<span style="color: #00007f;">eax</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">44</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 为i赋值
	movl	<span style="color: #0000ff;">44</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">edx</span> # 读取i值
	movl	<span style="color: #0000ff;">44</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span> # 读取i值
	movl	<span style="color: #0000ff;">44</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span> # 读取i值
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">16</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 参数k入栈，使用i值
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">edx</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">12</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 参数j入栈，使用i值
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">8</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 参数i入栈
	movl	$<span style="color: #339933;">.</span>LC0<span style="color: #339933;">,</span> <span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 格式字符串地址入栈
	<span style="color: #00007f; font-weight: bold;">call</span>	__printf_chk
	movl	$<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span>
	<span style="color: #00007f; font-weight: bold;">leave</span>
	<span style="color: #00007f; font-weight: bold;">ret</span>
<span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span></pre></td></tr></table></div>

<p>　　可以看到，每次对i的访问都是从内存（栈）中读取的。</p>
<h4>volatile vs. const</h4>
<p>　　正像上面所描述的那样，<span class="word">volatile</span>的意思是<strong>“易变的”</strong>。<span class="word">C/C++</span>中还有另外一个关键词叫<span class="word">const</span>，用来限定变量不可被改变。似乎volatile和const意思相反，水火不容。但<span class="word"><em>volatile const int N = 0;</em></span>这样的语句是允许存在的。为什么呢？其实，这个语句可以这样来理解：变量<span class="word">N</span>在本程序（或者设备）中是不可（禁止）改变的，但它可能会被其它程序（或者设备）改变。你或许知道，<span class="word">const</span>只是编译器的限定，而没有执行期的检查，因此<span class="word">const</span>也只是限于单个进程，因此<span class="word">volatile</span>和<span class="word">const</span>这两个关键词并不冲突。<br />
　　另外，普通的整型<span class="word">const</span>变量，比如<em><span class="word">const int N = 10; int a[N];</span></em> 中，变量<span class="word">N</span>可能并不会被分配内存（除非程序里面有显式使用N地址的表达式）。但是，根据<span class="word">volatile</span>变量的特性，<em><span class="word">volatile const int N = 10;</span></em>中变量<span class="word">N</span>是一定会占用内存的。这一点，亦可以通过观察相应的汇编代码来验证。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/08/volatile-const/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>qsort</title>
		<link>http://www.dutor.net/index.php/2010/07/qsort/</link>
		<comments>http://www.dutor.net/index.php/2010/07/qsort/#comments</comments>
		<pubDate>Tue, 06 Jul 2010 12:57:10 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[qsort]]></category>
		<category><![CDATA[排序]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2347</guid>
		<description><![CDATA[　　对qsort需要注意几点：
<ul>
	<li>qsort中第一个参数是待排序数组的开始地址，既然是数组，各元素就是同类型、同大小的对象，且数组是<strong>“一维数组”</strong>（即地址是连续的）；</li>
	<li>qsort用以区分对象的依据是第二和第三个参数，分别表示对象个数和每个对象的大小（字节）；</li>
	<li>qsort并不知道每个对象的类型和结构，排序准则由用户在第四个参数（比较函数）中指出，qsort按该比较函数准则的“升序”对数组进行排序；</li>
	<li>标准C不支持运算符重载，各对象的交换（因为这是qsort）靠的是逐字节的拷贝（memcpy?）。</li>
</ul>
　　在上面的两片代码中，待排序的对象一个是字符型指针，一个是char (*)[10]型数组。然后，就没有然后了。]]></description>
			<content:encoded><![CDATA[<p>　　Felix那里看到的，关于用qsort对指针式字符串数组和二维型字符串数组的排序的，觉得值得贴出来。注意下下面两片代码的区别。</p>

<div class="wp_codebox"><table><tr id="p234740"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code" id="p2347code40"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">const</span> <span style="color: #993333;">int</span> N <span style="color: #339933;">=</span> <span style="color: #0000dd;">4</span><span style="color: #339933;">;</span>
<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str<span style="color: #009900;">&#91;</span>N<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #ff0000;">&quot;xyz&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;cdef&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;abcd&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;caaa&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">int</span> cmp<span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">void</span> <span style="color: #339933;">*</span>l<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">void</span> <span style="color: #339933;">*</span>r<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>a <span style="color: #339933;">=</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span><span style="color: #339933;">**</span><span style="color: #009900;">&#41;</span>l<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>b <span style="color: #339933;">=</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span><span style="color: #339933;">**</span><span style="color: #009900;">&#41;</span>r<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> strcmp<span style="color: #009900;">&#40;</span>a<span style="color: #339933;">,</span> b<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: #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;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    qsort<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>str<span style="color: #339933;">,</span> N<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> cmp <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</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;">&lt;</span> N<span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<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;%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> str<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: #009900;">&#125;</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></td></tr></table></div>


<div class="wp_codebox"><table><tr id="p234741"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code" id="p2347code41"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">const</span> <span style="color: #993333;">int</span> N <span style="color: #339933;">=</span> <span style="color: #0000dd;">4</span><span style="color: #339933;">;</span>
<span style="color: #993333;">char</span> str<span style="color: #009900;">&#91;</span>N<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000dd;">10</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #ff0000;">&quot;xyz&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;cdef&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;abcd&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;caaa&quot;</span><span style="color: #009900;">&#125;</span><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;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    qsort<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>str<span style="color: #339933;">,</span> N<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: #0000dd;">10</span><span style="color: #339933;">,</span>
            <span style="color: #009900;">&#40;</span> <span style="color: #993333;">int</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">void</span><span style="color: #339933;">*,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">void</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>strcmp <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</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;">&lt;</span> N<span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<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;%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> str<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: #009900;">&#125;</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></td></tr></table></div>

<p>　　对qsort需要注意几点：</p>
<ul>
<li>qsort中第一个参数是待排序数组的开始地址，既然是数组，各元素就是同类型、同大小的对象，且数组是<strong>“一维数组”</strong>（即地址是连续的）；</li>
<li>qsort用以区分对象的依据是第二和第三个参数，分别表示对象个数和每个对象的大小（字节）；</li>
<li>qsort并不知道每个对象的类型和结构，排序准则由用户在第四个参数（比较函数）中指出，qsort按该比较函数准则的“升序”对数组进行排序；</li>
<li>标准C不支持运算符重载，各对象的交换（因为这是qsort）靠的是逐字节的拷贝（memcpy?）。</li>
</ul>
<p>　　在上面的两片代码中，待排序的对象一个是字符型指针，一个是char (*)[10]型数组。然后，就没有然后了。<br />
　　<br />
　　然后，上面代码，gcc编译出错，g++却可以。<br />
　　const int N = 4; char *str[N];可以。<br />
　　const int N = 4; char *str[N] = {&#8220;a&#8221;,&#8221;b&#8221;,&#8221;c&#8221;,&#8221;d&#8221;};却不可，何解？</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/07/qsort/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>struct/class关键字何时是必须的？</title>
		<link>http://www.dutor.net/index.php/2010/05/is-struct-class-necessary/</link>
		<comments>http://www.dutor.net/index.php/2010/05/is-struct-class-necessary/#comments</comments>
		<pubDate>Fri, 21 May 2010 13:16:54 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Cpp]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2288</guid>
		<description><![CDATA[　　在形如struct structName varName;的语句中，struct是必须的吗？这是一个显而易见的语法问题，但却容易被忽略，尤其容易被C+C++的同志们忽略。
　　在标准C中，struct关键字是必须的：
<pre lang="c" line="1">
struct structName {
    int n;
};
//~ typedef struct structName structName;
int
main()
{
    struct structName n;
    return 0;
}
</pre>
若没有前置的struct关键字，上面的代码就不能通过编译。我的gcc会提示"structName" undeclared, parse error before 'n'的错误。为了方便，通常会使用typedef struct structName structName;语句来为struct structName定义类型别名。
　　但是，在C++中，一般情况下，struct/class关键字就不是必须的。但是，在有些情况下struct/class关键字又是必须的，因为这时的名字structName有歧义性。这是因为，C/C++语言允许用户自定义类型和函数同名。]]></description>
			<content:encoded><![CDATA[<p>　　在形如struct structName varName;的语句中，struct是必须的吗？这是一个显而易见的语法问题，但却容易被忽略，尤其容易被C+C++的同志们忽略。<br />
　　在标准C中，struct关键字是必须的：</p>

<div class="wp_codebox"><table><tr id="p228842"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p2288code42"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> structName <span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> n<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//~ typedef struct structName structName;</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;">struct</span> structName n<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></td></tr></table></div>

<p>若没有前置的struct关键字，上面的代码就不能通过编译。我的gcc会提示&#8221;structName&#8221; undeclared, parse error before &#8216;n&#8217;的错误。为了方便，通常会使用typedef struct structName structName;语句来为struct structName定义类型别名。<br />
　　但是，在C++中，一般情况下，struct/class关键字就不是必须的。但是，在有些情况下struct/class关键字又是必须的，因为这时的名字structName有歧义性。这是因为，C/C++语言允许用户自定义类型和函数同名。</p>

<div class="wp_codebox"><table><tr id="p228843"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code" id="p2288code43"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> structName <span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> n<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">void</span> structName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</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>
    structName n<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></td></tr></table></div>

<p>上面代码，无论使用gcc还是g++，都不能通过编译，即使structName n;明显只能是一个变量定义语句。这时，就需要明确使用关键字struct，即struct structName n;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/05/is-struct-class-necessary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[STL]函数对象/仿函数</title>
		<link>http://www.dutor.net/index.php/2010/04/stl-functor-function-object/</link>
		<comments>http://www.dutor.net/index.php/2010/04/stl-functor-function-object/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 12:37:46 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[STL]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2209</guid>
		<description><![CDATA[　　提到C++ STL，首先被人想到的是它的三大组件：Containers, Iterators, Algorithms，即容器，迭代器和算法。容器为用户提供了常用的数据结构，算法大多是独立于容器的常用的基本算法，迭代器是由容器提供的一种接口，算法通过迭代器来操控容器。接下来要介绍的是另外的一种组件，函数对象（Function Object，JJHou译作Functor仿函数）。
<h4>什么是函数对象</h4>
　　顾名思义，函数对象首先是一个对象，即某个类的实例。其次，函数对象的行为和函数一致，即是说可以像调用函数一样来使用函数对象，如参数传递、返回值等。这种行为是通过重载类的()操作符来实现的，举例说明之，
<pre lang="cpp" line="1">
class Print
{
public:
    void operator()(int n)
    {
        std::cout<<n<<std::endl;
        return ;
    }
};
int
main(int argc, char **argv)
{
    Print print;
    print(372);
    print.operator()(372); //~ 显式调用
    return 0;
}
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　提到C++ STL，首先被人想到的是它的三大组件：Containers, Iterators, Algorithms，即容器，迭代器和算法。容器为用户提供了常用的数据结构，算法大多是独立于容器的常用的基本算法，迭代器是由容器提供的一种接口，算法通过迭代器来操控容器。接下来要介绍的是另外的一种组件，函数对象（Function Object，JJHou译作Functor仿函数）。</p>
<h4>什么是函数对象</h4>
<p>　　顾名思义，函数对象首先是一个对象，即某个类的实例。其次，函数对象的行为和函数一致，即是说可以像调用函数一样来使用函数对象，如参数传递、返回值等。这种行为是通过重载类的()操作符来实现的，举例说明之，</p>

<div class="wp_codebox"><table><tr id="p220944"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code" id="p2209code44"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> Print
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">void</span> operator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> n<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>n<span style="color: #000080;">&lt;&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    Print print<span style="color: #008080;">;</span>
    print<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">372</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    print.<span style="color: #007788;">operator</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">372</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 显式调用</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　其实我们早就开始使用函数对象了，当你写下sort(v.begin(), v.end())时(假定v是vector&lt;int&gt;)，其实调用的是sort(v.begin(), v.end(), less&lt;int&gt;())，这样sort就会将v从小至大排序。若要逆向排序，你就需要显式地为sort指定一个排序规则，即函数对象greater&lt;int&gt;(). less&lt;T&gt;和greater&lt;T&gt;是STL中的两个模板类，它们使用类型T的&lt;和&gt;操作符。less&lt;T&gt;的一个典型实现可能是这样的：</p>

<div class="wp_codebox"><table><tr id="p220945"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code" id="p2209code45"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> T<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">class</span> less
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">bool</span> operator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span>l, <span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span>r<span style="color: #008000;">&#41;</span><span style="color: #0000ff;">const</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> l <span style="color: #000080;">&lt;</span> r<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<h4>函数对象的分类</h4>
<p>　　根据用途和参数特征，STL中的函数对象通常分为以下几类：Predicates, Arithmetic Function Objects, Binders, Negaters, Member Function Adapters, Pointer to Function Adapters。下面逐一介绍一下，之前得先介绍两个基类：</p>

<div class="wp_codebox"><table><tr id="p220946"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code" id="p2209code46"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> Arg, <span style="color: #0000ff;">class</span> Res<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">struct</span> unary_function <span style="color: #666666;">//~ 一元函数对象基类</span>
<span style="color: #008000;">&#123;</span>
   <span style="color: #0000ff;">typedef</span> Arg argument_type<span style="color: #008080;">;</span>
   <span style="color: #0000ff;">typedef</span> Res result_type<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> Arg1, <span style="color: #0000ff;">class</span> Arg2, <span style="color: #0000ff;">class</span> Res<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">struct</span> binary_function <span style="color: #666666;">//~ 二元函数对象基类</span>
<span style="color: #008000;">&#123;</span>
   <span style="color: #0000ff;">typedef</span> Arg1 first_argument_type<span style="color: #008080;">;</span>
   <span style="color: #0000ff;">typedef</span> Arg2 second_argument_type<span style="color: #008080;">;</span>
   <span style="color: #0000ff;">typedef</span> Res  result_type<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>使用这两个基类，首先需要包含头文件<functional>。</p>
<h5>Predicates</h5>
<p>　　Predicate是一种函数对象，返回值（应该是operator()的返回值）为布尔型，接受一个或者两个参数。通常用来判断对象的有效性（一个参数时）或者对两个对象进行比较（如less）。你可以根据自己的需要定义自己的Predicate，但STL已经定义了一些Predicate，你可以直接使用。</p>
<table>
<caption>Predicates</caption>
<tr>
<th>Predicate</th>
<th>类型</th>
<th>描述</th>
</tr>
<tr>
<td>equal_to<type>()</td>
<td>Binary</td>
<td>使用==判等</td>
</tr>
<tr>
<td>not_equal_to<type>()</td>
<td>Binary</td>
<td>使用!=判等</td>
</tr>
<tr>
<td>less<type>()</td>
<td>Binary</td>
<td>使用< </td>
</tr>
<tr>
<td>greater<type>()</td>
<td>Binary</td>
<td>使用> </td>
</tr>
<tr>
<td>less_equal<type>()</td>
<td>Binary</td>
<td>使用<= </td>
</tr>
<tr>
<td>greater_equal<type>()</td>
<td>Binary</td>
<td>使用>= </td>
</tr>
<tr>
<td>logical_not<type>()</td>
<td>Unary</td>
<td>使用!逻辑取反</td>
</tr>
<tr>
<td>logical_and<type>()</td>
<td>Binary</td>
<td>使用&#038;&#038;逻辑与</td>
</tr>
<tr>
<td>logical_or<type>()</td>
<td>Binary</td>
<td>使用||逻辑或</td>
</tr>
</table>
<h5>算术运算函数对象</h5>
<p>　　进行简单的算术运算，这类函数对象我用的很少，通常是自己定义。</p>
<table>
<caption>算术运算函数对象</caption>
<tr>
<th>函数对象</th>
<th>类型</th>
<th>描述</th>
</tr>
<tr>
<td>negate<type>()</td>
<td>Unary</td>
<td>使用-求负</td>
</tr>
<tr>
<td>plus<type>()</td>
<td>Binary</td>
<td>使用+加法</td>
</tr>
<tr>
<td>minus<type>()</td>
<td>Binary</td>
<td>使用-减法</td>
</tr>
<tr>
<td>multiplies<type>()</td>
<td>Binary</td>
<td>使用*乘法</td>
</tr>
<tr>
<td>divides<type>()</td>
<td>Binary</td>
<td>使用/除法</td>
</tr>
<tr>
<td>modulus<type>()</td>
<td>Binary</td>
<td>使用%求余</td>
</tr>
</table>
<h5>绑定Binders</h5>
<p>　　有两种绑定bind1st和bind2nd，它们可以将一个二元函数对象的其中一个参数绑定为某个已知的对象，从而得到一个一元函数对象。例如要在vector&lt;int&gt; v中查找等于372的值的位置，我可以将372绑定到equal_to&lt;int&gt;()的第一个或者第二个参数：</p>

<div class="wp_codebox"><table><tr id="p220947"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code" id="p2209code47"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> v<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">1000</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        v.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span>i<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span><span style="color: #008080;">::</span><span style="color: #007788;">iterator</span> it<span style="color: #008080;">;</span>
    it <span style="color: #000080;">=</span> find_if<span style="color: #008000;">&#40;</span>v.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, v.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, bind1st<span style="color: #008000;">&#40;</span>equal_to<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, <span style="color: #0000dd;">372</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #000040;">*</span>it<span style="color: #000080;">&lt;&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　其实，这里的bind1st和bind2nd并不是函数对象，只是模板函数而已。这两个函数分别返回类型为binder1st和binder2nd的函数对象。下面的代码，聪明的你肯定一看就懂：</p>

<div class="wp_codebox"><table><tr id="p220948"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
</pre></td><td class="code" id="p2209code48"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// bind1st</span>
<span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> Op<span style="color: #000080;">&gt;</span> 
<span style="color: #0000ff;">class</span> binder1st <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> unary_function
                  <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">second_argument_type</span>,
                   <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">result_type</span><span style="color: #000080;">&gt;</span>
<span style="color: #008000;">&#123;</span>
   Op op_<span style="color: #008080;">;</span>
   <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">first_argument_type</span> first_arg_<span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
      binder1st<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Op<span style="color: #000040;">&amp;</span> op,
                <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">first_argument_type</span><span style="color: #000040;">&amp;</span>
                first_arg<span style="color: #008000;">&#41;</span> <span style="color: #008080;">:</span> op_<span style="color: #008000;">&#40;</span>op<span style="color: #008000;">&#41;</span>,
               first_arg_<span style="color: #008000;">&#40;</span>first_arg<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
   <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">result_type</span> operator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
      <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">second_argument_type</span><span style="color: #000040;">&amp;</span> arg<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span>
   <span style="color: #008000;">&#123;</span>
      <span style="color: #0000ff;">return</span> op_<span style="color: #008000;">&#40;</span>first_arg_, arg<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
   <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> Op, <span style="color: #0000ff;">class</span> Arg<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">inline</span> binder1st<span style="color: #000080;">&lt;</span>Op<span style="color: #000080;">&gt;</span> bind1st<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Op<span style="color: #000040;">&amp;</span> op,
                             <span style="color: #0000ff;">const</span> Arg<span style="color: #000040;">&amp;</span> arg<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
   <span style="color: #0000ff;">return</span> binder1st<span style="color: #000080;">&lt;</span>Op<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>op, arg<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #666666;">// bind2nd</span>
<span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> Op<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">class</span> binder2nd <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> unary_function
   <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">first_argument_type</span>,
    <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">result_type</span><span style="color: #000080;">&gt;</span>
<span style="color: #008000;">&#123;</span>
   Op op_<span style="color: #008080;">;</span>
   <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">second_argument_type</span> second_arg_<span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
      binder2nd<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Op<span style="color: #000040;">&amp;</span> op,
                <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">second_argument_type</span><span style="color: #000040;">&amp;</span>
                                   second_arg<span style="color: #008000;">&#41;</span> <span style="color: #008080;">:</span> op_<span style="color: #008000;">&#40;</span>op<span style="color: #008000;">&#41;</span>,
                                   second_arg_<span style="color: #008000;">&#40;</span>second_arg<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
   <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">result_type</span> operator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">typename</span>
      Op<span style="color: #008080;">::</span><span style="color: #007788;">argument_type</span><span style="color: #000040;">&amp;</span> arg<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span>
   <span style="color: #008000;">&#123;</span>
      <span style="color: #0000ff;">return</span> op_<span style="color: #008000;">&#40;</span>arg, second_arg_<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
   <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> Op, <span style="color: #0000ff;">class</span> Arg<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">inline</span> binder2nd<span style="color: #000080;">&lt;</span>Op<span style="color: #000080;">&gt;</span> bind2nd<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Op<span style="color: #000040;">&amp;</span> op,
                             <span style="color: #0000ff;">const</span> Arg<span style="color: #000040;">&amp;</span> arg<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
   <span style="color: #0000ff;">return</span> binder2nd<span style="color: #000080;">&lt;</span>Op<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>op, arg<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<h5>Negaters</h5>
<p>　　Negater是针对Predicate设计的，它简单的将Predicate的返回值取反。有两个Negater，not1和not2，分别对一元和二元Predicate取反。</p>
<h5>Member Function Adapters</h5>
<p>　　有时候，你可能想让算法调用容器元素的成员函数，而不是外部函数。因为外部无法改变对象内的状态，且内部函数通常具有更高的效率。例如swap(string, string)总是没有string.swap(string)快速。又比如sort无法对list进行排序，这时候只能使用list.sort()来给链表排序。这时候就需要使用一定的方法将对象内部的函数“变成”函数对象，这样的函数对象叫做成员函数适配器，其实前面的binder也是一种适配器。看下面的例子：</p>

<div class="wp_codebox"><table><tr id="p220949"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code" id="p2209code49"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    vector<span style="color: #000080;">&lt;</span>list<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> <span style="color: #000080;">&gt;</span> v<span style="color: #008080;">;</span>
    v.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span>list<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    vector<span style="color: #000080;">&lt;</span>list<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> <span style="color: #000080;">&gt;</span><span style="color: #008080;">::</span><span style="color: #007788;">iterator</span> it<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span>it <span style="color: #000080;">=</span> v.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> it <span style="color: #000040;">!</span><span style="color: #000080;">=</span> v.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>it<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">20</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>it<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">insert</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>it<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, i<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
    for_each<span style="color: #008000;">&#40;</span>v.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, v.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, std<span style="color: #008080;">::</span><span style="color: #007788;">mem_fun_ref</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>list<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span><span style="color: #008080;">::</span><span style="color: #007788;">sort</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span>it <span style="color: #000080;">=</span> v.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> it <span style="color: #000040;">!</span><span style="color: #000080;">=</span> v.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>it<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span>list<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span><span style="color: #008080;">::</span><span style="color: #007788;">iterator</span> lt<span style="color: #008080;">;</span> lt <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>it<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>lt<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #000040;">*</span>lt<span style="color: #000080;">&lt;&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>上面的例子中，遍历vector&lt;list&lt;int&gt; &gt;并对链表进行排序。其中使用的是成员函数适配器mem_fun_ref，它返回的函数对象会以list&lt;int&gt;对象的引用为参数。另外一个mem_fun则是以指向list&lt;int&gt;对象的指针为参数。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/stl-functor-function-object/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[C++]exit &amp; abort &amp; 析构 &amp; 异常</title>
		<link>http://www.dutor.net/index.php/2010/04/exit-abort-des-except/</link>
		<comments>http://www.dutor.net/index.php/2010/04/exit-abort-des-except/#comments</comments>
		<pubDate>Mon, 26 Apr 2010 12:20:46 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[OS基础]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2187</guid>
		<description><![CDATA[<h4>进程之死</h4>
　　对于一个用C++写的程序，被加载至内存后运行，最终走向死亡。程序的死亡大致有三种：
<ul>
	<li><strong>自然死亡</strong>，即无疾而终，通常就是main()中的一个return 0;</li>
	<li><strong>自杀</strong>，当程序发现自己再活下去已经没有任何意义时，通常会选择自杀。当然，这种自杀也是一种请求式的自杀，即请求OS将自己毙掉。有两种方式：void exit(int status)和void abort(void)。</li>
	<li><strong>他杀</strong>，同现实不同的是，程序家族中的他杀行径往往是由自己至亲完成的，通常这个至亲就是他的生身父亲（还是母亲？）。C++并没有提供他杀的凶器，这些凶器往往是由OS直接或者间接（通过一些进程库，如pthread）提供的。</li>
</ul>
　　自然死是最完美的结局，他杀是我们最不愿意看到的，自杀虽是迫不得已，但主动权毕竟还是由程序自己掌控的。下面探究程序一下不同的死亡方式对对象的析构有何影响。]]></description>
			<content:encoded><![CDATA[<h4>进程之死</h4>
<p>　　对于一个用C++写的程序，被加载至内存后运行，最终走向死亡。程序的死亡大致有三种：</p>
<ul>
<li><strong>自然死亡</strong>，即无疾而终，通常就是main()中的一个return 0;</li>
<li><strong>自杀</strong>，当程序发现自己再活下去已经没有任何意义时，通常会选择自杀。当然，这种自杀也是一种请求式的自杀，即请求OS将自己毙掉。有两种方式：void exit(int status)和void abort(void)。</li>
<li><strong>他杀</strong>，同现实不同的是，程序家族中的他杀行径往往是由自己至亲完成的，通常这个至亲就是他的生身父亲（还是母亲？）。C++并没有提供他杀的凶器，这些凶器往往是由OS直接或者间接（通过一些进程库，如pthread）提供的。</li>
</ul>
<p>　　自然死是最完美的结局，他杀是我们最不愿意看到的，自杀虽是迫不得已，但主动权毕竟还是由程序自己掌控的。下面探究程序一下不同的死亡方式对对象的析构有何影响。</p>
<h4>程序死亡方式对对象析构的影响</h4>
<p>　　C++程序中大致有三种对象：全局对象、局部静态对象、局部非静态对象（自动对象）。举例说明之：</p>

<div class="wp_codebox"><table><tr id="p218750"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="code" id="p2187code50"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">struct</span> Foo
<span style="color: #008000;">&#123;</span>
    Foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Foo&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    ~Foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;~Foo&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #ff0000; font-style: italic;">/* some other sources here */</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
Foo Global<span style="color: #008080;">;</span>
<span style="color: #0000ff;">void</span> quit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">static</span> Foo StaticLocal<span style="color: #008080;">;</span>
    Foo Local<span style="color: #008080;">;</span>
    <span style="color: #666666;">//~ quit();</span>
    <span style="color: #666666;">//~ abort();</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> quit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    Foo AnotherLocal<span style="color: #008080;">;</span>
    <span style="color: #0000dd;">exit</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　编译运行这个程序，程序将正常退出。运行过程中，Global对象在进入main之前首先被构造，其次是StaticLocal和Local。main函数退出之前，Local和StaticLocal被析构，main退出后Global也将被析构。<br />
　　如果将17行处quit()的注释去掉，我们将会看到4个对象被构造，但却只有两个对象被析构，分别是Global和StaticLocal对象，其他两个对象Local和AnotherLocal对象的析构函数将不会被调用。<br />
　　如果将18行处abort()的注释去掉（quit()被注释），3个对象对象被构造，但在程序退出之前没有任何一个对象的析构函数被调用。<br />
　　也就是说，正常情况下，所有类型的对象都将被析构；由exit退出时只有非自动对象被析构；abort被调用时，程序将直接退出，任何对象的析构函数都不会调用。下面着重介绍下exit的行为。</p>
<h4>exit做了什么</h4>
<p>　　介绍exit之前，不得不提void atexit(void (*f)(void) )函数。atexit，顾名思义，它描述了exit里面要做些什么。可以看出，它接受一个void f(void)形式的函数的指针。使用atexit我们可以向exit注册一些列的函数，这些函数在exit中被调用，调用的顺序与它们被注册的顺序相反。你可以使用下面的代码来验证：</p>

<div class="wp_codebox"><table><tr id="p218751"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code" id="p2187code51"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">void</span> f1<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;f1&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> f2<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;f2&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000dd;">atexit</span><span style="color: #008000;">&#40;</span>f1<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">atexit</span><span style="color: #008000;">&#40;</span>f2<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">exit</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　void exit(int status)被调用时，它首先调用全局的或者静态的对象的析构函数，然后调用atexit所注册的函数。如果这些函数中的某一个再次调用exit，your nightmare is coming。最后，exit会将代表程序执行状态的status<strong>“返回”</strong>（确切的说应该叫做传递，因为exit永远不会返回调用方）给当前程序的父进程。<br />
　　值得一提的是，执行exit结束程序，虽然自动对象的析构函数不被调用，但当程序结束时，OS会将该程序占用的资源全部释放。这些资源包括该程序申请的内存（堆）、打开的文件句柄、管道（Unix/Linux）、socket等。这样一来，似乎那些析构函数不被调用并不会有什么问题。确实，但可惜这只适用于单线程的程序。对于多线程程序来说，只有当整个进程结束时，它占用的资源才会被OS释放，这时某个线程的exit就可能带来麻烦（比如内存泄露）。怎么办呢？</p>
<h4>使用异常</h4>
<p>　　使用C++提供的异常机制，可以很好的解决上面提出的问题。我们可以在需要exit的地方抛出（throw）异常，然后在捕获（catch）异常处调用exit，这样，所有需要的析构函数都将被调用。代码通常是这个样子滴：</p>

<div class="wp_codebox"><table><tr id="p218752"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
</pre></td><td class="code" id="p2187code52"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;cstdlib&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">struct</span> Foo
<span style="color: #008000;">&#123;</span>
    Foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Foo&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    ~Foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;~Foo&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #ff0000; font-style: italic;">/* some other sources here */</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">struct</span> except<span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> exception
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> what<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">throw</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #FF0000;">&quot;except&quot;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
Foo Global<span style="color: #008080;">;</span>
<span style="color: #0000ff;">void</span> quit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">try</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">static</span> Foo StaticLocal<span style="color: #008080;">;</span>
        Foo Local<span style="color: #008080;">;</span>
        quit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">catch</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> exception<span style="color: #000040;">&amp;</span> e<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cerr</span><span style="color: #000080;">&lt;&lt;</span>e.<span style="color: #007788;">what</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
        <span style="color: #0000dd;">exit</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> quit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    Foo AnotherLocal<span style="color: #008080;">;</span>
    <span style="color: #666666;">//~ exit(1);</span>
    <span style="color: #0000ff;">throw</span> except<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>输出：</p>
<pre>
Foo
Foo
Foo
Foo
~Foo
~Foo
except
~Foo
~Foo
</pre>
<p><strong>补充：</strong>还有一个与atexit()相似的函数叫on_exit()，Google之。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/exit-abort-des-except/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[C++]覆盖std内的名字</title>
		<link>http://www.dutor.net/index.php/2010/04/name-look-up/</link>
		<comments>http://www.dutor.net/index.php/2010/04/name-look-up/#comments</comments>
		<pubDate>Tue, 20 Apr 2010 08:07:08 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2171</guid>
		<description><![CDATA[　　在现行的C++标准中有这么一个名字，std，它是一个namespace(命名空间)。C++标准库的所有类型/对象/函数/模板都定义在这个命名空间中。关于"What namespace? Why namespace? How namespace?" 的问题，任何一本基础的C++读物中都会有介绍，此处略过。为了使用std内定义的对象，可供使用的语法无非是
<pre lang="cpp" line="1">
std::vector<int> ivec;
//~ or
using std::vector;
vector<int> ivec;
//~ or
using namespace std;
vector<int> ivec;
</pre>
　　现在有这样一种需要，我想为std内的某种类型(比如string)重载操作符，而不想使用std内为我们提供的版本。]]></description>
			<content:encoded><![CDATA[<p>　　在现行的C++标准中有这么一个名字，std，它是一个namespace(命名空间)。C++标准库的所有类型/对象/函数/模板都定义在这个命名空间中。关于&#8221;What namespace? Why namespace? How namespace?&#8221; 的问题，任何一本基础的C++读物中都会有介绍，此处略过。为了使用std内定义的对象，可供使用的语法无非是</p>

<div class="wp_codebox"><table><tr id="p217153"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p2171code53"><pre class="cpp" style="font-family:monospace;">std<span style="color: #008080;">::</span><span style="color: #007788;">vector</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> ivec<span style="color: #008080;">;</span>
<span style="color: #666666;">//~ or</span>
<span style="color: #0000ff;">using</span> std<span style="color: #008080;">::</span><span style="color: #007788;">vector</span><span style="color: #008080;">;</span>
vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> ivec<span style="color: #008080;">;</span>
<span style="color: #666666;">//~ or</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> ivec<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>　　现在有这样一种需要，我想为std内的某种类型(比如string)重载操作符，而不想使用std内为我们提供的版本。很简单：</p>

<div class="wp_codebox"><table><tr id="p217154"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code" id="p2171code54"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;string&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
<span style="color: #0000ff;">bool</span> operator<span style="color: #000080;">&lt;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> string<span style="color: #000040;">&amp;</span> l, <span style="color: #0000ff;">const</span> string<span style="color: #000040;">&amp;</span> r<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> l <span style="color: #000080;">&gt;</span> r<span style="color: #008080;">;</span> <span style="color: #666666;">//~ 逆天而行了 :-)</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>string<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;dutor&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #000080;">&lt;</span>string<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;ivan&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　运行这段代码，确实会得到我们想要的结果，dutor > ivan. 但是对于std内其他使用string的operator<()的对象还会这样吗？</p>

<div class="wp_codebox"><table><tr id="p217155"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code" id="p2171code55"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;string&gt;</span>
<span style="color: #339900;">#include &lt;set&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
<span style="color: #0000ff;">bool</span> operator<span style="color: #000080;">&lt;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> string<span style="color: #000040;">&amp;</span> l, <span style="color: #0000ff;">const</span> string<span style="color: #000040;">&amp;</span> r<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> l <span style="color: #000080;">&gt;</span> r<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    set<span style="color: #000080;">&lt;</span>string<span style="color: #000080;">&gt;</span> Set<span style="color: #008080;">;</span>
    Set.<span style="color: #007788;">insert</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;ivan&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    Set.<span style="color: #007788;">insert</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;dutor&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span>set<span style="color: #000080;">&lt;</span>string<span style="color: #000080;">&gt;</span><span style="color: #008080;">::</span><span style="color: #007788;">iterator</span> it <span style="color: #000080;">=</span> Set.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            it <span style="color: #000040;">!</span><span style="color: #000080;">=</span> Set.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>it<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #000040;">*</span>it<span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　这次ivan会在dutor前面输出吗？很遗憾，dutor被首先输出。不要忘了，std内还有一个operator<(const string&#038;, const string&#038;)呢！set调用的正是std里面的版本！那么我们有什么办法可以让set调用我们自己的operator<()呢？这涉及到C++的名字查找机制，C++采用的是一种懒惰的名字查找机制，也可以说是一种非贪婪式的查找。以本例来说，set与原始版本的operator<同属于std命名空间，set就会就近使用这个版本，而不是我们的自定义版本，而我们在main中使用的却是自定义版本。<br />
　　现在如何让set使用自定义的operator<已经变得明朗了，我们仅仅需要把我们的这个operator<添加到std中：</p>

<div class="wp_codebox"><table><tr id="p217156"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p2171code56"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">namespace</span> std<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">bool</span> operator<span style="color: #000080;">&lt;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> string<span style="color: #000040;">&amp;</span> l, <span style="color: #0000ff;">const</span> string<span style="color: #000040;">&amp;</span> r<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> l <span style="color: #000080;">&gt;</span> r<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　关于C++的名字查找机制，这里提到的只是皮毛而已，很多参考资料中到都做了深入的描述，请自行查阅。</p>
<p>　　刚才在当当买书，又看到雷人的一幕（我为什么说又？）：<br />
<a href="http://www.dutor.net/index.php/2010/04/name-look-up/stl1/" rel="attachment wp-att-2174"><img src="http://www.dutor.net/wp-content/uploads/2010/04/stl1.png" alt="" title="stl1" width="446" height="200" class="aligncenter size-full wp-image-2174" /></a><br />
<a href="http://www.dutor.net/index.php/2010/04/name-look-up/stl2/" rel="attachment wp-att-2175"><img src="http://www.dutor.net/wp-content/uploads/2010/04/stl2.png" alt="" title="stl2" width="480" height="222" class="aligncenter size-full wp-image-2175" /></a><br />
实在想不通，这￥0.56是哪里来的？</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/name-look-up/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Visual Studio中的Functional</title>
		<link>http://www.dutor.net/index.php/2010/04/visual-studio-functional/</link>
		<comments>http://www.dutor.net/index.php/2010/04/visual-studio-functional/#comments</comments>
		<pubDate>Sun, 18 Apr 2010 09:04:46 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[麻烦]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2149</guid>
		<description><![CDATA[　　今天在VS中遇到一个十分诡异的事情，先看下面这个简单的程序：
<pre lang="cpp" line="1">
class cmp
{
public:
	bool operator()(long long l, long long r)
	{
		//~ 此间内容可略去不看。
		//~ 如果l和r含有的digits完全相同则返回false,
		//~ 如125 vs. 512
		char tmp1[1024], tmp2[1024];
		sprintf(tmp1,"%ld",l);
		sprintf(tmp2,"%ld",r);
		sort(tmp1, tmp1+strlen(tmp1));
		sort(tmp2, tmp2+strlen(tmp2));
		if (!strcmp(tmp1, tmp2))
		{
			return false;
		}
		return true;
	}
};
</pre>
]]></description>
			<content:encoded><![CDATA[<p>　　今天在VS中遇到一个十分诡异的事情，先看下面这个简单的程序：</p>

<div class="wp_codebox"><table><tr id="p214957"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
</pre></td><td class="code" id="p2149code57"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;set&gt;</span>
<span style="color: #339900;">#include &lt;algorithm&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> cmp
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
	<span style="color: #0000ff;">bool</span> operator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">long</span> <span style="color: #0000ff;">long</span> l, <span style="color: #0000ff;">long</span> <span style="color: #0000ff;">long</span> r<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #666666;">//~ 此间内容可略去不看。</span>
		<span style="color: #666666;">//~ 如果l和r含有的digits完全相同则返回false,</span>
		<span style="color: #666666;">//~ 如125 vs. 512</span>
		<span style="color: #0000ff;">char</span> tmp1<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">1024</span><span style="color: #008000;">&#93;</span>, tmp2<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">1024</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
		<span style="color: #0000dd;">sprintf</span><span style="color: #008000;">&#40;</span>tmp1,<span style="color: #FF0000;">&quot;%ld&quot;</span>,l<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		<span style="color: #0000dd;">sprintf</span><span style="color: #008000;">&#40;</span>tmp2,<span style="color: #FF0000;">&quot;%ld&quot;</span>,r<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		sort<span style="color: #008000;">&#40;</span>tmp1, tmp1<span style="color: #000040;">+</span><span style="color: #0000dd;">strlen</span><span style="color: #008000;">&#40;</span>tmp1<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		sort<span style="color: #008000;">&#40;</span>tmp2, tmp2<span style="color: #000040;">+</span><span style="color: #0000dd;">strlen</span><span style="color: #008000;">&#40;</span>tmp2<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span><span style="color: #0000dd;">strcmp</span><span style="color: #008000;">&#40;</span>tmp1, tmp2<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span>
			<span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
		<span style="color: #008000;">&#125;</span>
		<span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	set<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">long</span> <span style="color: #0000ff;">long</span>,cmp <span style="color: #000080;">&gt;</span> Set<span style="color: #008080;">;</span>
	<span style="color: #0000ff;">int</span> a<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">15</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
	Set.<span style="color: #007788;">insert</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	Set.<span style="color: #007788;">insert</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 此处疯狂</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　程序在这个地方跑偏了，弹出这么个东西</p>
<p><a href="http://www.dutor.net/index.php/2010/04/visual-studio-functional/vsnaocan/" rel="attachment wp-att-2150"><img src="http://www.dutor.net/wp-content/uploads/2010/04/vsnaocan.jpg" alt="" title="vsnaocan" width="377" height="244" class="aligncenter size-full wp-image-2150" /></a><br />
　　可是set的key_compare我一直都是这么用的啊。把程序拷到Linux下面用g++就一切正常。望达人指教。</p>
<h4>更新</h4>
<p>　　Johnny同学给的贴文中提到了，一个predicate对于任两个参数a,b不能返回<strong>两个true</strong>，即pred(a, b)和pred(b, a)不能同时返回true，这是strict weak规则决定的。代码为证：</p>

<div class="wp_codebox"><table><tr id="p214958"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p2149code58"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> _Pr, <span style="color: #0000ff;">class</span> _Ty1, <span style="color: #0000ff;">class</span> _Ty2<span style="color: #000080;">&gt;</span> <span style="color: #0000ff;">inline</span>
    <span style="color: #0000ff;">bool</span> __CLRCALL_OR_CDECL _Debug_lt_pred<span style="color: #008000;">&#40;</span>_Pr _Pred, _Ty1<span style="color: #000040;">&amp;</span> _Left, _Ty2<span style="color: #000040;">&amp;</span> _Right,
        <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">wchar_t</span> <span style="color: #000040;">*</span>_Where, <span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">int</span> _Line<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>    <span style="color: #666666;">// test if _Pred(_Left, _Right)  and _Pred is strict weak ordering</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>_Pred <span style="color: #008000;">&#40;</span>_Left, _Right<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">false</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>_Pred<span style="color: #008000;">&#40;</span>_Right, _Left<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
        _DEBUG_ERROR2<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;invalid operator&lt;&quot;</span>, _Where, _Line<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">true</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　即是说，在调试时（特指Visual Studio的debug模式），bool _Debug_lt_pred()模板函数会对pred(a, b)的返回结果进行检查。如果pred(a, b)返回false没有问题。但如果其返回true，那么_Debug_lt_pred还会对pred(b, a)进行检查，若也返回true就会触发assert（有上图为证）。<br />
　　对于本文最初的代码，为了通过的_Debug_lt_pred的检查，我可以：</p>

<div class="wp_codebox"><table><tr id="p214959"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code" id="p2149code59"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> cmp
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
	<span style="color: #0000ff;">bool</span> operator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">long</span> <span style="color: #0000ff;">long</span> l, <span style="color: #0000ff;">long</span> <span style="color: #0000ff;">long</span> r<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #666666;">//~ ……</span>
		<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span><span style="color: #0000dd;">strcmp</span><span style="color: #008000;">&#40;</span>tmp1, tmp2<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span>
			<span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
		<span style="color: #008000;">&#125;</span>
                <span style="color: #0000ff;">else</span>
		        <span style="color: #0000ff;">return</span> l <span style="color: #000080;">&lt;</span> r<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>这样就保证了cmp::(long long, long long)不会返回<strong>&#8220;两个true&#8221;</strong>了</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/visual-studio-functional/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>[C++]优先级队列priority_queque</title>
		<link>http://www.dutor.net/index.php/2010/03/priority_queque/</link>
		<comments>http://www.dutor.net/index.php/2010/03/priority_queque/#comments</comments>
		<pubDate>Sat, 27 Mar 2010 11:15:59 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[STL]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2096</guid>
		<description><![CDATA[　　好久没写C++没用STL了，今天在STLChina泡了一下午。完整的代码只写了这么一个，贴上来吧。
　　写了两个类，Max_Heap和Min_Heap，以他们特例化priority_queue，可以方便地实现最大、最小堆。写完了忽然又觉得这俩类似乎是多此一举了，完全可以用greater<int>来实现最小堆，但由priority_queue的模板定义看出，那样就必须提供一个容器类型，比如vector<int>。
　　最后还写了测试用例：找出ｎ个数中最大的k个。
<pre lang="cpp" line="1">
/*
template < class T, class Container = vector<T>,
           class Compare = less<typename Container::value_type> > class priority_queue;

explicit priority_queue ( const Compare&#038; x = Compare(),
                          const Container&#038; y = Container() );
template <class InputIterator>
         priority_queue ( InputIterator first, InputIterator last,
                          const Compare&#038; x = Compare(),
                          const Container&#038; y = Container() );
*/
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　好久没写C++没用STL了，今天在STLChina泡了一下午。完整的代码只写了这么一个，贴上来吧。<br />
　　写了两个类，Max_Heap和Min_Heap，以他们特例化priority_queue，可以方便地实现最大、最小堆。写完了忽然又觉得这俩类似乎是多此一举了，完全可以用greater<int>来实现最小堆，但由priority_queue的模板定义看出，那样就必须提供一个容器类型，比如vector<int>。<br />
　　最后还写了测试用例：找出ｎ个数中最大的k个。</p>

<div class="wp_codebox"><table><tr id="p209660"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
</pre></td><td class="code" id="p2096code60"><pre class="cpp" style="font-family:monospace;"><span style="color: #ff0000; font-style: italic;">/*
template &lt; class T, class Container = vector&lt;T&gt;,
           class Compare = less&lt;typename Container::value_type&gt; &gt; class priority_queue;
&nbsp;
explicit priority_queue ( const Compare&amp; x = Compare(),
                          const Container&amp; y = Container() );
template &lt;class InputIterator&gt;
         priority_queue ( InputIterator first, InputIterator last,
                          const Compare&amp; x = Compare(),
                          const Container&amp; y = Container() );
*/</span>
<span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;queue&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">struct</span> Max_Heap
<span style="color: #008000;">&#123;</span>
    Max_Heap<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> n<span style="color: #008000;">&#41;</span><span style="color: #008080;">:</span> _n<span style="color: #008000;">&#40;</span>n<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    operator <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> _n<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span> <span style="color: #666666;">//在需要的地方隐式类型转换</span>
    <span style="color: #0000ff;">int</span> _n<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">struct</span> Min_Heap
<span style="color: #008000;">&#123;</span>
    Min_Heap<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> n<span style="color: #008000;">&#41;</span><span style="color: #008080;">:</span> _n<span style="color: #008000;">&#40;</span>n<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    operator <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> _n<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span> <span style="color: #666666;">//在需要的地方隐式类型转换</span>
    <span style="color: #0000ff;">int</span> _n<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">bool</span> operator <span style="color: #000080;">&lt;</span> <span style="color: #008000;">&#40;</span>Max_Heap l, Max_Heap r<span style="color: #008000;">&#41;</span> <span style="color: #666666;">//~ 正常的&lt;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> l._n <span style="color: #000080;">&lt;</span> r._n<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">bool</span> operator <span style="color: #000080;">&lt;</span> <span style="color: #008000;">&#40;</span>Min_Heap l, Min_Heap r<span style="color: #008000;">&#41;</span> <span style="color: #666666;">//~ 反义的&lt;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> l._n <span style="color: #000080;">&gt;</span> r._n<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">int</span>
main <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    priority_queue<span style="color: #000080;">&lt;</span>Min_Heap<span style="color: #000080;">&gt;</span> heap<span style="color: #008080;">;</span> <span style="color: #666666;">//~ 最小堆</span>
    <span style="color: #666666;">//priority_queue&lt;Max_Heap&gt; heap; //~ 最大堆</span>
    <span style="color: #666666;">//~ 测试用例</span>
    <span style="color: #666666;">//~ 前K个最大值</span>
    <span style="color: #0000ff;">int</span> k <span style="color: #000080;">=</span> <span style="color: #0000dd;">5</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">int</span> tmp<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> k<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>tmp<span style="color: #008080;">;</span>
        heap.<span style="color: #007788;">push</span><span style="color: #008000;">&#40;</span>tmp<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span><span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>tmp<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>tmp <span style="color: #000080;">&gt;</span> heap.<span style="color: #007788;">top</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>._n<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            heap.<span style="color: #007788;">push</span><span style="color: #008000;">&#40;</span>tmp<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            heap.<span style="color: #007788;">pop</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000dd;">cin</span>.<span style="color: #007788;">clear</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span>heap.<span style="color: #007788;">size</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>heap.<span style="color: #007788;">top</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>._n<span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">' '</span><span style="color: #008080;">;</span>
        heap.<span style="color: #007788;">pop</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/03/priority_queque/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一个关于大小端的问题</title>
		<link>http://www.dutor.net/index.php/2010/03/big-little-endian/</link>
		<comments>http://www.dutor.net/index.php/2010/03/big-little-endian/#comments</comments>
		<pubDate>Sun, 14 Mar 2010 09:14:59 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[大小端]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2015</guid>
		<description><![CDATA[　　所谓大小端模式，就是一个关于数据字节在存储顺序的问题。在某些编程环境中，了解大小端是非常重要的，比如汇编和网络编程中，对存取和发送、接收数据的字节序都有严格的要求。当然，在高层次，你很少会需要考虑到这些。为什么会有大小端模式之分呢？这是因为在计算机系统中，我们是以字节为单位的，每个地址单元都对应着一个字节。在许多计算机语言中，许多数据类型都是多字节的，这就产生了多字节数据在内存中存放数据的问题。在大端模式（Big-endian）中，数据的低位（就是权值较小的后面那几位）保存在内存的高地址中，而数据的高位，保存在内存的低地址中；在小端模式（Little-endian）中，数据低位就存放在内存的低位。了解了什么是大小端，看下面的程序，输出结果是什么？
<pre lang="c" line="1">
#include <stdio.h>
int
main()
{
    int a[] = {1, 2, 3, 4, 5};
    int *ptr1 = (int*) (&#038;a + 1) - 1;
    int *ptr2 = (int*) ((int)a + 1);
    printf("%x, %x\n", *ptr1, *ptr2);
    return 0;
}
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　所谓大小端模式，就是一个关于数据字节在存储顺序的问题。在某些编程环境中，了解大小端是非常重要的，比如汇编和网络编程中，对存取和发送、接收数据的字节序都有严格的要求。当然，在高层次，你很少会需要考虑到这些。为什么会有大小端模式之分呢？这是因为在计算机系统中，我们是以字节为单位的，每个地址单元都对应着一个字节。在许多计算机语言中，许多数据类型都是多字节的，这就产生了多字节数据在内存中存放数据的问题。在大端模式（Big-endian）中，数据的低位（就是权值较小的后面那几位）保存在内存的高地址中，而数据的高位，保存在内存的低地址中；在小端模式（Little-endian）中，数据低位就存放在内存的低位。了解了什么是大小端，看下面的程序，输出结果是什么？</p>

<div class="wp_codebox"><table><tr id="p201561"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p2015code61"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdio.h&gt;</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;">int</span> a<span style="color: #009900;">&#91;</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;">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> <span style="color: #339933;">*</span>ptr1 <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>a <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> <span style="color: #339933;">*</span>ptr2 <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span>a <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</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;%x, %x<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #339933;">*</span>ptr1<span style="color: #339933;">,</span> <span style="color: #339933;">*</span>ptr2<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></td></tr></table></div>

<p>　　在我的机器上的输出时5, 2000000，可以看出是处理器是小端模式的。为什么呢？<br />
　　首先*ptr1 == 5是没有疑问的。<br />
　　再看看，*ptr2：</p>
<table>
<tr>
<td>内存编号</td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>……</td>
</tr>
<tr>
<td>数据内容(16进制)</td>
<td>0&#215;01</td>
<td>0&#215;00</td>
<td>0&#215;00</td>
<td>0&#215;00</td>
<td>0&#215;02</td>
<td>……</td>
</tr>
</table>
<p>　　指针ptr2指向1号单元，因此*ptr2就是0&#215;02000000。在大端模式的机器中内存布局应该是这样滴：</p>
<table>
<tr>
<td>内存编号</td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>……</td>
</tr>
<tr>
<td>数据内容(16进制)</td>
<td>0&#215;00</td>
<td>0&#215;00</td>
<td>0&#215;00</td>
<td>0&#215;01</td>
<td>0&#215;00</td>
<td>……</td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/03/big-little-endian/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>[C++]虚 静态函数</title>
		<link>http://www.dutor.net/index.php/2010/03/virtual-static-function/</link>
		<comments>http://www.dutor.net/index.php/2010/03/virtual-static-function/#comments</comments>
		<pubDate>Sat, 06 Mar 2010 10:44:28 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2012</guid>
		<description><![CDATA[　　C++类的静态函数是属于类型的，而不是某个对象的，因此把它声明成Virtual也没什么实际意义。那么运行下面这段程序，会产生什么样的结果呢？
<pre lang="cpp" line="1">
#include <iostream>
using namespace std;
class Base
{
public:
    static void foo() { cout<<"Base"<<endl; }
    virtual void bar() { foo(); }
};
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　C++类的静态函数是属于类型的，而不是某个对象的，因此把它声明成Virtual也没什么实际意义。那么运行下面这段程序，会产生什么样的结果呢？</p>

<div class="wp_codebox"><table><tr id="p201262"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code" id="p2012code62"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> Base
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Base&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> bar<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> Derived<span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> Base
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Derived&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> bar<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span> main
<span style="color: #008000;">&#123;</span>
    Base <span style="color: #000040;">*</span> p <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> Derived<span style="color: #008080;">;</span>
    p<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>bar<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">delete</span> p<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/03/virtual-static-function/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>[Tricks]C++成员函数和静态变量</title>
		<link>http://www.dutor.net/index.php/2010/02/cpp-fun-st/</link>
		<comments>http://www.dutor.net/index.php/2010/02/cpp-fun-st/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 15:34:18 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=1989</guid>
		<description><![CDATA[　　想一下，下面的代码片段会输出什么？
<pre lang="cpp" line="1">
#include <iostream>
class Test
{
public:
    void print() const
    {
        std::cout<<_int<<std::endl;
    }
private:
    static int _int;
};
int Test::_int = 0;
int
main(int argc, char **argv)
{
    Test TArray[10];
    TArray[100].print();
    return 0;
}
</pre>
　　May you note something, anyhow.]]></description>
			<content:encoded><![CDATA[<p>　　想一下，下面的代码片段会输出什么？</p>

<div class="wp_codebox"><table><tr id="p198963"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code" id="p1989code63"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #0000ff;">class</span> Test
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">void</span> print<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span>
    <span style="color: #008000;">&#123;</span>
        std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>_int<span style="color: #000080;">&lt;&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">int</span> _int<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span> Test<span style="color: #008080;">::</span>_int <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    Test TArray<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">10</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
    TArray<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">100</span><span style="color: #008000;">&#93;</span>.<span style="color: #007788;">print</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　May you note something, anyhow.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/02/cpp-fun-st/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>char &amp; * &amp; []</title>
		<link>http://www.dutor.net/index.php/2009/11/char-pointer/</link>
		<comments>http://www.dutor.net/index.php/2009/11/char-pointer/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 14:12:45 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[C]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=1731</guid>
		<description><![CDATA[<pre lang="cpp" line="1">
void fun1(char * str) {}
void fun2(char ** str) {}

//~ int main(int argc, char ** argv)
int main(int argc, char * argv[])
{
	char str1[] = "Hello, Piggy!";
	char str2[][4] = "Hello, Piggy!";
	fun1(str1);
	fun2(str2);
	fun2(&#038;str1);
	return 0;
}
</pre>
　　上面的snippet有错误吗？有几个？你能找出来并说出原因吗？4、5两行有区别吗？想一下，然后看gcc给出的错误信息，]]></description>
			<content:encoded><![CDATA[
<div class="wp_codebox"><table><tr id="p173164"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code" id="p1731code64"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> fun1<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span> str<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> fun2<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span> str<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #666666;">//~ int main(int argc, char ** argv)</span>
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span> argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">char</span> str1<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;Hello, Piggy!&quot;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">char</span> str2<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span><span style="color: #0000dd;">4</span><span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;Hello, Piggy!&quot;</span><span style="color: #008080;">;</span>
	fun1<span style="color: #008000;">&#40;</span>str1<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	fun2<span style="color: #008000;">&#40;</span>str2<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	fun2<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>str1<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　上面的snippet有错误吗？有几个？你能找出来并说出原因吗？4、5两行有区别吗？想一下，然后看gcc给出的错误信息，</p>
<pre>
test.c: In function ‘main’:
test.c:9: error: invalid initializer
test.c:11: warning: passing argument 1 of ‘fun2’ from incompatible pointer type
test.c:4: note: expected ‘char **’ but argument is of type ‘char (*)[4]’
test.c:12: warning: passing argument 1 of ‘fun2’ from incompatible pointer type
test.c:4: note: expected ‘char **’ but argument is of type ‘char (*)[14]’
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2009/11/char-pointer/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>内存泄漏小陷阱</title>
		<link>http://www.dutor.net/index.php/2009/11/mem-leak-trap/</link>
		<comments>http://www.dutor.net/index.php/2009/11/mem-leak-trap/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 04:36:20 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[字符串]]></category>
		<category><![CDATA[汇编]]></category>
		<category><![CDATA[虚拟内存]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=1681</guid>
		<description><![CDATA[<pre lang="cpp" line="1">
int
main()
{
	char * str = new char[32];
	str = "Hello, Piggy!";
	return 0;
}
</pre>
这样是会内存泄漏的……而我一直都不知道……不过想来也自然，因为这样是允许的，char *str = "Hello, Piggy!";，“程序中的字符串被存放在常量存储区”不要把这句话当成耳旁风，谨记。]]></description>
			<content:encoded><![CDATA[
<div class="wp_codebox"><table><tr id="p168165"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p1681code65"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span> str <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> <span style="color: #0000ff;">char</span><span style="color: #008000;">&#91;</span><span style="color: #0000dd;">32</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
	str <span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;Hello, Piggy!&quot;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>这样是会内存泄漏的……而我一直都不知道……</p>

<div class="wp_codebox"><table><tr id="p168166"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code" id="p1681code66"><pre class="asm" style="font-family:monospace;"><span style="color: #339933;">.</span>LC0<span style="color: #339933;">:</span>
	<span style="color: #339933;">.</span>string	<span style="color: #7f007f;">&quot;Hello, Piggy!&quot;</span>
	<span style="color: #339933;">.</span>text
<span style="color: #339933;">.</span>globl main
	<span style="color: #339933;">.</span><span style="color: #000000; font-weight: bold;">type</span>	main<span style="color: #339933;">,</span> @function
main<span style="color: #339933;">:</span>
	andl	$<span style="color: #339933;">-</span><span style="color: #0000ff;">16</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	subl	$<span style="color: #0000ff;">32</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	movl	$<span style="color: #0000ff;">32</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span>
	<span style="color: #00007f; font-weight: bold;">call</span>	_Znaj
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">28</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span>
	movl	$<span style="color: #339933;">.</span>LC0<span style="color: #339933;">,</span> <span style="color: #0000ff;">28</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> <span style="color: #666666; font-style: italic;">;把str给覆盖了</span></pre></td></tr></table></div>

<p>不过想来也自然，因为这样是允许的，char *str = &#8220;Hello, Piggy!&#8221;;，“程序中的字符串被存放在常量存储区”不要把这句话当成耳旁风，谨记。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2009/11/mem-leak-trap/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>

