﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-学习一下-记录一下-随笔分类-C/C++</title><link>http://www.cppblog.com/hello8706/category/13370.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 15 Apr 2011 01:02:40 GMT</lastBuildDate><pubDate>Fri, 15 Apr 2011 01:02:40 GMT</pubDate><ttl>60</ttl><item><title>c/c++中内存区域划分大总结</title><link>http://www.cppblog.com/hello8706/archive/2010/11/03/132271.html</link><dc:creator>小火球</dc:creator><author>小火球</author><pubDate>Wed, 03 Nov 2010 03:04:00 GMT</pubDate><guid>http://www.cppblog.com/hello8706/archive/2010/11/03/132271.html</guid><wfw:comment>http://www.cppblog.com/hello8706/comments/132271.html</wfw:comment><comments>http://www.cppblog.com/hello8706/archive/2010/11/03/132271.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/hello8706/comments/commentRss/132271.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/hello8706/services/trackbacks/132271.html</trackback:ping><description><![CDATA[<p>一. 在c中分为这几个存储区<br>1.栈 - 由编译器自动分配释放<br>2.堆 - 一般由程序员分配释放，若程序员不释放，程序结束时可能由OS回收<br>3.全局区（静态区），全局变量和静态变量的存储是放在一块的，初始化的全局变量和静态变量在一块区域，未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。- 程序结束释放<br>4.另外还有一个专门放常量的地方。- 程序结束释放<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>在函数体中定义的变量通常是在栈上，用malloc, calloc, realloc等分配内存的函数分配得到的就是在堆上。在所有函数体外定义的是全局量，加了static修饰符后不管在哪里都存放在全局区（静态区）,在所有函数体外定义的static变量表示在该文件中有效，不能extern到别的文件用，在函数体内定义的static表示只在该函数体内有效。另外，函数中的"adgfdf"这样的字符串存放在常量区。比如：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">全局初始化区</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p1;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">全局未初始化区</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;b;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">栈</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;s[]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">abc</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">栈</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p2;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">栈</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p3&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">123456</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">123456{post.content}在常量区，p3在栈上</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;c&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">全局（静态）初始化区</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;p1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)malloc(</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">分配得来得10字节的区域在堆区</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;p2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)malloc(</span><span style="COLOR: #000000">20</span><span style="COLOR: #000000">);&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">分配得来得20字节的区域在堆区</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;strcpy(p1,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">123456</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">123456{post.content}放在常量区，编译器可能会将它与p3所指向的"123456"优化成一块</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">}</span></div>
<p>&nbsp;</p>
<p>二.在C++中，内存分成5个区，他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区<br>1.栈，就是那些由编译器在需要的时候分配，在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。<br>2.堆，就是那些由new分配的内存块，他们的释放编译器不去管，由我们的应用程序去控制，一般一个new就要对应一个delete。如果程序员没有释放掉，那么在程序结束后，操作系统会自动回收。<br>3.自由存储区，就是那些由malloc等分配的内存块，他和堆是十分相似的，不过它是用free来结束自己的生命的。<br>4.全局/静态存储区，全局变量和静态变量被分配到同一块内存中，在以前的C语言中，全局变量又分为初始化的和未初始化的，在C++里面没有这个区分了，他们共同占用同一块内存区。<br>5.常量存储区，这是一块比较特殊的存储区，他们里面存放的是常量，不允许修改（当然，你要通过非正当手段也可以修改）</p>
<p>三. 谈谈堆与栈的关系与区别<br>具体地说，现代计算机(串行执行机制)，都直接在代码底层支持栈的数据结构。这体现在，有专门的寄存器指向栈所在的地址，有专门的机器指令完成数据入栈出栈的操作。这种机制的特点是效率高，支持的数据有限，一般是整数，指针，浮点数等系统直接支持的数据类型，并不直接支持其他的数据结构。因为栈的这种特点，对栈的使用在程序中是非常频繁的。对子程序的调用就是直接利用栈完成的。机器的call指令里隐含了把返回地址推入栈，然后跳转至子程序地址的操作，而子程序中的ret指令则隐含从堆栈中弹出返回地址并跳转之的操作。C/C++中的自动变量是直接利用栈的例子，这也就是为什么当函数返回时，该函数的自动变量自动失效的原因。 </p>
<p>和栈不同，堆的数据结构并不是由系统(无论是机器系统还是操作系统)支持的，而是由函数库提供的。基本的malloc/realloc/free 函数维护了一套内部的堆数据结构。当程序使用这些函数去获得新的内存空间时，这套函数首先试图从内部堆中寻找可用的内存空间，如果没有可以使用的内存空间，则试图利用系统调用来动态增加程序数据段的内存大小，新分配得到的空间首先被组织进内部堆中去，然后再以适当的形式返回给调用者。当程序释放分配的内存空间时，这片内存空间被返回内部堆结构中，可能会被适当的处理(比如和其他空闲空间合并成更大的空闲空间)，以更适合下一次内存分配申请。这套复杂的分配机制实际上相当于一个内存分配的缓冲池(Cache)，使用这套机制有如下若干原因：<br>1. 系统调用可能不支持任意大小的内存分配。有些系统的系统调用只支持固定大小及其倍数的内存请求(按页分配)；这样的话对于大量的小内存分类来说会造成浪费。<br>2. 系统调用申请内存可能是代价昂贵的。系统调用可能涉及用户态和核心态的转换。<br>3. 没有管理的内存分配在大量复杂内存的分配释放操作下很容易造成内存碎片。</p>
<p>堆和栈的对比<br>从以上知识可知，栈是系统提供的功能，特点是快速高效，缺点是有限制，数据不灵活；而堆是函数库提供的功能，特点是灵活方便，数据适应面广泛，但是效率有一定降低。栈是系统数据结构，对于进程/线程是唯一的；堆是函数库内部数据结构，不一定唯一。不同堆分配的内存无法互相操作。栈空间分静态分配和动态分配两种。静态分配是编译器完成的，比如自动变量(auto)的分配。动态分配由alloca函数完成。栈的动态分配无需释放(是自动的)，也就没有释放函数。为可移植的程序起见，栈的动态分配操作是不被鼓励的！堆空间的分配总是动态的，虽然程序结束时所有的数据空间都会被释放回系统，但是精确的申请内存/ 释放内存匹配是良好程序的基本要素。</p>
<p>&nbsp;&nbsp;&nbsp; 1.碎片问题：对于堆来讲，频繁的new/delete势必会造成内存空间的不连续，从而造成大量的碎片，使程序效率降低。对于栈来讲，则不会存在这个问题，因为栈是先进后出的队列，他们是如此的一一对应，以至于永远都不可能有一个内存块从栈中间弹出，在他弹出之前，在他上面的后进的栈内容已经被弹出，详细的可以&gt;参考数据结构，这里我们就不再一一讨论了。<br>&nbsp;&nbsp;&nbsp; 2.生长方向：对于堆来讲，生长方向是向上的，也就是向着内存地址增加的方向；对于栈来讲，它的生长方向是向下的，是向着内存地址减小的方向增长。<br>&nbsp;&nbsp;&nbsp; 3.分配方式：堆都是动态分配的，没有静态分配的堆。栈有2种分配方式：静态分配和动态分配。静态分配是编译器完成的，比如局部变量的分配。动态分配由alloca函数进行分配，但是栈的动态分配和堆是不同的，他的动态分配是由编译器进行释放，无需我们手工实现。<br>&nbsp;&nbsp;&nbsp; 4.分配效率：栈是机器系统提供的数据结构，计算机会在底层对栈提供支持：分配专门的寄存器存放栈的地址，压栈出栈都有专门的指令执行，这就决定了栈的效率比较高。堆则是C/C++函数库提供的，它的机制是很复杂的，例如为了分配一块内存，库函数会按照一定的算法（具体的算法可以参考数据结构/操作系统）在堆内存中搜索可用的足够大小的空间，如果没有足够大小的空间（可能是由于内存碎片太多），就有可能调用系统功能去增加程序数据段的内存空间，这样就有机会分到足够大小的内存，然后进行返回。显然，堆的效率比栈要低得多。</p>
<p>&nbsp;&nbsp;&nbsp; 明确区分堆与栈:<br>&nbsp;&nbsp;&nbsp; 在bbs上，堆与栈的区分问题，似乎是一个永恒的话题，由此可见，初学者对此往往是混淆不清的，所以我决定拿他第一个开刀。<br>&nbsp;&nbsp;&nbsp; 首先，我们举一个例子：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;f()<br>{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;p</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">[</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">];<br>}</span></div>
<p><br>这条短短的一句话就包含了堆与栈，看到new，我们首先就应该想到，我们分配了一块堆内存，那么指针p呢？他分配的是一块栈内存，所以这句话的意思就是：在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小，然后调用operator new分配内存，然后返回这块内存的首地址，放入栈中，他在VC6下的汇编代码如下：<br>&nbsp;&nbsp;&nbsp; 00401028&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 14h<br>&nbsp;&nbsp;&nbsp; 0040102A&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; operator new (00401060)<br>&nbsp;&nbsp;&nbsp; 0040102F&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; esp,4<br>&nbsp;&nbsp;&nbsp; 00401032&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-8],eax<br>&nbsp;&nbsp;&nbsp; 00401035&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eax,dword ptr [ebp-8]<br>&nbsp;&nbsp;&nbsp; 00401038&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ebp-4],eax<br>&nbsp;&nbsp;&nbsp; 这里，我们为了简单并没有释放内存，那么该怎么去释放呢？是delete p么？澳，错了，应该是delete []p，这是为了告诉编译器：我删除的是一个数组，VC6就会根据相应的Cookie信息去进行释放内存的工作。<br>&nbsp;&nbsp;&nbsp; 好了，我们回到我们的主题：堆和栈究竟有什么区别？<br>&nbsp;&nbsp;&nbsp; 主要的区别由以下几点：<br>&nbsp;&nbsp;&nbsp; 1、管理方式不同；<br>&nbsp;&nbsp;&nbsp; 2、空间大小不同；<br>&nbsp;&nbsp;&nbsp; 3、能否产生碎片不同；<br>&nbsp;&nbsp;&nbsp; 4、生长方向不同；<br>&nbsp;&nbsp;&nbsp; 5、分配方式不同；<br>&nbsp;&nbsp;&nbsp; 6、分配效率不同；<br>&nbsp;&nbsp;&nbsp; 管理方式：对于栈来讲，是由编译器自动管理，无需我们手工控制；对于堆来说，释放工作由程序员控制，容易产生memory leak。<br>&nbsp;&nbsp;&nbsp; 空间大小：一般来讲在32位系统下，堆内存可以达到4G的空间，从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲，一般都是有一定的空间大小的，例如，在VC6下面，默认的栈空间大小是1M（好像是，记不清楚了）。当然，我们可以修改：<br>&nbsp;&nbsp;&nbsp; 打开工程，依次操作菜单如下：Project-&gt;Setting-&gt;Link，在Category 中选中Output，然后在Reserve中设定堆栈的最大值和commit。<br>注意：reserve最小值为4Byte；commit是保留在虚拟内存的页文件里面，它设置的较大会使栈开辟较大的值，可能增加内存的开销和启动时间。<br>&nbsp;&nbsp;&nbsp; 堆和栈相比，由于大量new/delete的使用，容易造成大量的内存碎片；由于没有专门的系统支持，效率很低；由于可能引发用户态和核心态的切换，内存的申请，代价变得更加昂贵。所以栈在程序中是应用最广泛的，就算是函数的调用也利用栈去完成，函数调用过程中的参数，返回地址，EBP和局部变量都采用栈的方式存放。所以，我们推荐大家尽量用栈，而不是用堆。</p>
<p>另外对存取效率的比较:<br>代码:<br>char s1[] = "aaaaaaaaaaaaaaa";<br>char *s2 = "bbbbbbbbbbbbbbbbb";aaaaaaaaaaa是在运行时刻赋值的；<br>而bbbbbbbbbbb是在编译时就确定的；<br>但是，在以后的存取中，在栈上的数组比指针所指向的字符串(例如堆)快。<br>比如：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;c[]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1234567890</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1234567890</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;&nbsp;&nbsp;a&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;c[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">];<br>&nbsp;&nbsp;&nbsp;&nbsp;a&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;p[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">];<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;<br>}</span></div>
<p><br>对应的汇编代码<br>10: a = c[1];<br>00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]<br>0040106A 88 4D FC mov byte ptr [ebp-4],cl<br>11: a = p[1];<br>0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]<br>00401070 8A 42 01 mov al,byte ptr [edx+1]<br>00401073 88 45 FC mov byte ptr [ebp-4],al<br>第一种在读取时直接就把字符串中的元素读到寄存器cl中，而第二种则要先把指针值读到edx中，在根据edx读取字符，显然慢了.<br>&nbsp;&nbsp;&nbsp; 无论是堆还是栈，都要防止越界现象的发生（除非你是故意使其越界），因为越界的结果要么是程序崩溃，要么是摧毁程序的堆、栈结构，产生以想不到的结果,就算是在你的程序运行过程中，没有发生上面的问题，你还是要小心，说不定什么时候就崩掉,编写稳定安全的代码才是最重要的。</p>
<p>static用来控制变量的存储方式和可见性<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 函数内部定义的变量，在程序执行到它的定义处时，编译器为它在栈上分配空间，函数在栈上分配的空间在此函数执行结束时会释放掉，这样就产生了一个问题: 如果想将函数中此变量的值保存至下一次调用时，如何实现？ 最容易想到的方法是定义一个全局的变量，但定义为一个全局变量有许多缺点，最明显的缺点是破坏了此变量的访问范围（使得在此函数中定义的变量，不仅仅受此 函数控制）。 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 需要一个数据对象为整个类而非某个对象服务,同时又力求不破坏类的封装性,即要求此成员隐藏在类的内部，对外不可见。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static的内部机制：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 静态数据成员要在程序一开始运行时就必须存在。因为函数在程序运行中被调用，所以静态数据成员不能在任何函数内分配空间和初始化。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样，它的空间分配有三个可能的地方，一是作为类的外部接口的头文件，那里有类声明；二是类定义的内部实现，那里有类的成员函数定义；三是应用程序的main（）函数前的全局数据声明和定义处。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 静态数据成员要实际地分配空间，故不能在类的声明中定义（只能声明数据成员）。类声明只声明一个类的&#8220;尺寸和规格&#8221;，并不进行实际的内存分配，所以在类声 明中写成定义是错误的。它也不能在头文件中类声明的外部定义，因为那会造成在多个使用该类的源文件中，对其重复定义。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static被引入以告知编译器，将变量存储在程序的静态存储区而非栈上空间，静态数据成员按定义出现的先后顺序依次初始化，注意静态成员嵌套时，要保证所嵌套的成员已经初始化了。消除时的顺序是初始化的反顺序。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static的优势：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可以节省内存，因为它是所有对象所公有的，因此，对多个对象来说，静态数据成员只存储一处，供所有对象共用。静态数据成员的值对每个对象都是一样，但它的 值是可以更新的。只要对静态数据成员的值更新一次，保证所有对象存取更新后的相同的值，这样可以提高时间效率。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 引用静态数据成员时，采用如下格式：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;类名&gt;::&lt;静态成员名&gt;<br>&nbsp;&nbsp;&nbsp; 如果静态数据成员的访问权限允许的话(即public的成员)，可在程序中，按上述格式<br>来引用静态数据成员。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PS:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (1)类的静态成员函数是属于整个类而非类的对象，所以它没有this指针，这就导致<br>了它仅能访问类的静态数据和静态成员函数。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (2)不能将静态成员函数定义为虚函数。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (3)由于静态成员声明于类中，操作于其外，所以对其取地址操作，就多少有些特殊<br>，变量地址是指向其数据类型的指针 ，函数地址类型是一个&#8220;nonmember函数指针&#8221;。 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (4)由于静态成员函数没有this指针，所以就差不多等同于nonmember函数，结果就<br>产生了一个意想不到的好处：成为一个callback函数，使得我们得以将C++和C-based X W<br>indow系统结合，同时也成功的应用于线程函数身上。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (5)static并没有增加程序的时空开销，相反她还缩短了子类对父类静态成员的访问<br>时间，节省了子类的内存空间。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (6)静态数据成员在&lt;定义或说明&gt;时前面加关键字static。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (7)静态数据成员是静态存储的，所以必须对它进行初始化。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (8)静态成员初始化与一般数据成员初始化不同:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 初始化在类体外进行，而前面不加static，以免与一般静态变量或对象相混淆；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 初始化时不加该成员的访问权限控制符private，public等；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 初始化时使用作用域运算符来标明它所属类；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所以我们得出静态数据成员初始化的格式：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;数据类型&gt;&lt;类名&gt;::&lt;静态数据成员名&gt;=&lt;值&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (9)为了防止父类的影响，可以在子类定义一个与父类相同的静态变量，以屏蔽父类的影响。这里有一点需要注意：我们说静态成员为父类和子类共享，但我们有 重复定义了静态成员，这会不会引起错误呢？不会，我们的编译器采用了一种绝妙的手法：name-mangling 用以生成唯一的标志。</p>
<p>补充：new&nbsp; delete［］,基本类型的对象没有析构函数（例如 int , char ），所以回收基本类型组成的数组空间 delete&nbsp; delete[] 都是应该可以如： int p = new int[10], delete p 和delete[]p 都可 。但是对于类对象数组（如string strArr = new string[10]），只能 delete[]。对 new 的单个对象，只能 delete 不能 delete[] 回收空间 。</p>
<p><br>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/AtlasHR/archive/2009/05/08/4160245.aspx">http://blog.csdn.net/AtlasHR/archive/2009/05/08/4160245.aspx</a></p>
<img src ="http://www.cppblog.com/hello8706/aggbug/132271.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hello8706/" target="_blank">小火球</a> 2010-11-03 11:04 <a href="http://www.cppblog.com/hello8706/archive/2010/11/03/132271.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>四种强制转换类型运算符</title><link>http://www.cppblog.com/hello8706/archive/2010/11/02/132103.html</link><dc:creator>小火球</dc:creator><author>小火球</author><pubDate>Tue, 02 Nov 2010 03:01:00 GMT</pubDate><guid>http://www.cppblog.com/hello8706/archive/2010/11/02/132103.html</guid><wfw:comment>http://www.cppblog.com/hello8706/comments/132103.html</wfw:comment><comments>http://www.cppblog.com/hello8706/archive/2010/11/02/132103.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/hello8706/comments/commentRss/132103.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/hello8706/services/trackbacks/132103.html</trackback:ping><description><![CDATA[<ol>
    <li class=alt><span><span>标准c++中主要有四种强制转换类型运算符： &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span></span><span class=keyword><strong><font color=#5697d9>const_cast</font></strong></span><span>，</span><span class=keyword><strong><font color=#5697d9>reinterpret_cast</font></strong></span><span>，</span><span class=keyword><strong><font color=#5697d9>static_cast</font></strong></span><span>，</span><span class=keyword><strong><font color=#5697d9>dynamic_cast</font></strong></span><span>等等。 &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;</span></li>
    <li class=""><span>1）</span><span class=keyword><strong><font color=#5697d9>static_cast</font></strong></span><span>&lt;T*&gt;(a) &nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>将地址a转换成类型T，T和a必须是指针、引用、算术类型或枚举类型。 &nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>表达式</span><span class=keyword><strong><font color=#5697d9>static_cast</font></strong></span><span>&lt;T*&gt;(a),&nbsp;a的值转换为模板中指定的类型T。在运行时转换过程中，不进行类型检查来确保转换的安全性。 &nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>例子： &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;</span></li>
    <li class=alt><span></span><span class=keyword><strong><font color=#5697d9>class</font></strong></span><span>&nbsp;B&nbsp;{&nbsp;...&nbsp;}; &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span></span><span class=keyword><strong><font color=#5697d9>class</font></strong></span><span>&nbsp;D&nbsp;:&nbsp;</span><span class=keyword><strong><font color=#5697d9>public</font></strong></span><span>&nbsp;B&nbsp;{&nbsp;...&nbsp;}; &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span></span><span class=keyword><strong><font color=#5697d9>void</font></strong></span><span>&nbsp;f(B*&nbsp;pb,&nbsp;D*&nbsp;pd) &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>{ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;&nbsp;D*&nbsp;pd2&nbsp;=&nbsp;</span><span class=keyword><strong><font color=#5697d9>static_cast</font></strong></span><span>&lt;D*&gt;(pb);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class=comment><font color=#ee0000>//&nbsp;不安全,&nbsp;pb可能只是B的指针 </font></span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;B*&nbsp;pb2&nbsp;=&nbsp;</span><span class=keyword><strong><font color=#5697d9>static_cast</font></strong></span><span>&lt;B*&gt;(pd);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class=comment><font color=#ee0000>//&nbsp;安全的 </font></span><span>&nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;... &nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>2）</span><span class=keyword><strong><font color=#5697d9>dynamic_cast</font></strong></span><span>&lt;T*&gt;(a) &nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>完成类层次结构中的提升。T必须是一个指针、引用或无类型的指针。a必须是决定一个指针或引用的表达式。 &nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>表达式</span><span class=keyword><strong><font color=#5697d9>dynamic_cast</font></strong></span><span>&lt;T*&gt;(a)&nbsp;将a值转换为类型为T的对象指针。如果类型T不是a的某个基类型，该操作将返回一个空指针。 &nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>例子： &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span></span><span class=keyword><strong><font color=#5697d9>class</font></strong></span><span>&nbsp;A&nbsp;{&nbsp;...&nbsp;}; &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span></span><span class=keyword><strong><font color=#5697d9>class</font></strong></span><span>&nbsp;B&nbsp;{&nbsp;...&nbsp;}; &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span></span><span class=keyword><strong><font color=#5697d9>void</font></strong></span><span>&nbsp;f() &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>{ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;A*&nbsp;pa&nbsp;=&nbsp;</span><span class=keyword><strong><font color=#5697d9>new</font></strong></span><span>&nbsp;A; &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;B*&nbsp;pb&nbsp;=&nbsp;</span><span class=keyword><strong><font color=#5697d9>new</font></strong></span><span>&nbsp;B; &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span><span class=keyword><strong><font color=#5697d9>void</font></strong></span><span>*&nbsp;pv&nbsp;=&nbsp;</span><span class=keyword><strong><font color=#5697d9>dynamic_cast</font></strong></span><span>&lt;A*&gt;(pa); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span><span class=comment><font color=#ee0000>//&nbsp;pv&nbsp;现在指向了一个类型为A的对象 </font></span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;... &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;pv&nbsp;=&nbsp;</span><span class=keyword><strong><font color=#5697d9>dynamic_cast</font></strong></span><span>&lt;B*&gt;(pb); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span><span class=comment><font color=#ee0000>//&nbsp;pv&nbsp;现在指向了一个类型为B的对象 </font></span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>3）</span><span class=keyword><strong><font color=#5697d9>const_cast</font></strong></span><span>&lt;T*&gt;(a) &nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>去掉类型中的常量，除了</span><span class=keyword><strong><font color=#5697d9>const</font></strong></span><span>或不稳定的变址数，T和a必须是相同的类型。 &nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>表达式</span><span class=keyword><strong><font color=#5697d9>const_cast</font></strong></span><span>&lt;T*&gt;(a)被用于从一个类中去除以下这些属性：</span><span class=keyword><strong><font color=#5697d9>const</font></strong></span><span>,&nbsp;</span><span class=keyword><strong><font color=#5697d9>volatile</font></strong></span><span>,&nbsp;和&nbsp;__unaligned。 &nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>例子： &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span></span><span class=keyword><strong><font color=#5697d9>class</font></strong></span><span>&nbsp;A&nbsp;{&nbsp;...&nbsp;}; &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span></span><span class=keyword><strong><font color=#5697d9>void</font></strong></span><span>&nbsp;f() &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>{ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;</span><span class=keyword><strong><font color=#5697d9>const</font></strong></span><span>&nbsp;A&nbsp;*pa&nbsp;=&nbsp;</span><span class=keyword><strong><font color=#5697d9>new</font></strong></span><span>&nbsp;A;</span><span class=comment><font color=#ee0000>//const对象 </font></span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;A&nbsp;*pb;</span><span class=comment><font color=#ee0000>//非const对象 </font></span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class=comment><font color=#ee0000>//pb&nbsp;=&nbsp;pa;&nbsp;//&nbsp;这里将出错，不能将const对象指针赋值给非const对象 </font></span><span>&nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;pb&nbsp;=&nbsp;</span><span class=keyword><strong><font color=#5697d9>const_cast</font></strong></span><span>&lt;A*&gt;(pa);&nbsp;</span><span class=comment><font color=#ee0000>//&nbsp;现在OK了 </font></span><span>&nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>... &nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>}&nbsp;&nbsp;&nbsp;</span></li>
    <li class=""><span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>4）</span><span class=keyword><strong><font color=#5697d9>reinterpret_cast</font></strong></span><span>&lt;T*&gt;(a) &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>任何指针都可以转换成其它类型的指针，T必须是一个指针、引用、算术类型、指向函数的指针或指向一个类成员的指针。 &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>表达式</span><span class=keyword><strong><font color=#5697d9>reinterpret_cast</font></strong></span><span>&lt;T*&gt;(a)能够用于诸如</span><span class=datatypes><strong><font color=#2e8b57>char</font></strong></span><span>*&nbsp;到&nbsp;</span><span class=datatypes><strong><font color=#2e8b57>int</font></strong></span><span>*，或者One_class*&nbsp;到&nbsp;Unrelated_class*等类似这样的转换，因此可能是不安全的。 &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>例子： &nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class=keyword><strong><font color=#5697d9>class</font></strong></span><span>&nbsp;A&nbsp;{&nbsp;...&nbsp;}; &nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class=keyword><strong><font color=#5697d9>class</font></strong></span><span>&nbsp;B&nbsp;{&nbsp;...&nbsp;}; &nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class=keyword><strong><font color=#5697d9>void</font></strong></span><span>&nbsp;f() &nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>{ &nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;A*&nbsp;pa&nbsp;=&nbsp;</span><span class=keyword><strong><font color=#5697d9>new</font></strong></span><span>&nbsp;A; &nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span><span class=keyword><strong><font color=#5697d9>void</font></strong></span><span>*&nbsp;pv&nbsp;=&nbsp;</span><span class=keyword><strong><font color=#5697d9>reinterpret_cast</font></strong></span><span>&lt;A*&gt;(pa); &nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span><span class=comment><font color=#ee0000>//&nbsp;pv&nbsp;现在指向了一个类型为A的对象，这可能是不安全的 </font></span><span>&nbsp;&nbsp;</span></span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;... &nbsp;&nbsp;</span></li>
    <li class=alt><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;</span></li>
