﻿<?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++博客-AFEI-随笔分类-转帖</title><link>http://www.cppblog.com/AFEI/category/17294.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 12 Jul 2011 18:30:15 GMT</lastBuildDate><pubDate>Tue, 12 Jul 2011 18:30:15 GMT</pubDate><ttl>60</ttl><item><title>pragma comment的使用</title><link>http://www.cppblog.com/AFEI/archive/2011/07/13/150806.html</link><dc:creator>小谢</dc:creator><author>小谢</author><pubDate>Tue, 12 Jul 2011 18:16:00 GMT</pubDate><guid>http://www.cppblog.com/AFEI/archive/2011/07/13/150806.html</guid><wfw:comment>http://www.cppblog.com/AFEI/comments/150806.html</wfw:comment><comments>http://www.cppblog.com/AFEI/archive/2011/07/13/150806.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/AFEI/comments/commentRss/150806.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/AFEI/services/trackbacks/150806.html</trackback:ping><description><![CDATA[<div>该宏放置一个注释到对象文件或者可执行文件。<br /> <pre><strong>#pragma comment(</strong> comment-type [<strong>,"</strong>commentstring<strong>"</strong>] <strong>)<br /><br /></strong><em>comment-type</em>是一个预定义的标识符，指定注释的类型，应该是<strong>compiler，</strong><strong>exestr，lib，linker</strong>之一。<br />commentstring是一个提供为<em>comment-type</em>提供附加信息的字符串，<br />Remarks：<br />1、compiler：放置编译器的版本或者名字到一个对象文件，该选项是被linker忽略的。<br />2、exestr：在以后的版本将被取消。<br />3、lib：放置一个库搜索记录到对象文件中，这个类型应该是和commentstring（指定你要Liner搜索的lib的名称和路径）<br />这个库的名字放在Object文件的默认库搜索记录的后面，linker搜索这个这个库就像你在命令行输入这个命令一样。你可以<br />在一个源文件中设置多个库记录，它们在object文件中的顺序和在源文件中的顺序一样。如果默认库和附加库的次序是需要<br />区别的，使用Z编译开关是防止默认库放到object模块。<br />4、linker：指定一个连接选项，这样就不用在命令行输入或者在开发环境中设置了。<br />只有下面的linker选项能被传给Linker.<br /></pre> <ul><li>     <p>/DEFAULTLIB</p>     </li><li>     <p>/EXPORT</p>     </li><li>     <p>/INCLUDE</p>     </li><li>     <p>/MANIFESTDEPENDENCY     </p>     </li><li>     <p>/MERGE</p>     </li><li>     <p>/SECTION</p>     </li></ul> <pre>(1)/DEFAULTLIB:<em>library<br /><br /></em>/DEFAULTLIB 选项将一个 <em>library</em> 添加到 LINK 在解析引用时搜索的库列表。用 /DEFAULTLIB 指定的库在命令行上指定的库之后和 .obj 文件中指定的默认库之前被搜索。<br /></pre> <p>忽略所有默认库 (/NODEFAULTLIB) 选项重写 /DEFAULTLIB:library。如果在两者中指定了相同的 library 名称，<span style="color: #080000;">忽略库</span> (/NODEFAULTLIB:<em>library</em>) 选项将重写 /DEFAULTLIB:<em>library</em>。</p> <p>(2)/EXPORT:<em>entryname</em>[,@<em>ordinal</em>[,NONAME]][,DATA]<br /></p> <p>使用该选项，可以从程序导出函数，以便其他程序可以调用该函数。也可以导出数据。通常在 DLL 中定义导出。<em>entryname</em> 是调用程序要使用的函数或数据项的名称。ordinal 在导出表中指定范围在 1 至 65,535 的索引；如果没有指定 ordinal，则 LINK 将分配一个。<strong>NONAME</strong> 关键字只将函数导出为序号，没有 <em>entryname</em>。</p> <p><strong>DATA </strong>关键字指定导出项为数据项。客户程序中的数据项必须用 <strong>extern __declspec(dllimport)</strong> 来声明。<br />有三种导出定义的方法，按照建议的使用顺序依次为： </p> <ol><li>     <p>源代码中的 __declspec(dllexport)</p>     </li><li>     <p>.def 文件中的 EXPORTS     语句</p>     </li><li>     <p>LINK 命令中的 /EXPORT 规范</p>     </li></ol> <p>所有这三种方法可以用在同一个程序中。LINK 在生成包含导出的程序时还创建导入库，除非生成中使用了 .exp 文件。<br />LINK 使用标识符的修饰形式。编译器在创建 .obj 文件时修饰标识符。如果 <em>entryname</em> 以其未修饰的形式指定给链接器（与其在源代码中一样），则 LINK 将试图匹配该名称。如果无法找到唯一的匹配名称，则 LINK 发出错误信息。当需要将标识符指定给链接器时，请使用 Dumpbin 工具获取该标识符的修饰名形式。</p> <pre>(3)/INCLUDE:<em>symbol<br /></em></pre> <p>/INCLUDE 选项通知链接器将指定的符号添加到符号表。</p> <p>若要指定多个符号，请在符号名称之间键入逗号 (,)、分号 (;) 或空格。在命令行上，对每个符号指定一次 /INCLUDE:symbol。<br />链接器通过将包含符号定义的对象添加到程序来解析 symbol。该功能对于添包含不会链接到程序的库对象非常有用。用该选项指定符号将通过 /OPT:REF 重写该符号的移除。</p> <pre><br /><em><br /></em>我们经常用到的是#pragma &nbsp; comment（lib，"*.lib"）这类的。<br />#pragma &nbsp; comment(lib,"Ws2_32.lib")表示链接Ws2_32.lib这个库。 &nbsp; <br />和在工程设置里写上链入Ws2_32.lib的效果一样，不过这种方法写的 &nbsp; <br />程序别人在使用你的代码的时候就不用再设置工程settings了</pre></div><img src ="http://www.cppblog.com/AFEI/aggbug/150806.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/AFEI/" target="_blank">小谢</a> 2011-07-13 02:16 <a href="http://www.cppblog.com/AFEI/archive/2011/07/13/150806.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>堆和栈的区别</title><link>http://www.cppblog.com/AFEI/archive/2011/07/12/150723.html</link><dc:creator>小谢</dc:creator><author>小谢</author><pubDate>Mon, 11 Jul 2011 16:59:00 GMT</pubDate><guid>http://www.cppblog.com/AFEI/archive/2011/07/12/150723.html</guid><wfw:comment>http://www.cppblog.com/AFEI/comments/150723.html</wfw:comment><comments>http://www.cppblog.com/AFEI/archive/2011/07/12/150723.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/AFEI/comments/commentRss/150723.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/AFEI/services/trackbacks/150723.html</trackback:ping><description><![CDATA[<div><h2>堆和栈的区别&nbsp;(转贴) </h2> 		<p>非本人作也!因非常经典,所以收归旗下,与众人阅之!原作者不祥!</p> 		堆和栈的区别<br />一、预备知识&#8212;程序的内存分配<br />一个由c/C++编译的程序占用的内存分为以下几个部分<br />1、栈区（stack）&#8212;&nbsp;由编译器自动分配释放&nbsp;，存放函数的参数值，局部变量的值等。其操作方式类似于数据结构中的栈。<br />2、堆区（heap）&nbsp;&#8212;&nbsp;一般由程序员分配释放，&nbsp;若程序员不释放，程序结束时可能由OS回收&nbsp;。注意它与数据结构中的堆是两回事，分配方式倒是类似于链表，呵呵。<br />3、全局区（静态区）（static）&#8212;，全局变量和静态变量的存储是放在一块的，初始化的全局变量和静态变量在一块区域，&nbsp;未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。&nbsp;-&nbsp;程序结束后有系统释放&nbsp;<br />4、文字常量区&#8212;常量字符串就是放在这里的。&nbsp;程序结束后由系统释放<br />5、程序代码区&#8212;存放函数体的二进制代码。<br />二、例子程序&nbsp;<br />这是一个前辈写的，非常详细&nbsp;<br />//main.cpp&nbsp;<br />int&nbsp;a&nbsp;=&nbsp;0;&nbsp;全局初始化区&nbsp;<br />char&nbsp;*p1;&nbsp;全局未初始化区&nbsp;<br />main()&nbsp;<br />{&nbsp;<br />int&nbsp;b;&nbsp;栈&nbsp;<br />char&nbsp;s[]&nbsp;=&nbsp;"abc";&nbsp;栈&nbsp;<br />char&nbsp;*p2;&nbsp;栈&nbsp;<br />char&nbsp;*p3&nbsp;=&nbsp;"123456";&nbsp;123456\0在常量区，p3在栈上。&nbsp;<br />static&nbsp;int&nbsp;c&nbsp;=0；&nbsp;全局（静态）初始化区&nbsp;<br />p1&nbsp;=&nbsp;(char&nbsp;*)malloc(10);&nbsp;<br />p2&nbsp;=&nbsp;(char&nbsp;*)malloc(20);&nbsp;<br />分配得来得10和20字节的区域就在堆区。&nbsp;<br />strcpy(p1,&nbsp;"123456");&nbsp;123456\0放在常量区，编译器可能会将它与p3所指向的"123456"优化成一个地方。&nbsp;<br />}&nbsp;  <p><br />二、堆和栈的理论知识&nbsp;<br />2.1申请方式&nbsp;<br />stack:&nbsp;<br />由系统自动分配。&nbsp;例如，声明在函数中一个局部变量&nbsp;int&nbsp;b;&nbsp;系统自动在栈中为b开辟空间&nbsp;<br />heap:&nbsp;<br />需要程序员自己申请，并指明大小，在c中malloc函数&nbsp;<br />如p1&nbsp;=&nbsp;(char&nbsp;*)malloc(10);&nbsp;<br />在C++中用new运算符&nbsp;<br />如p2&nbsp;=&nbsp;(char&nbsp;*)malloc(10);&nbsp;<br />但是注意p1、p2本身是在栈中的。&nbsp;</p><p><br />2.2&nbsp;<br />申请后系统的响应&nbsp;<br />栈：只要栈的剩余空间大于所申请空间，系统将为程序提供内存，否则将报异常提示栈溢出。&nbsp;<br />堆：首先应该知道操作系统有一个记录空闲内存地址的链表，当系统收到程序的申请时，&nbsp;<br />会 遍历该链表，寻找第一个空间大于所申请空间的堆结点，然后将该结点从空闲结点链表中删除，并将该结点的空间分配给程序，另外，对于大多数系统，会在这块内 存空间中的首地址处记录本次分配的大小，这样，代码中的delete语句才能正确的释放本内存空间。另外，由于找到的堆结点的大小不一定正好等于申请的大 小，系统会自动的将多余的那部分重新放入空闲链表中。&nbsp;</p><p>2.3申请大小的限制&nbsp;<br />栈：在Windows下,栈是向低地址扩展的数据结 构，是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的，在WINDOWS下，栈的大小是2M（也有的说是1M，总之是 一个编译时就确定的常数），如果申请的空间超过栈的剩余空间时，将提示overflow。因此，能从栈获得的空间较小。&nbsp;<br />堆：堆是向高地址扩展的数据结构，是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的，自然是不连续的，而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见，堆获得的空间比较灵活，也比较大。&nbsp;</p><p><br />2.4申请效率的比较：&nbsp;<br />栈由系统自动分配，速度较快。但程序员是无法控制的。&nbsp;<br />堆是由new分配的内存，一般速度比较慢，而且容易产生内存碎片,不过用起来最方便.&nbsp;<br />另外，在WINDOWS下，最好的方式是用VirtualAlloc分配内存，他不是在堆，也不是在栈是直接在进程的地址空间中保留一快内存，虽然用起来最不方便。但是速度快，也最灵活。&nbsp;</p><p>2.5堆和栈中的存储内容&nbsp;<br />栈：&nbsp;在函数调用时，第一个进栈的是主函数中后的下一条指令（函数调用语句的下一条可执行语句）的地址，然后是函数的各个参数，在大多数的C编译器中，参数是由右往左入栈的，然后是函数中的局部变量。注意静态变量是不入栈的。&nbsp;<br />当本次函数调用结束后，局部变量先出栈，然后是参数，最后栈顶指针指向最开始存的地址，也就是主函数中的下一条指令，程序由该点继续运行。&nbsp;<br />堆：一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。&nbsp;</p><p>2.6存取效率的比较&nbsp;</p><p>char&nbsp;s1[]&nbsp;=&nbsp;"aaaaaaaaaaaaaaa";&nbsp;<br />char&nbsp;*s2&nbsp;=&nbsp;"bbbbbbbbbbbbbbbbb";&nbsp;<br />aaaaaaaaaaa是在运行时刻赋值的；&nbsp;<br />而bbbbbbbbbbb是在编译时就确定的；&nbsp;<br />但是，在以后的存取中，在栈上的数组比指针所指向的字符串(例如堆)快。&nbsp;<br />比如：&nbsp;<br />#include&nbsp;<br />void&nbsp;main()&nbsp;<br />{&nbsp;<br />char&nbsp;a&nbsp;=&nbsp;1;&nbsp;<br />char&nbsp;c[]&nbsp;=&nbsp;"1234567890";&nbsp;<br />char&nbsp;*p&nbsp;="1234567890";&nbsp;<br />a&nbsp;=&nbsp;c[1];&nbsp;<br />a&nbsp;=&nbsp;p[1];&nbsp;<br />return;&nbsp;<br />}&nbsp;<br />对应的汇编代码&nbsp;<br />10:&nbsp;a&nbsp;=&nbsp;c[1];&nbsp;<br />00401067&nbsp;8A&nbsp;4D&nbsp;F1&nbsp;mov&nbsp;cl,byte&nbsp;ptr&nbsp;[ebp-0Fh]&nbsp;<br />0040106A&nbsp;88&nbsp;4D&nbsp;FC&nbsp;mov&nbsp;byte&nbsp;ptr&nbsp;[ebp-4],cl&nbsp;<br />11:&nbsp;a&nbsp;=&nbsp;p[1];&nbsp;<br />0040106D&nbsp;8B&nbsp;55&nbsp;EC&nbsp;mov&nbsp;edx,dword&nbsp;ptr&nbsp;[ebp-14h]&nbsp;<br />00401070&nbsp;8A&nbsp;42&nbsp;01&nbsp;mov&nbsp;al,byte&nbsp;ptr&nbsp;[edx+1]&nbsp;<br />00401073&nbsp;88&nbsp;45&nbsp;FC&nbsp;mov&nbsp;byte&nbsp;ptr&nbsp;[ebp-4],al&nbsp;<br />第一种在读取时直接就把字符串中的元素读到寄存器cl中，而第二种则要先把指针值读到edx中，在根据edx读取字符，显然慢了。&nbsp;</p><br />2.7小结：&nbsp;<br />堆和栈的区别可以用如下的比喻来看出：&nbsp;<br />使用栈就象我们去饭馆里吃饭，只管点菜（发出申请）、付钱、和吃（使用），吃饱了就走，不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作，他的好处是快捷，但是自由度小。&nbsp;<br />使用堆就象是自己动手做喜欢吃的菜肴，比较麻烦，但是比较符合自己的口味，而且自由度大。</div><img src ="http://www.cppblog.com/AFEI/aggbug/150723.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/AFEI/" target="_blank">小谢</a> 2011-07-12 00:59 <a href="http://www.cppblog.com/AFEI/archive/2011/07/12/150723.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>