</ol>
<img src ="http://www.cppblog.com/hello8706/aggbug/132103.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hello8706/" target="_blank">小火球</a> 2010-11-02 11:01 <a href="http://www.cppblog.com/hello8706/archive/2010/11/02/132103.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>剖析C++标准库智能指针(std::auto_ptr)   以及智能指针的原理</title><link>http://www.cppblog.com/hello8706/archive/2010/10/29/131752.html</link><dc:creator>小火球</dc:creator><author>小火球</author><pubDate>Fri, 29 Oct 2010 07:21:00 GMT</pubDate><guid>http://www.cppblog.com/hello8706/archive/2010/10/29/131752.html</guid><wfw:comment>http://www.cppblog.com/hello8706/comments/131752.html</wfw:comment><comments>http://www.cppblog.com/hello8706/archive/2010/10/29/131752.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/hello8706/comments/commentRss/131752.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/hello8706/services/trackbacks/131752.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1.Do you Smart Pointer?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Smart Pointer,中文名：智能指针&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不可否认,资源泄露(resource leak)曾经是C++程序的一大噩梦.垃圾回收&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 机制(Garbage Collectio...&nbsp;&nbsp;<a href='http://www.cppblog.com/hello8706/archive/2010/10/29/131752.html'>阅读全文</a><img src ="http://www.cppblog.com/hello8706/aggbug/131752.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hello8706/" target="_blank">小火球</a> 2010-10-29 15:21 <a href="http://www.cppblog.com/hello8706/archive/2010/10/29/131752.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++读取INI文件</title><link>http://www.cppblog.com/hello8706/archive/2010/07/23/121102.html</link><dc:creator>小火球</dc:creator><author>小火球</author><pubDate>Fri, 23 Jul 2010 02:48:00 GMT</pubDate><guid>http://www.cppblog.com/hello8706/archive/2010/07/23/121102.html</guid><description><![CDATA[Windows操作系统专门为此提供了6个API函数来对配置设置文件进行读、写：<br><br>GetPrivateProfileInt() 从私有初始化文件获取整型数值<br>GetPrivateProfileString() 从私有初始化文件获取字符串型值<br>GetProfileInt 从win.ini 获取整数值<br>GetProfileString 从win.ini 获取字符串值<br>WritePrivateProfileStrin<wbr>g 写字符串到私有初始化文件<br>WriteProfileString 写字符串到win.ini<br><br>我们可以把视图类的:OnInitialUpdate() 函数作为程序启动时读取配置文件的入口，配置文件的存储格式如下：<br><br>[SECTION 1]<br>XPos=300<br>YPos=200<br><br>[SECTION 2]<br>Text=Hello<br><br>仅有两个节，XPos和YPos标明了待显示信息的坐标，而待显示的信息存储在第二节的Text项中，用读取访问私有配置设置文件的API函数将其分别读入到变量m_nXPos,m_nYPos和m_strText中，并通过Invalidate()调用OnDraw()函数，在其内用TextOut函数将该信息在读取的坐标位置显示出来：<br><br>m_nXPos=GetPrivateProfileInt("SECTION 1", //节名<br>"XPos", //项名<br>0, //没找到此项时的缺省返回值<br>"C:\test\debug\test.ini"); //配置文件的准确路径<br><br>m_nYPos=GetPrivateProfileInt("SECTION 1","YPos",0,exeFullPath);<br>char buf[256];<br>len=GetPrivateProfileString("SECTION 2", //节名<br>"Text", //项名<br>"No Text", //没找到此项时的返回值<br>buf, //目标缓冲区地址<br>256, //目标缓冲区长度<br>"C:\test\debug\test.ini"); //配置文件的准确路径<br><br>for(int i=0;i&lt;len;i++)<br>{<br>&nbsp;&nbsp;&nbsp;CString str;<br>&nbsp;&nbsp;&nbsp;str.Format("%c",buf[i]);<br>&nbsp;&nbsp;&nbsp;m_strText+=str;<br>}<br>Invalidate();<br><br>一般配置文件是和应用程序存放在同一个目录中的如果用"C:\test\debug\test.ini"的绝对路径进行设置就会出现路径改变后找不到配置文件的问题，所以应动态搜寻配置文件的存放地址：<br><br>Tchar exeFullPath[MAX_PATH]; // MAX_PATH在API中有定义，为128<br>int len=GetModuleFileName(NULL,<br>exeFullPath, //应用程序的全路径存放地址<br>MAX_PATH);<br>CString path="\test.ini"; //配置文件名<br>::strcpy(exeFullPath+len-13,path); //组合出配置文件的全路径<br><br>值得注意的是这里的13是项目名的大小，但是不同项目可能名字不一样，定义这样的长度过于机械化<br><br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #008080">1</span><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;NULL;<br></span><span style="COLOR: #008080">2</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;exeFullPath[</span><span style="COLOR: #000000">128</span><span style="COLOR: #000000">];<br></span><span style="COLOR: #008080">3</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;len</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">GetModuleFileName(NULL,<br></span><span style="COLOR: #008080">4</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exeFullPath,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">128</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">5</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;p</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">strrchr(exeFullPath,&nbsp;</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">\\</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">);&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">6</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">\0</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">;</span></div>
这样，通过strrchr函数屏蔽掉最后出现的'\'就能够把项目名也屏蔽掉了，根据不同的情况当然也有不同的做法。<br><br><br>写配置文件也基本类似，只是需要把数值类型的变量格式化成字符串再行存储：<br><br>str.Format("%d",m_nXPos);<br>WritePrivateProfileStrin<wbr>g("SECTION 1","XPos",str,exeFullPath);<br>str.Format("%d",m_nYPos);<br>WritePrivateProfileStrin<wbr>g("SECTION 1","YPos",str,exeFullPath);<br>WritePrivateProfileStrin<wbr>g("SECTION 2","Text",m_strText,exeFullPath);<br><br>我们一定遇到过这样的程序：在执行过一遍以后，重启系统会自动加载该程序，其实除了在启动菜单和注册表添加信息外，也可以用 WriteProfileString()函数向win.ini的"windows"节的"run"项目添加应用程序的全路径来实现，这要比其它两种方法简便的多，而且也比较安全。<br><br><br><br>二.将信息从INI文件中读入程序中的变量.<br><br>1.所用的WINAPI函数原型为:<br><br>DWORD GetPrivateProfileString(<br>LPCTSTR lpAppName,<br>LPCTSTR lpKeyName,<br>LPCTSTR lpDefault,<br>LPTSTR lpReturnedString,<br>DWORD nSize,<br>LPCTSTR lpFileName<br>);<br><br>其中各参数的意义:<br><br>前二个参数与 WritePrivateProfileStrin<wbr>g中的意义一样.<br><br>lpDefault : 如果INI文件中没有前两个参数指定的字段名或键名,则将此值赋给变量.<br><br>lpReturnedString : 接收INI文件中的值的CString对象,即目的缓存器.<br><br>nSize : 目的缓存器的大小.<br><br>lpFileName : 是完整的INI文件名.<br><br>2.具体使用方法:现要将上一步中写入的学生的信息读入程序中.<br><br>CString strStudName;<br>int nStudAge;<br>GetPrivateProfileString("StudentInfo","Name","默认姓名",strStudName.GetBuffer(MAX_PATH),MAX_PATH,"c:\stud\student.ini");<br><br>执行后 strStudName 的值为:"张三",若前两个参数有误,其值为:"默认姓名".<br><br>3.读入整型值要用另一个WINAPI函数:<br><br>UINT GetPrivateProfileInt(<br>LPCTSTR lpAppName,<br>LPCTSTR lpKeyName,<br>INT nDefault,<br>LPCTSTR lpFileName<br>);<br><br>这里的参数意义与上相同.使用方法如下:<br>nStudAge=GetPrivateProfileInt("StudentInfo","Age",10,"c:\stud\student.ini");<br><br><br><br><br>贴上自己WIN32测试并通过的一段例子（部分代码，主要功能是如何配置相对路径，后续操作，前面已经有了）<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #008080">&nbsp;1</span><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;NULL;<br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;exeFullPath[</span><span style="COLOR: #000000">128</span><span style="COLOR: #000000">];<br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;len</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">GetModuleFileName(NULL,<br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exeFullPath,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">应用程序的全路径存放地址</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #008000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">128</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;p</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">strrchr(exeFullPath,&nbsp;</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">\\</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">屏蔽掉项目名称</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #008000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">\0</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;p</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">strrchr(exeFullPath,&nbsp;</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">\\</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">屏蔽掉DEBUG（实际开发中这个可能不需要）</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #008000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">\0</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;len&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;strlen(exeFullPath);<br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;path</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">\\system.ini</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">配置文件名</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">12</span><span style="COLOR: #008000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;::strcpy(exeFullPath</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">len,path.c_str());&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">组合出配置文件的全路径</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">13</span><span style="COLOR: #008000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;ipstr[</span><span style="COLOR: #000000">20</span><span style="COLOR: #000000">];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">存储IP地址</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">16</span><span style="COLOR: #008000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;GetPrivateProfileString(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Server</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">ServerIP</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,NULL,ipstr,</span><span style="COLOR: #000000">20</span><span style="COLOR: #000000">,exeFullPath);<br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;port;<br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;port&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;GetPrivateProfileInt(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Server</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Port</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,exeFullPath);</span></div>
<br><br>下面这段是公司里工作时候写的，做个记录<br>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #008080">&nbsp;1</span><img id=Codehighlighter1_1_52_Open_Image onclick="this.style.display='none'; Codehighlighter1_1_52_Open_Text.style.display='none'; Codehighlighter1_1_52_Closed_Image.style.display='inline'; Codehighlighter1_1_52_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_1_52_Closed_Image onclick="this.style.display='none'; Codehighlighter1_1_52_Closed_Text.style.display='none'; Codehighlighter1_1_52_Open_Image.style.display='inline'; Codehighlighter1_1_52_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_1_52_Closed_Text>/**/</span><span id=Codehighlighter1_1_52_Open_Text><span style="COLOR: #808080">//////////////////////////////////////////</span><span style="COLOR: #008000">将内容以','分离</span><span style="COLOR: #808080"></span></span><br><span style="COLOR: #008080">&nbsp;2</span><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&nbsp;strFream&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;szFream;<br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;strVec;<br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;cTrim&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">::size_type&nbsp;pos1,&nbsp;pos2;<br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;pos2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(pos2&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">::npos)<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img id=Codehighlighter1_207_538_Open_Image onclick="this.style.display='none'; Codehighlighter1_207_538_Open_Text.style.display='none'; Codehighlighter1_207_538_Closed_Image.style.display='inline'; Codehighlighter1_207_538_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_207_538_Closed_Image onclick="this.style.display='none'; Codehighlighter1_207_538_Closed_Text.style.display='none'; Codehighlighter1_207_538_Open_Image.style.display='inline'; Codehighlighter1_207_538_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_207_538_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_207_538_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pos1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;strFream.find_first_not_of(cTrim,&nbsp;pos2);<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(pos1&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">::npos)<br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pos2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;strFream.find_first_of(cTrim,&nbsp;pos1&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(pos2&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;std::</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">::npos)<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img id=Codehighlighter1_387_479_Open_Image onclick="this.style.display='none'; Codehighlighter1_387_479_Open_Text.style.display='none'; Codehighlighter1_387_479_Closed_Image.style.display='inline'; Codehighlighter1_387_479_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_387_479_Closed_Image onclick="this.style.display='none'; Codehighlighter1_387_479_Closed_Text.style.display='none'; Codehighlighter1_387_479_Open_Image.style.display='inline'; Codehighlighter1_387_479_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_387_479_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_387_479_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(pos1&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;strFream.size())<br></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strVec.push_back(strFream.substr(pos1));&nbsp;<br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strVec.push_back(strFream.substr(pos1,&nbsp;pos2&nbsp;</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">&nbsp;pos1));<br></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;strVec.size();</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">i)<br></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img id=Codehighlighter1_580_697_Open_Image onclick="this.style.display='none'; Codehighlighter1_580_697_Open_Text.style.display='none'; Codehighlighter1_580_697_Closed_Image.style.display='inline'; Codehighlighter1_580_697_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_580_697_Closed_Image onclick="this.style.display='none'; Codehighlighter1_580_697_Closed_Text.style.display='none'; Codehighlighter1_580_697_Open_Image.style.display='inline'; Codehighlighter1_580_697_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_580_697_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_580_697_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">23</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;nTemp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;atoi(strVec[i].c_str());<br></span><span style="COLOR: #008080">24</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(nTemp&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;m_nFrameNum)<br></span><span style="COLOR: #008080">25</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_vecFrame.push_back(nTemp);<br></span><span style="COLOR: #008080">26</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">continue</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">27</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
<br>
<img src ="http://www.cppblog.com/hello8706/aggbug/121102.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hello8706/" target="_blank">小火球</a> 2010-07-23 10:48 <a href="http://www.cppblog.com/hello8706/archive/2010/07/23/121102.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>va_list、va_start、va_arg、va_end</title><link>http://www.cppblog.com/hello8706/archive/2010/07/08/119725.html</link><dc:creator>小火球</dc:creator><author>小火球</author><pubDate>Thu, 08 Jul 2010 05:48:00 GMT</pubDate><guid>http://www.cppblog.com/hello8706/archive/2010/07/08/119725.html</guid><description><![CDATA[简介
<p><font size=+0>va_list</font>、<font size=+0>va_arg</font>、<font size=+0>va_end</font>是为了处理变参数的函数而做的宏定义，这些定义会因为平台（<font size=+0>cpu</font>、操作系统）和环境（编译系统）的不同而有所不同。</p>
<p>简单原理：编译系统编译时，会将函数的参数依次放到栈中，这样根据固定参数的地址以及固定参数给出的相关信息很容易得到可变参数的个数、类型、值。注意一点，这些或者是固定参数给出的信息，虽然不是直接给出的；或者是程序写作者自我约定。得到了可变参数，剩下的处理和普通函数一样了。<br></p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #008080">&nbsp;1</span><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdlib.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">time.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">varargs.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdarg.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">errno.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;arg_cnt(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;cnt,&nbsp;<img src="http://www.cppblog.com/Images/dot.gif">)<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img id=Codehighlighter1_172_327_Open_Image onclick="this.style.display='none'; Codehighlighter1_172_327_Open_Text.style.display='none'; Codehighlighter1_172_327_Closed_Image.style.display='inline'; Codehighlighter1_172_327_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_172_327_Closed_Image onclick="this.style.display='none'; Codehighlighter1_172_327_Closed_Text.style.display='none'; Codehighlighter1_172_327_Open_Image.style.display='inline'; Codehighlighter1_172_327_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_172_327_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_172_327_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;nValue&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;va_list&nbsp;arg_ptr;<br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;va_start(arg_ptr,cnt);<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;cnt;</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">i)<br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img id=Codehighlighter1_264_325_Open_Image onclick="this.style.display='none'; Codehighlighter1_264_325_Open_Text.style.display='none'; Codehighlighter1_264_325_Closed_Image.style.display='inline'; Codehighlighter1_264_325_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_264_325_Closed_Image onclick="this.style.display='none'; Codehighlighter1_264_325_Closed_Text.style.display='none'; Codehighlighter1_264_325_Open_Image.style.display='inline'; Codehighlighter1_264_325_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_264_325_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_264_325_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nValue&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;va_arg(arg_ptr,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;nValue&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;argc,</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">argv[])<br></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img id=Codehighlighter1_361_484_Open_Image onclick="this.style.display='none'; Codehighlighter1_361_484_Open_Text.style.display='none'; Codehighlighter1_361_484_Closed_Image.style.display='inline'; Codehighlighter1_361_484_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_361_484_Closed_Image onclick="this.style.display='none'; Codehighlighter1_361_484_Closed_Text.style.display='none'; Codehighlighter1_361_484_Open_Image.style.display='inline'; Codehighlighter1_361_484_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_361_484_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_361_484_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;int_size&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;_INTSIZEOF(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">23</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">int_size&nbsp;=&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;int_size&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br></span><span style="COLOR: #008080">24</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;arg_cnt(</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">25</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;getchar();<br></span><span style="COLOR: #008080">26</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">27</span><span style="COLOR: #000000"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span></div>
<p><br>两个小知识（转）</p>
<p>（1）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; win32 vc++编译</p>
<p>内存分配由高址向低址进行；参数调用时，参数入栈顺序：从最后一个开始，直到第一个。</p>
<p>（2）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 内存对齐</p>
<p>分为结构成员内存对齐和栈内存对齐。</p>
<p>前者要求：字、双字和四字在自然边界上不需要在内存中对齐。（对字、双字和四字来说，自然边界分别是偶数地址、可以被4整除的地址、和可以被8整除的地址。）一个字或双字操作数跨越了4字节边界，或者一个四字操作数跨越了8字节边界，被认为未对齐的。</p>
<p>后者要求：总保持对齐，而且对齐在4字节边界上。</p>
<p>两者区别：前者是可以通过工具控制对齐边界的，如在vc++中就可以通过控制选项控制边界；而后者是不能控制的，必须对齐的，毕竟栈的效率太影响到程序性能了。<br></p>
<p>宏定义</p>
<p>以下是vc++6.0定义在stdarg.h文件中的关于x86平台的部分宏定义：</p>
<p>typedef char *&nbsp; va_list;</p>
<p>#define _INTSIZEOF(n)&nbsp;&nbsp; ( (sizeof(n) + sizeof(int) - 1) &amp; ~(sizeof(int) - 1) )</p>
<p>#define va_start(ap,v)&nbsp; ( ap = (va_list)&amp;v + _INTSIZEOF(v) )</p>
<p>#define va_arg(ap,t)&nbsp;&nbsp;&nbsp; ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )</p>
<p>#define va_end(ap)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( ap = (va_list)0 )</p>
<p>结合上例，调用AveInt(4,2,4,6,8)，当运行了va_start(myvalist,num);之后，根据定义myvalist =(va_list)&amp;num+_INTSIZEOF(i),这样myvalist指向第一个可变参数2；第一次运行va_arg(myvalist,int);后，先让myvalist+= _INTSIZEOF(int)指向下一个可变参数4，然后在取出前面的可变参数2进行处理；依此类推。</p>
<p><br>&nbsp;</p>
<p>由于是可变参数，对编译器来说，检查类型一般比较困难，所以，编译器对类型检查不严格，容易出现由于程序写作者的疏忽导致的错误。例如，可变参数中有个<font size=+0>int</font>型的，然而在函数中把这个<font size=+0>int</font>型参数当作<font size=+0>char *</font>进行处理，就可能导致内存越界等错误。不得不说的是，如果采用WINDOWS窗口，那么这段程序不能执行。望高手能帮我解决这个问题</p>
<a href="http://blog.csdn.net/mader/archive/2007/08/20/1751893.aspx"></a>
<img src ="http://www.cppblog.com/hello8706/aggbug/119725.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hello8706/" target="_blank">小火球</a> 2010-07-08 13:48 <a href="http://www.cppblog.com/hello8706/archive/2010/07/08/119725.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>main参数</title><link>http://www.cppblog.com/hello8706/archive/2010/06/28/118858.html</link><dc:creator>小火球</dc:creator><author>小火球</author><pubDate>Mon, 28 Jun 2010 04:03:00 GMT</pubDate><guid>http://www.cppblog.com/hello8706/archive/2010/06/28/118858.html</guid><wfw:comment>http://www.cppblog.com/hello8706/comments/118858.html</wfw:comment><comments>http://www.cppblog.com/hello8706/archive/2010/06/28/118858.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/hello8706/comments/commentRss/118858.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/hello8706/services/trackbacks/118858.html</trackback:ping><description><![CDATA[C语言中的main函数,一般会带有2个参数,例如int main ( int argc, char* argv[]),这是一个典型的main函数的声明。这是为了在执行程序时需要向程序传递参数,参数argc代表了输入参数的个数,char *argv[]表示传入的参数的字符串,是一个字符串数组。<br><br>例如在Unix平台下编写一个小程序:<br>
<pre>int main(int argc, char* argv[])<br>{<br>　int i;<br><br>　printf("test main parameter\n");<br>　printf("argc:%d\n", argc);<br>　for(i=0;i&lt;argc;i++)<br>　{<br>　　printf("argv[%d]:%s\n", i, argv[i]);<br>　}<br>　exit(0);<br>}<br>用cc编译后形成一个a.out*的可执行的文件,运行a.out,其结果是argc=1,argv[0]="a.out",运行的程序的文件名,也占用一个参数位置,也就是说argv数组中的第一个单元指向的字符串总是</pre>
<pre>可执行程序的名字,以后的单元指向的字符串依次是程序调用时的参数。这个赋值过程时操作系统完成的,我们只需要拿来用就可以了。</pre>
<pre>&nbsp;</pre>
<pre>
<p><font size=2>main()主函数 <br><br><br>&nbsp; &nbsp; 每一C 程序都必须有一main()函数, 可以根据自己的爱好把它放在程序的某 <br>个地方。有些程序员把它放在最前面, 而另一些程序员把它放在最后面, 无论放 <br>在哪个地方, 以下几点说明都是适合的。 <br>&nbsp; &nbsp; 1. main() 参数 <br>&nbsp; &nbsp; 在Turbo C2.0启动过程中, 传递main()函数三个参数: argc, argv和env。 <br>&nbsp; &nbsp; &nbsp;* argc: &nbsp;整数, 为传给main()的命令行参数个数。 <br>&nbsp; &nbsp; &nbsp;* argv: &nbsp;字符串数组。 <br>&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;在DOS 3.X 版本中, argv[0] 为程序运行的全路径名; 对DOS 3.0 <br>&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;以下的版本, argv[0]为空串("") 。 <br>&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;argv[1] 为在DOS命令行中执行程序名后的第一个字符串; <br>&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;argv[2] 为执行程序名后的第二个字符串; <br>&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;... <br>&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;argv[argc]为NULL。 <br>&nbsp; &nbsp; &nbsp;*env: &nbsp;安符串数组。env[] 的每一个元素都包含ENVVAR=value形式的字符 <br>串。其中ENVVAR为环境变量如PATH或87。value 为ENVVAR的对应值如C:\DOS, C: <br>\TURBOC(对于PATH) 或YES(对于87)。 <br><br><br>&nbsp; &nbsp; <br>&nbsp;&nbsp;&nbsp; Turbo C2.0启动时总是把这三个参数传递给main()函数, 可以在用户程序中 <br>说明(或不说明)它们, 如果说明了部分(或全部)参数, 它们就成为main()子程序 <br>的局部变量。 <br>&nbsp; &nbsp; 请注意: 一旦想说明这些参数, 则必须按argc, argv, env 的顺序, 如以下 <br>的例子: <br>&nbsp; &nbsp; &nbsp;main() <br>&nbsp; &nbsp; &nbsp;main(int argc) <br>&nbsp; &nbsp; &nbsp;main(int argc, char *argv[]) <br>&nbsp; &nbsp; &nbsp;main(int argc, char *argv[], char *env[]) <br>&nbsp; &nbsp; 其中第二种情况是合法的, 但不常见, 因为在程序中很少有只用argc, 而不 <br>用argv[]的情况。 <br>&nbsp; &nbsp; 以下提供一样例程序EXAMPLE.EXE, &nbsp;演示如何在main()函数中使用三个参数: <br>&nbsp; &nbsp; &nbsp;/*program name EXAMPLE.EXE*/ <br>&nbsp; &nbsp; &nbsp;#include &lt;stdio.h&gt; <br>&nbsp; &nbsp; &nbsp;#include &lt;stdlib.h&gt; <br>&nbsp; &nbsp; &nbsp;main(int argc, char *argv[], char *env[]) <br>&nbsp; &nbsp; &nbsp;{ <br>&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; int i; <br>&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; printf("These are the %d &nbsp;command- line &nbsp;arguments passed &nbsp;to <br>&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; main:\n\n", argc); <br>&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; for(i=0; i&lt;=argc; i++) <br>&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; printf("argv[%d]:%s\n", i, argv</font><font size=2>); <br>&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; printf("\nThe environment string(s)on this system are:\n\n"); <br>&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; for(i=0; env</font><font size=2>!=NULL; i++) <br>&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; printf(" env[%d]:%s\n", i, env</font><font size=2>); <br>&nbsp; &nbsp; &nbsp;} <br><br><br><br><br>&nbsp; &nbsp; <br><br>&nbsp;&nbsp;&nbsp; 如果在DOS 提示符下, 按以下方式运行EXAMPLE.EXE: <br>&nbsp; &nbsp; C:\example first_argument "argument with blanks" &nbsp;3 &nbsp;4 &nbsp;"last &nbsp;but <br>one" stop! <br>&nbsp; &nbsp; 注意: 可以用双引号括起内含空格的参数, 如本例中的: &nbsp; " &nbsp;argument <br>with blanks"和"Last but one")。 <br>&nbsp; &nbsp; 结果是这样的: <br>&nbsp; &nbsp; &nbsp;The value of argc is 7 <br>&nbsp; &nbsp; &nbsp;These are the 7 command-linearguments passed to main: <br>&nbsp; &nbsp; &nbsp;argv[0]:C:\TURBO\EXAMPLE.EXE <br>&nbsp; &nbsp; &nbsp;argv[1]:first_argument <br>&nbsp; &nbsp; &nbsp;argv[2]:argument with blanks <br>&nbsp; &nbsp; &nbsp;argv[3]:3 <br>&nbsp; &nbsp; &nbsp;argv[4]:4 <br>&nbsp; &nbsp; &nbsp;argv[5]:last but one <br>&nbsp; &nbsp; &nbsp;argv[6]:stop! <br>&nbsp; &nbsp; &nbsp;argv[7]:(NULL) <br>&nbsp; &nbsp; &nbsp;The environment string(s) on this system are: <br>&nbsp; &nbsp; &nbsp;env[0]: COMSPEC=C:\COMMAND.COM <br>&nbsp; &nbsp; &nbsp;env[1]: PROMPT=$P$G &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; /*视具体设置而定*/ <br>&nbsp; &nbsp; &nbsp;env[2]: PATH=C:\DOS;C:\TC &nbsp; &nbsp;&nbsp; /*视具体设置而定*/ <br>&nbsp; <br>&nbsp; &nbsp; &nbsp;应该提醒的是: 传送main() 函数的命令行参数的最大长度为128 个字符 (包 <br>括参数间的空格), &nbsp;这是由DOS 限制的。</font></p>
</pre>
<pre>&nbsp;</pre>
<pre>&nbsp;</pre>
<img src ="http://www.cppblog.com/hello8706/aggbug/118858.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hello8706/" target="_blank">小火球</a> 2010-06-28 12:03 <a href="http://www.cppblog.com/hello8706/archive/2010/06/28/118858.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转-双线性差值</title><link>http://www.cppblog.com/hello8706/archive/2010/05/06/114640.html</link><dc:creator>小火球</dc:creator><author>小火球</author><pubDate>Thu, 06 May 2010 07:57:00 GMT</pubDate><guid>http://www.cppblog.com/hello8706/archive/2010/05/06/114640.html</guid><description><![CDATA[<font size=4>简单比方<font style="LINE-HEIGHT: 1.3em" face=Times>,</font>原来的<font style="LINE-HEIGHT: 1.3em" color=#ff6600>数值序列</font>：<font style="LINE-HEIGHT: 1.3em" face=Times>0</font>，<font style="LINE-HEIGHT: 1.3em" face=Times>10</font>，<font style="LINE-HEIGHT: 1.3em" face=Times>20</font>，<font style="LINE-HEIGHT: 1.3em" face=Times>30</font>，<font style="LINE-HEIGHT: 1.3em" face=Times>40 </font><br></font><font size=3><font style="FONT-SIZE: medium; LINE-HEIGHT: 1.3em">线性插值一次为：<font style="LINE-HEIGHT: 1.3em" face=Times>0</font>，<font style="LINE-HEIGHT: 1.3em" face=Times>5</font>，<font style="LINE-HEIGHT: 1.3em" face=Times>10</font>，<font style="LINE-HEIGHT: 1.3em" face=Times>15</font>，<font style="LINE-HEIGHT: 1.3em" face=Times>20</font>，<font style="LINE-HEIGHT: 1.3em" face=Times>25</font>，<font style="LINE-HEIGHT: 1.3em" face=Times>30</font>，<font style="LINE-HEIGHT: 1.3em" face=Times>35</font>，<font style="LINE-HEIGHT: 1.3em" face=Times>40 </font></font><br><font style="FONT-SIZE: medium; LINE-HEIGHT: 1.3em">即认为其变化（增减）是线形的，可以在坐标图上画出一条直线 </font><br><font style="FONT-SIZE: medium; LINE-HEIGHT: 1.3em">在数码相机技术中，这些数值可以代表组成一张照片的不同像素点的色彩、色度等指标。 </font><br><br><font style="FONT-SIZE: medium; LINE-HEIGHT: 1.3em"><strong><font style="LINE-HEIGHT: 1.3em" color=#0000ff>为了方便理解，先考虑一维情况下的线性插值</font></strong> </font><br><font style="FONT-SIZE: medium; LINE-HEIGHT: 1.3em">对于一个数列<font style="LINE-HEIGHT: 1.3em" face=Times>c</font>，我们假设<font style="LINE-HEIGHT: 1.3em" face=Times>c[a]</font>到<font style="LINE-HEIGHT: 1.3em" face=Times>c[a+1]</font>之间是线性变化的 </font><br><font style="FONT-SIZE: medium; LINE-HEIGHT: 1.3em">那么对于浮点数<font style="LINE-HEIGHT: 1.3em" face=Times>x(a&lt;=x&lt;a+1)</font>，<font style="LINE-HEIGHT: 1.3em" face=Times>c(x)=c[a+1]*(x-a)+c[a]*(1+a-x); </font></font><br><br><font style="FONT-SIZE: medium; LINE-HEIGHT: 1.3em"><strong><font style="LINE-HEIGHT: 1.3em" color=#0000ff>把这种插值方式扩展到二维情况</font></strong> </font><br><font style="FONT-SIZE: medium; LINE-HEIGHT: 1.3em">对于一个二维数组<font style="LINE-HEIGHT: 1.3em" face=Times>c</font>，我们假设对于任意一个浮点数<font style="LINE-HEIGHT: 1.3em" face=Times>i,c(a,i)</font>到<font style="LINE-HEIGHT: 1.3em" face=Times>c(a+1,i)</font>之间是线性变化的<font style="LINE-HEIGHT: 1.3em" face=Times>,c(i,b)</font>到<font style="LINE-HEIGHT: 1.3em" face=Times>c(i,b+1)</font>之间也是线性变化的<font style="LINE-HEIGHT: 1.3em" face=Times>(a,b</font>都是整数<font style="LINE-HEIGHT: 1.3em" face=Times>) </font></font><br><font style="FONT-SIZE: medium; LINE-HEIGHT: 1.3em">那么对于浮点数的坐标<font style="LINE-HEIGHT: 1.3em" face=Times>(x,y)</font>满足<font style="LINE-HEIGHT: 1.3em" face=Times>(a&lt;=x&lt;a+1,b&lt;=y&lt;b+1)</font>，我们可以先分别求出<font style="LINE-HEIGHT: 1.3em" face=Times>c(x,b)</font>和<font style="LINE-HEIGHT: 1.3em" face=Times>c(x,b+1): </font></font><br><font style="FONT-SIZE: medium; LINE-HEIGHT: 1.3em" face=Times>c(x,b) = c[a+1]*(x-a)+c[a]*(1+a-x); </font><br><font style="FONT-SIZE: medium; LINE-HEIGHT: 1.3em" face=Times>c(x,b+1) = c[a+1][b+1]*(x-a)+c[a][b+1]*(1+a-x); </font><br><font style="FONT-SIZE: medium; LINE-HEIGHT: 1.3em">好，现在已经知道<font style="LINE-HEIGHT: 1.3em" face=Times>c(x,b)</font>和<font style="LINE-HEIGHT: 1.3em" face=Times>c(x,b+1)</font>了，而根据假设<font style="LINE-HEIGHT: 1.3em" face=Times>c(x,b)</font>到<font style="LINE-HEIGHT: 1.3em" face=Times>c(x,b+1)</font>也是线性变化的，所以<font style="LINE-HEIGHT: 1.3em" face=Times>: </font></font><br><font style="FONT-SIZE: medium; LINE-HEIGHT: 1.3em" face=Times>c(x,y) = c(x,b+1)*(y-b)+c(x,b)*(1+b-y) </font><br><font style="FONT-SIZE: medium; LINE-HEIGHT: 1.3em">这就是双线性插值。</font></font>
<img src ="http://www.cppblog.com/hello8706/aggbug/114640.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hello8706/" target="_blank">小火球</a> 2010-05-06 15:57 <a href="http://www.cppblog.com/hello8706/archive/2010/05/06/114640.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++宏的一些副作用</title><link>http://www.cppblog.com/hello8706/archive/2010/03/11/109410.html</link><dc:creator>小火球</dc:creator><author>小火球</author><pubDate>Thu, 11 Mar 2010 02:48:00 GMT</pubDate><guid>http://www.cppblog.com/hello8706/archive/2010/03/11/109410.html</guid><wfw:comment>http://www.cppblog.com/hello8706/comments/109410.html</wfw:comment><comments>http://www.cppblog.com/hello8706/archive/2010/03/11/109410.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/hello8706/comments/commentRss/109410.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/hello8706/services/trackbacks/109410.html</trackback:ping><description><![CDATA[<p>1、优先级问题</p>
<p>&nbsp;1) 传入变量优先级</p>
<p>&nbsp;&nbsp;&nbsp;#define MULTI(a,b)&nbsp;a * b</p>
<p>&nbsp;&nbsp;&nbsp;MULTI(1+2,3)&nbsp;&nbsp;&nbsp;=&gt; 1 + 2 * 3&nbsp;其实是想要(1 + 2) * 3</p>
<p>&nbsp;2) 作为值返回时，类似1）</p>
<p>&nbsp;&nbsp;&nbsp;#define ADD(a,b)&nbsp;(a) + (b)</p>
<p>&nbsp;&nbsp;&nbsp;int c = ADD(a,b) * 3;&nbsp;=&gt; (a) + (b) * 3 &nbsp;其实是想要(a + b) * 3</p>
<p>&nbsp;所以，一般的规则是：宏里面参数全部用括号括起来；如果作为值返回，整个表达式也用括号括起来。</p>
<p>&nbsp;所以，上面最好这么写：</p>
<p>&nbsp;&nbsp;&nbsp;#define&nbsp;MULTI(a,b)&nbsp;((a) * (b))</p>
<p>&nbsp;&nbsp;&nbsp;#define&nbsp;ADD(a,b)&nbsp;&nbsp;((a) + (b))</p>
<p>2、实际使用参数和宏内部变量同名</p>
<p>&nbsp;&nbsp;&nbsp;#define&nbsp;HASH(str,sz,rst)&nbsp;do{unsigned int n = 0; n = xxx; rst = n % sz;}while(0)</p>
<p>&nbsp;这是一个hash的宏实现，其中定义了一个临时变量n，根据str计算n，然后对sz求模并把返回值赋给传进来的rst.</p>
<p>&nbsp;这么调用：</p>
<p>&nbsp;&nbsp;&nbsp;int n;</p>
<p>&nbsp;&nbsp;&nbsp;HASH("hello",7,n);</p>
<p>&nbsp;不会达到改变n的效果，因为实际使用参数n和宏内部的变量n同名。宏扩展中最后一条语句是：n = n % sz;因为宏内部n有更小作&nbsp;用域，实际赋值的是宏内部的那个临时变量n。外面调用的n不会有任何改变。</p>
<p>&nbsp;这个副作用有些隐蔽，一般的规则是：宏内部变量使用一种不同风格的命名方式。</p>
<p>&nbsp;比如：</p>
<p>&nbsp;&nbsp;&nbsp;#define HASH(str,sz,rst)&nbsp;&nbsp;do{unsigned int __n = 0; __n = ...</p>
<p>3、++,--</p>
<p>&nbsp;&nbsp;&nbsp;#define&nbsp;MAX(a,b)&nbsp;&nbsp;((a) &gt; (b) ? (a) : (b))</p>
<p>&nbsp;&nbsp;&nbsp;int a = 3,b = 2;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;int c = MAX(a++,b);</p>
<p>&nbsp;执行看看，不但a的值不是和想要的一致，返回值c也会让你大吃一惊，哈哈。(a = 5,c = 4)</p>
<p>&nbsp;在宏内部一个变量"执行"多少次，它就自增或自减了多少次。</p>
<p>&nbsp;所以一般使用宏最好不要传入自增自减。如果你一定要在宏里消除这个副作用，可以这样：</p>
<p>&nbsp;&nbsp;&nbsp;#define&nbsp;MAX(a,b)&nbsp;&nbsp;({int __x = (a), __y = (b);(__x &gt; __y) ? __x : __y;})</p>
<p>&nbsp;也就是：保证传入宏的参数在内部只使用一次。(注意：传入a++或++a都能得到各自正确的效果)</p>
<p>&nbsp;这里的内部变量__x,__y是不需要用括号包起来的，原因可以自己想想。</p>
<p>&nbsp;另外对宏中括号的使用补充说明两点：</p>
<p>&nbsp;&nbsp;因为宏中定义了临时变量，所以要用{}括起来；</p>
<p>&nbsp;&nbsp;因为要返回值，所以外面还要用()括起来({}不返回值)；</p>
<p>&nbsp;另外，这里还有一个问题：实际中a,b不一定是int的，这个宏中的临时变量声明为int，不通用。</p>
<p>&nbsp;改进：</p>
<p>&nbsp;&nbsp;&nbsp;#define&nbsp;MAX(a,b,type)&nbsp;({type __x = (a), __y = (b);(__x &gt; __y) ? __x : __y;})</p>
<p>&nbsp;使用：</p>
<p>&nbsp;&nbsp;&nbsp;MAX(1,2,int);&nbsp; MAX(1.1,1.2,double);</p>
<p>&nbsp;是不是感觉怪怪的，有点c++的感觉～～ 这样的使用太复杂了，而且也会给代码的阅读带来难度。</p>
<p>&nbsp;我觉得好的态度是多了解些宏的可能的副作用，在实际编码中遵守第1、2条规则，不要往宏中传入自增自减的东西，就够了。不要把过多的复杂度全扔给宏，"通用"也不能盲目，因为毕竟：yy是没有极限的。</p>
<img src ="http://www.cppblog.com/hello8706/aggbug/109410.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hello8706/" target="_blank">小火球</a> 2010-03-11 10:48 <a href="http://www.cppblog.com/hello8706/archive/2010/03/11/109410.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）C++位运算</title><link>http://www.cppblog.com/hello8706/archive/2010/03/10/109367.html</link><dc:creator>小火球</dc:creator><author>小火球</author><pubDate>Wed, 10 Mar 2010 09:02:00 GMT</pubDate><guid>http://www.cppblog.com/hello8706/archive/2010/03/10/109367.html</guid><wfw:comment>http://www.cppblog.com/hello8706/comments/109367.html</wfw:comment><comments>http://www.cppblog.com/hello8706/archive/2010/03/10/109367.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/hello8706/comments/commentRss/109367.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/hello8706/services/trackbacks/109367.html</trackback:ping><description><![CDATA[<div class=blog_content>
<p>最近想系统的对位运算了解一下，所以在网上转了这个，分享一下。<br>关键字：c++位运算</p>
<p>什么是位(bit)？ <br><br>很简单，位(bit)就是单个的0或1，位是我们在计算机上所作一切的基础。计算机上的所有数据都是用位来存储的。一个字节(BYTE)由八个位组成，一个字(WORD)是二个字节或十六位，一个双字(DWORD)是二个字(WORDS)或三十二位。如下所示： <br><br>0 1 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 1 1 1 0 1 0 0 0 1 1 1 1 0 0 0 <br>| | | | | | | <br>| +- bit 31 | | | bit 0 -+ | <br>| | | | | <br>+-- BYTE 3 ---- -+---- BYTE 2 ---+---- BYTE 1 ---+--- BYTE 0 -----+ <br>| | | <br>+------------ WORD 1 ------------+----------- WORD 0 -------------+ <br>| | <br>+----------------------------- DWORD -----------------------------+ <br><br>使用位运算的好处是可以将BYTE, WORD 或 DWORD 作为小数组或结构使用。通过位运算可以检查位的值或赋值，也可以对整组的位进行运算。 <br><br>16进制数及其与位的关系 <br>用0或1表示的数值就是二进制数，很难理解。因此用到16进制数。 <br><br>16进制数用4个位表示0 - 15的值，4个位组成一个16进制数。也把4位成为半字节(nibble)。一个BYTE有二个nibble，因此可以用二个16进制数表示一个BYTE。如下所示： <br><br>NIBBLE HEX VALUE <br>====== ========= <br>0000 0 <br>0001 1 <br>0010 2 <br>0011 3 <br>0100 4 <br>0101 5 <br>0110 6 <br>0111 7 <br>1000 8 <br>1001 9 <br>1010 A <br>1011 B <br>1100 C <br>1101 D <br>1110 E <br>1111 F <br><br>如果用一个字节存放字母"r"(ASCII码114)，结果是： <br>0111 0010 二进制 <br>7 2 16进制 <br><br>可以表达为：'0x72' <br><br>有6种位运算： <br>&amp; 与运算 <br>| 或运算 <br>^ 异或运算 <br>~ 非运算(求补) <br>&gt;&gt; 右移运算 <br>&lt;&lt; 左移运算 <br><br>与运算(&amp;) <br>双目运算。二个位都置位(等于1)时，结果等于1，其它的结果都等于0。 <br>1 &amp; 1 == 1 <br>1 &amp; 0 == 0 <br>0 &amp; 1 == 0 <br>0 &amp; 0 == 0 <br><br>与运算的一个用途是检查指定位是否置位(等于1)。例如一个BYTE里有标识位，要检查第4位是否置位，代码如下： <br><br>BYTE b = 50; <br>if ( b &amp; 0x10 ) <br>cout &lt;&lt; "Bit four is set" &lt;&lt; endl; <br>else <br>cout &lt;&lt; "Bit four is clear" &lt;&lt; endl; <br><br>上述代码可表示为： <br><br>00110010 - b <br>&amp; 00010000 - &amp; 0x10 <br>---------------------------- <br>00010000 - result <br><br>可以看到第4位是置位了。 <br><br>或运算( | ) <br>双目运算。二个位只要有一个位置位，结果就等于1。二个位都为0时，结果为0。 <br>1 | 1 == 1 <br>1 | 0 == 1 <br>0 | 1 == 1 <br>0 | 0 == 0 <br><br>与运算也可以用来检查置位。例如要检查某个值的第3位是否置位： <br><br>BYTE b = 50; <br>BYTE c = b | 0x04; <br>cout &lt;&lt; "c = " &lt;&lt; c &lt;&lt; endl; <br><br>可表达为： <br><br>00110010 - b <br>| 00000100 - | 0x04 <br>---------- <br>00110110 - result <br><br>异或运算(^) <br>双目运算。二个位不相等时，结果为1，否则为0。 <br><br>1 ^ 1 == 0 <br>1 ^ 0 == 1 <br>0 ^ 1 == 1 <br>0 ^ 0 == 0 <br><br>异或运算可用于位值翻转。例如将第3位与第4位的值翻转： <br><br>BYTE b = 50; <br>cout &lt;&lt; "b = " &lt;&lt; b &lt;&lt; endl; <br>b = b ^ 0x18; <br>cout &lt;&lt; "b = " &lt;&lt; b &lt;&lt; endl; <br>b = b ^ 0x18; <br>cout &lt;&lt; "b = " &lt;&lt; b &lt;&lt; endl; <br><br>可表达为： <br><br>00110010 - b <br>^ 00011000 - ^0x18 <br>---------- <br>00101010 - result <br><br>00101010 - b <br>^ 00011000 - ^0x18 <br>---------- <br>00110010 - result <br><br>非运算(~) <br>单目运算。位值取反，置0为1，或置1为0。非运算的用途是将指定位清0，其余位置1。非运算与数值大小无关。例如将第1位和第2位清0，其余位置1： <br><br>BYTE b = ~0x03; <br>cout &lt;&lt; "b = " &lt;&lt; b &lt;&lt; endl; <br>WORD w = ~0x03; <br>cout &lt;&lt; "w = " &lt;&lt; w &lt;&lt; endl; <br><br>可表达为： <br><br>00000011 - 0x03 <br>11111100 - ~0x03 b <br><br>0000000000000011 - 0x03 <br>1111111111111100 - ~0x03 w <br><br>非运算和与运算结合，可以确保将指定为清0。如将第4位清0： <br><br>BYTE b = 50; <br>cout &lt;&lt; "b = " &lt;&lt; b &lt;&lt; endl; <br>BYTE c = b &amp; ~0x10; <br>cout &lt;&lt; "c = " &lt;&lt; c &lt;&lt; endl; <br><br>可表达为： <br><br>00110010 - b <br>&amp; 11101111 - ~0x10 <br>---------- <br>00100010 - result <br><br>移位运算(&gt;&gt; 与 &lt;&lt;) <br>将位值向一个方向移动指定的位数。右移 &gt;&gt; 算子从高位向低位移动，左移 &lt;&lt; 算子从低位向高位移动。往往用位移来对齐位的排列(如MAKEWPARAM, HIWORD, LOWORD 宏的功能)。 <br><br>BYTE b = 12; <br>cout &lt;&lt; "b = " &lt;&lt; b &lt;&lt; endl; <br>BYTE c = b &lt;&lt; 2; <br>cout &lt;&lt; "c = " &lt;&lt; c &lt;&lt; endl; <br>c = b &gt;&gt; 2; <br>cout &lt;&lt; "c = " &lt;&lt; c &lt;&lt; endl; <br><br>可表达为： <br>00001100 - b <br>00110000 - b &lt;&lt; 2 <br>00000011 - b &gt;&gt; 2 <br><br>译注：以上示例都对，但举例用法未必恰当。请阅文末链接的文章，解释得较为清楚。 <br><br>位域(Bit Field) <br>位操作中的一件有意义的事是位域。利用位域可以用BYTE, WORD或DWORD来创建最小化的数据结构。例如要保存日期数据，并尽可能减少内存占用，就可以声明这样的结构： <br><br>struct date_struct { <br>BYTE day : 5, // 1 to 31 <br>month : 4, // 1 to 12 <br>year : 14; // 0 to 9999 <br>}date; <br><br>在结构中，日期数据占用最低5位，月份占用4位，年占用14位。这样整个日期数据只需占用23位，即3个字节。忽略第24位。如果用整数来表达各个域，整个结构要占用12个字节。 <br><br>| 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | <br>| | | | <br>+------------- year --------------+ month+-- day --+ <br><br>现在分别看看在这个结构声明中发生了什么 <br><br>首先看一下位域结构使用的数据类型。这里用的是BYTE。1个BYTE有8个位，编译器将分配1个BYTE的内存。如果结构内的数据超过8位，编译器就再分配1个BYTE，直到满足数据要求。如果用WORD或DWORD作结构的数据类型，编译器就分配一个完整的32位内存给结构。 <br><br>其次看一下域声明。变量(day, month, year)名跟随一个冒号，冒号后是变量占用的位数。位域之间用逗号分隔，用分号结束。 <br><br>使用了位域结构，就可以方便地象处理普通结构数据那样处理成员数据。尽管我们无法得到位域的地址，却可以使用结构地址。例如： <br>date.day = 12; <br>dateptr = &amp;date; <br>dateptr-&gt;year = 1852;</p>
</div>
<script type=text/javascript><!--
google_ad_client = "pub-4348265167276910";
/* 468x60, 个人博客 */
google_ad_slot = "2046406163";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script><script type=text/javascript src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script><script src="http://pagead2.googlesyndication.com/pagead/expansion_embed.js"></script><script src="http://googleads.g.doubleclick.net/pagead/test_domain.js"></script><script src="http://pagead2.googlesyndication.com/pagead/render_ads.js"></script><script>google_protectAndRun("render_ads.js::google_render_ad", google_handleError, google_render_ad);</script>
<img src ="http://www.cppblog.com/hello8706/aggbug/109367.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hello8706/" target="_blank">小火球</a> 2010-03-10 17:02 <a href="http://www.cppblog.com/hello8706/archive/2010/03/10/109367.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>