﻿<?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++博客-积木-随笔分类-VC / C++</title><link>http://www.cppblog.com/Tongy0/category/17057.html</link><description>No sub title</description><language>zh-cn</language><lastBuildDate>Fri, 20 Mar 2015 08:51:42 GMT</lastBuildDate><pubDate>Fri, 20 Mar 2015 08:51:42 GMT</pubDate><ttl>60</ttl><item><title>【转载】C中的预编译宏定义</title><link>http://www.cppblog.com/Tongy0/archive/2015/03/18/210093.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Wed, 18 Mar 2015 01:56:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2015/03/18/210093.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/210093.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2015/03/18/210093.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/210093.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/210093.html</trackback:ping><description><![CDATA[ 原文转载自：http://www.uml.org.cn/c++/200902104.asp 

一篇讲解宏预编译的内容。 

<img src ="http://www.cppblog.com/Tongy0/aggbug/210093.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2015-03-18 09:56 <a href="http://www.cppblog.com/Tongy0/archive/2015/03/18/210093.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转载】C语言stat()函数：获取文件状态</title><link>http://www.cppblog.com/Tongy0/archive/2015/01/20/209594.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Tue, 20 Jan 2015 11:36:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2015/01/20/209594.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/209594.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2015/01/20/209594.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/209594.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/209594.html</trackback:ping><description><![CDATA[<div><font style="background-color: #c7edcc">转自:<a href="http://c.biancheng.net/cpp/html/326.html">http://c.biancheng.net/cpp/html/326.html</a><br /><br />
<div style="padding-bottom: 5px; text-transform: none; background-color: rgb(238,238,238); text-indent: 0px; font: 14px 'Microsoft Yahei', Arial, Helvetica, sans-serif; white-space: normal; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-stroke-width: 0px" id="ad-shoutu">站长收徒：<a style="border-bottom: medium none; border-left: medium none; color: rgb(0,136,204); border-top: medium none; border-right: medium none; text-decoration: none" href="http://www.weixueyuan.net/shoutu/" target="_blank">C语言基础视频 + C语言扩展视频 + C语言高级视频 + 一对一答疑</a></div>
<div style="text-transform: none; background-color: rgb(238,238,238); text-indent: 0px; font: 14px/1.6em 'Microsoft Yahei', Arial, Helvetica, sans-serif; white-space: normal; margin-bottom: 12px; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-stroke-width: 0px" id="art-body">相关函数：fstat, lstat, chmod, chown, readlink, utime<br /><br />头文件：#include &lt;sys/stat.h&gt; &nbsp;&nbsp;#include &lt;unistd.h&gt;<br /><br />定义函数：int stat(const char * file_name, struct stat *buf);<br /><br /><span style="color: rgb(255,0,0)">函数说明：stat()用来将参数file_name 所指的文件状态, 复制到参数buf 所指的结构中。</span><br /><br />下面是struct stat 内各参数的说明：<br />struct stat<br />{<br />&nbsp; &nbsp; dev_t st_dev; //device 文件的设备编号<br />&nbsp; &nbsp; ino_t st_ino; //inode 文件的i-node<br />&nbsp; &nbsp; mode_t st_mode; //protection 文件的类型和存取的权限<br />&nbsp; &nbsp; nlink_t st_nlink; //number of hard links 连到该文件的硬连接数目, 刚建立的文件值为1.<br />&nbsp; &nbsp; uid_t st_uid; //user ID of owner 文件所有者的用户识别码<br />&nbsp; &nbsp; gid_t st_gid; //group ID of owner 文件所有者的组识别码<br />&nbsp; &nbsp; dev_t st_rdev; //device type 若此文件为装置设备文件, 则为其设备编号<br />&nbsp; &nbsp; off_t st_size; //total size, in bytes 文件大小, 以字节计算<br />&nbsp; &nbsp; unsigned long st_blksize; //blocksize for filesystem I/O 文件系统的I/O 缓冲区大小.<br />&nbsp; &nbsp; unsigned long st_blocks; //number of blocks allocated 占用文件区块的个数, 每一区块大小为512 个字节.<br />&nbsp; &nbsp; time_t st_atime; //time of lastaccess 文件最近一次被存取或被执行的时间, 一般只有在用mknod、utime、read、write 与tructate 时改变.<br />&nbsp; &nbsp; time_t st_mtime; //time of last modification 文件最后一次被修改的时间, 一般只有在用mknod、utime 和write 时才会改变<br />&nbsp; &nbsp; time_t st_ctime; //time of last change i-node 最近一次被更改的时间, 此参数会在文件所有者、组、权限被更改时更新<br />};<br /><br /><span style="color: rgb(165,42,42)">先前所描述的st_mode 则定义了下列数种情况：<br />1、S_IFMT 0170000 文件类型的位遮罩<br />2、S_IFSOCK 0140000 scoket<br />3、S_IFLNK 0120000 符号连接<br />4、S_IFREG 0100000 一般文件<br />5、S_IFBLK 0060000 区块装置<br />6、S_IFDIR 0040000 目录<br />7、S_IFCHR 0020000 字符装置<br />8、S_IFIFO 0010000 先进先出<br />9、S_ISUID 04000 文件的 (set user-id on execution)位<br />10、S_ISGID 02000 文件的 (set group-id on execution)位<br />11、S_ISVTX 01000 文件的sticky 位<br />12、S_IRUSR (S_IREAD) 00400 文件所有者具可读取权限<br />13、S_IWUSR (S_IWRITE)00200 文件所有者具可写入权限<br />14、S_IXUSR (S_IEXEC) 00100 文件所有者具可执行权限<br />15、S_IRGRP 00040 用户组具可读取权限<br />16、S_IWGRP 00020 用户组具可写入权限<br />17、S_IXGRP 00010 用户组具可执行权限<br />18、S_IROTH 00004 其他用户具可读取权限<br />19、S_IWOTH 00002 其他用户具可写入权限<br />20、S_IXOTH 00001 其他用户具可执行权限上述的文件类型在 POSIX 中定义了检查这些类型的宏定义<br />21、S_ISLNK (st_mode) 判断是否为符号连接<br />22、S_ISREG (st_mode) 是否为一般文件<br />23、S_ISDIR (st_mode) 是否为目录<br />24、S_ISCHR (st_mode) 是否为字符装置文件<br />25、S_ISBLK (s3e) 是否为先进先出<br />26、S_ISSOCK (st_mode) 是否为socket 若一目录具有sticky 位 (S_ISVTX), 则表示在此目录下的文件只能被该文件所有者、此目录所有者或root 来删除或改名.</span><br /><br />返回值：执行成功则返回0，失败返回-1，错误代码存于errno。<br /><br /><span style="color: rgb(165,42,42)">错误代码：<br />1、ENOENT 参数file_name 指定的文件不存在<br />2、ENOTDIR 路径中的目录存在但却非真正的目录<br />3、ELOOP 欲打开的文件有过多符号连接问题, 上限为16 符号连接<br />4、EFAULT 参数buf 为无效指针, 指向无法存在的内存空间<br />5、EACCESS 存取文件时被拒绝<br />6、ENOMEM 核心内存不足<br />7、ENAMETOOLONG 参数file_name 的路径名称太长</span><br /><br />范例<br />#include &lt;sys/stat.h&gt;<br />#include &lt;unistd.h&gt;<br />main()<br />{<br />&nbsp; &nbsp; struct stat buf;<br />&nbsp; &nbsp; stat("/etc/passwd", &amp;buf);<br />&nbsp; &nbsp; printf("/etc/passwd file size = %d \n", buf.st_size);<br />}<br /><br />执行：<br />/etc/passwd file size = 705</div><br /></font></div><img src ="http://www.cppblog.com/Tongy0/aggbug/209594.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2015-01-20 19:36 <a href="http://www.cppblog.com/Tongy0/archive/2015/01/20/209594.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转载】创建并调用MFC规则DLL的实例</title><link>http://www.cppblog.com/Tongy0/archive/2014/11/14/208874.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Fri, 14 Nov 2014 02:02:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2014/11/14/208874.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/208874.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2014/11/14/208874.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/208874.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/208874.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 原文转载自：http://blog.csdn.net/callbackfunc/article/details/7233894本例通过新建一个MFC规则DLL并新建一个MFC对话框程序调用它，演示MFC规则DLL的创建及调用。（VS2010环境下实例代码亲测可编译通过）一、MFC规则DLL项目1.创建MFC规则DLL2.新建global.cpp(新建此文件没有特殊意义，仅用...&nbsp;&nbsp;<a href='http://www.cppblog.com/Tongy0/archive/2014/11/14/208874.html'>阅读全文</a><img src ="http://www.cppblog.com/Tongy0/aggbug/208874.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2014-11-14 10:02 <a href="http://www.cppblog.com/Tongy0/archive/2014/11/14/208874.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ Json数据保存与解析(到文件)</title><link>http://www.cppblog.com/Tongy0/archive/2014/10/21/208634.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Tue, 21 Oct 2014 01:49:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2014/10/21/208634.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/208634.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2014/10/21/208634.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/208634.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/208634.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 直接上代码Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->&nbsp;&nbsp;1&nbsp;#include&nbsp;"stdafx.h"&nbsp;&nbsp;2&nbsp;#include&nbsp;&lt;fstream&gt;&nbs...&nbsp;&nbsp;<a href='http://www.cppblog.com/Tongy0/archive/2014/10/21/208634.html'>阅读全文</a><img src ="http://www.cppblog.com/Tongy0/aggbug/208634.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2014-10-21 09:49 <a href="http://www.cppblog.com/Tongy0/archive/2014/10/21/208634.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用 std::stringstream 将数值型转 string 时有坑</title><link>http://www.cppblog.com/Tongy0/archive/2014/03/28/206374.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Fri, 28 Mar 2014 03:21:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2014/03/28/206374.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/206374.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2014/03/28/206374.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/206374.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/206374.html</trackback:ping><description><![CDATA[众所周知，用stringstream实现数值型与string进行互转是十分方便的。<br />但它不是万能的。有着许多限制。下面就列出几点让人比较郁闷的，也是问题比较大条的坑，大伙需警惕。<br />坑 1：<br />如果待转换的数值型为整型，且值为0时，则转换出来的字符串去并不是："0"。<br />调试跟踪后，发现最终结果是一个，类似：""(即：空字符串)，却并非空字符串的东西。<br />亦不是："\0"或"\n"或" "，到现在本人仍不清楚结果是什么东东。<br /><br />坑 2：<br />对于十六进制，无法正常转换。<br /><br />坑 3：<br />对于待转换的内容中，含有非[0..9]与[.]的内容，则转一般都会出错。（甚者，可能会蹦）<img src ="http://www.cppblog.com/Tongy0/aggbug/206374.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2014-03-28 11:21 <a href="http://www.cppblog.com/Tongy0/archive/2014/03/28/206374.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转载】TinyXml创建XMl的两种方法，以及属性添加</title><link>http://www.cppblog.com/Tongy0/archive/2014/03/24/206315.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Mon, 24 Mar 2014 09:59:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2014/03/24/206315.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/206315.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2014/03/24/206315.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/206315.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/206315.html</trackback:ping><description><![CDATA[文章转自：http://blog.sina.com.cn/s/blog_69e905cd0100ks5v.html<br /><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->第一种方法:<br /><br />&nbsp;TiXmlDocument&nbsp;*pDoc=<span style="color: #0000FF; ">new</span>&nbsp;TiXmlDocument;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">定义一个文档的指针<br />&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">添加一个xml头。</span><span style="color: #008000; "><br /></span>&nbsp;TiXmlDeclaration&nbsp;*pDeclaration=<span style="color: #0000FF; ">new</span>&nbsp;TiXmlDeclaration("1.0","UTF-8","");<br />&nbsp;pDoc-&gt;LinkEndChild(pDeclaration);<br />&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">添加XMl的根节点</span><span style="color: #008000; "><br /></span>&nbsp;TiXmlElement&nbsp;*lengquan=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;TiXmlElement("lengquan");<br />&nbsp;pDoc-&gt;LinkEndChild(lengquan);<br />&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">添加一个父节点</span><span style="color: #008000; "><br /></span>&nbsp;TiXmlNode&nbsp;*parent=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;TiXmlElement("qiu");<br />&nbsp;TiXmlNode*&nbsp;name4NewNode&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;TiXmlElement("name");<br />&nbsp;parent-&gt;InsertEndChild(*name4NewNode)-&gt;InsertEndChild(TiXmlText("pipi"));&nbsp;<br />&nbsp;TiXmlNode*&nbsp;addr4NewNode&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;TiXmlElement("addr");<br />&nbsp;parent-&gt;InsertEndChild(*addr4NewNode)-&gt;InsertEndChild(TiXmlText("Shaanxi&nbsp;Xianyang"));<br />&nbsp;TiXmlNode*&nbsp;tel4NewNode&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;TiXmlElement("tel");<br />&nbsp;parent-&gt;InsertEndChild(*tel4NewNode)-&gt;InsertEndChild(TiXmlText("02937310627"));<br />&nbsp;TiXmlNode*&nbsp;email4NewNode&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;TiXmlElement("email");<br />&nbsp;parent-&gt;InsertEndChild(*email4NewNode)-&gt;InsertEndChild(TiXmlText(lengshijie@163.com));<br />&nbsp;lengquan-&gt;InsertEndChild(*parent);&nbsp;&nbsp;&nbsp;<br /><br /><br />&nbsp;pDoc-&gt;SaveFile("lengquan.xml");<br /><br />第二种方法：<br /><br /><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO:&nbsp;Add&nbsp;your&nbsp;control&nbsp;notification&nbsp;handler&nbsp;code&nbsp;here</span><span style="color: #008000; "><br /></span>&nbsp;TiXmlDocument&nbsp;*pDoc=<span style="color: #0000FF; ">new</span>&nbsp;TiXmlDocument;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">定义一个文档的指针<br />&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">添加一个xml头。</span><span style="color: #008000; "><br /></span>&nbsp;TiXmlDeclaration&nbsp;*pDeclaration=<span style="color: #0000FF; ">new</span>&nbsp;TiXmlDeclaration("1.0","UTF-8","");<br />&nbsp;pDoc-&gt;LinkEndChild(pDeclaration);<br />&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">添加XMl的根节点</span><span style="color: #008000; "><br /></span>&nbsp;TiXmlElement&nbsp;*lengquan=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;TiXmlElement("lengquan");<br />&nbsp;pDoc-&gt;LinkEndChild(lengquan);<br />&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">添加xml父节点，其实父节点跟子节点一样，这里为了我自己明白的更清楚一点，所以我自己称根节点的下一结点为父节点。</span><span style="color: #008000; "><br /></span>&nbsp;TiXmlElement&nbsp;*parent=<span style="color: #0000FF; ">new</span>&nbsp;TiXmlElement("qiu");<br />&nbsp;lengquan-&gt;LinkEndChild(parent);<br />&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">添加属性</span><span style="color: #008000; "><br /></span>&nbsp;parent-&gt;SetAttribute("time","12:10");<br /><br />&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">添加子节点。</span><span style="color: #008000; "><br /></span>&nbsp;TiXmlElement&nbsp;*name4NewNode=<span style="color: #0000FF; ">new</span>&nbsp;TiXmlElement("name");<br />&nbsp;parent-&gt;LinkEndChild(name4NewNode);<br />&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">添加节点下文本</span><span style="color: #008000; "><br /></span>&nbsp;CString&nbsp;strName="pipi";<br />&nbsp;TiXmlText&nbsp;*pNameValue=<span style="color: #0000FF; ">new</span>&nbsp;TiXmlText(strName);<br />&nbsp;name4NewNode-&gt;LinkEndChild(pNameValue);<br />&nbsp;<br />&nbsp;<span style="color: #008000; ">//<br /></span>&nbsp;TiXmlElement*&nbsp;addr4NewNode=<span style="color: #0000FF; ">new</span>&nbsp;TiXmlElement("addr");<br />&nbsp;parent-&gt;LinkEndChild(addr4NewNode);<br /><br />&nbsp;CString&nbsp;strAddr="Shaanxi&nbsp;Xianyang";<br />&nbsp;TiXmlText&nbsp;*pAddrValue=<span style="color: #0000FF; ">new</span>&nbsp;TiXmlText(strAddr);<br />&nbsp;parent-&gt;LinkEndChild(pAddrValue);<br />&nbsp;<span style="color: #008000; ">//<br /></span>&nbsp;TiXmlElement*&nbsp;tel4NewNode=<span style="color: #0000FF; ">new</span>&nbsp;TiXmlElement("tel");<br />&nbsp;parent-&gt;LinkEndChild(tel4NewNode);<br /><br />&nbsp;CString&nbsp;strTel="02937310627";<br />&nbsp;TiXmlText&nbsp;*pTelValue=<span style="color: #0000FF; ">new</span>&nbsp;TiXmlText(strTel);<br />&nbsp;parent-&gt;LinkEndChild(pTelValue);<br /><br />&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">保存</span><span style="color: #008000; "><br /></span>&nbsp;pDoc-&gt;SaveFile("lengquan1.xml");<br /><br />&nbsp;<br /><br />相对而言我更趋向于第二种写法。</div><img src ="http://www.cppblog.com/Tongy0/aggbug/206315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2014-03-24 17:59 <a href="http://www.cppblog.com/Tongy0/archive/2014/03/24/206315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转载】彻底搞懂字符编码(unicode,mbcs,utf-8,utf-16,utf-32,big endian,little endian...)</title><link>http://www.cppblog.com/Tongy0/archive/2013/12/26/205021.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Thu, 26 Dec 2013 10:57:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2013/12/26/205021.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/205021.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2013/12/26/205021.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/205021.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/205021.html</trackback:ping><description><![CDATA[<div>原谅转自：<br /><br />该文章介绍的不错，值得收藏。<br /><br />
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">最近有一些朋友常问我一些乱码的问题，和他们交流过程中，发现这个编码的相关知识还真是杂乱不堪，不少人对一些</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">知识理解似乎也有些偏差，网上百度,google的内容，也有不少以讹传讹，根本就是错误的（例如说 unicode编码是两</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">个字节），各种软件让你选择编码的时候，常常是很长的一个选单，让用户不知道该如何选。基于这样的问题，我就写</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">下我的理解吧，一方面帮助一些需要帮助的人纠正认识，一方面作为自己以后备查的资料。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">1.ASCII(American Standard Code for Information Interchange)<br />&nbsp; 美国信息交换标准代码，这是计算机上最早使用的通用的编码方案。那个时候计算机还只是拉丁文字的专利，根本没</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">有想到现在计算机的发展势头，如果想到了，可能一开始就会使用unicode了。当时绝大部分专家都认为，要用计算机</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">，必须熟练掌握英文。这种编码占用7个Bit，在计算机中占用一个字节，8位，最高位没用，通讯的时候有时用作奇偶</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">校验位。因此ASCII编码的取值范围实际上是：0x00-0x7f,只能表示128个字符。后来发现128个不太够用，做了扩展，</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">叫做ASCII扩展编码，用足八位，取值范围变成：0x00-0xff,能表示256个字符。其实这种扩展意义不大，因为256个字</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">符表示一些非拉丁文字远远不够，但是表示拉丁文字，又用不完。所以扩展的意义还是为了下面的ANSI编码服务。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">2.ANSI（American National Standard Institite ）<br />&nbsp; 美国国家标准协会，也就是说，每个国家（非拉丁语系国家）自己制定自己的文字的编码规则，并得到了ANSI认可，</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">符合ANSI的标准，全世界在表示对应国家文字的时候都通用这种编码就叫ANSI编码。换句话说，中国的ANSI编码和在日</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">本的ANSI的意思是不一样的，因为都代表自己国家的文字编码标准。比如中国的ANSI对应就是GB2312标准，日本就是</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">JIT标准，香港，台湾对应的是BIG5标准等等。当然这个问题也比较复杂，微软从95开始，用就是自己搞的一个标准GBK</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">。GB2312里面只有6763个汉字，682个符号，所以确实有时候不是很够用。GBK一直能和GB2312相互混淆并且相安无事的<br />一个重要原因是GBK全面兼容GB2312，所以没有出现任何冲突，你用GB2312编码的文件通过GBK去解释一定能获得相同的</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">显示效果，换句话说：GBK对GB2312就是，你有的，我也有，你没得的，我还有！</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><br />好了，ANSI的标准是什么呢，首先是ASCII的代码你不能用！也就是说ASCII码在任何ANSI中应该都是相同的。其他的，</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">你们自己扩展。所以呢，中国人就把ASCII码变成8位，0x7f之前我不动你的，我从0xa0开始编，0xa0到0xff才95个码位</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">，对于中国字那简直是杯水车薪，因此，就用两个字节吧，因此编码范围就从0xA1A1 - 0xFEFE，这个范围可以表示</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">23901个汉字。基本够用了吧，GB2312才7000多个呢！GBK更猛，编码范围是从0x8140 - 0xFEFE,可以表示3万多个汉字</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">。可以看出，这两种方案，都能保证汉字头一个字节在0x7f以上，从而和ASCII不会发生冲突。能够实现英文和汉字同</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">时显示。<br />BIG5，香港和台湾用的比较多，繁体，范围： 0xA140 - 0xF9FE, 0xA1A1 - 0xF9FE，每个字由两个字节组成，其第一</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">字节编码范围为0xA1~0xF9，第二字节编码范围为0x40-0x7E与0xA1-0xFE，总计收入13868个字 (包括5401个常用字、</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">7652 个次常用字、7个扩充字、以及808个各式符号)。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><br />那么到底ANSI是多少位呢？这个不一定！比如在GB2312和GBK，BIG5中，是两位！但是其他标准或者其他语言如果不够</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">用，就完全可能不止两位！</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">例如：GB18030:<br />GB18030-2000(GBK2K)在GBK的基础上进一步扩展了汉字，增加了藏、蒙等少数民族的字形。GBK2K从根本上解决了字位</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">不够，字形不足的问题。它有几个特点：它并没有确定所有的字形，只是规定了编码范围，留待以后扩充。<br />编码是变长的，其二字节部分与GBK兼容；四字节部分是扩充的字形、字位，其编码范围是首字节0x81-0xfe、二字节</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">0x30-0x39、三字节0x81-0xfe、四字节0x30-0x39。它的推广是分阶段的，首先要求实现的是能够完全映射到</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Unicode3.0标准的所有字形。它是国家标准，是强制性的。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">搞懂了ANSI的含义，我们发现ANSI有个致命的缺陷，就是每个标准是各自为阵的，不保证能兼容。换句话说，要同时显</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">示中文和日本文或者阿拉伯文，就完全可能会出现一个编码两个字符集里面都有对应，不知道该显示哪一个的问题，也</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">就是编码重叠的问题。显然这样的方案不好，所以Unicode才会出现！</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">3.MBCS（Multi-Byte Chactacter System（Set)）<br />&nbsp; 多字节字符系统或者字符集，基于ANSI编码的原理上，对一个字符的表示实际上无法确定他需要占用几个字节的，只</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">能从编码本身来区分和解释。因此计算机在存储的时候，就是采用多字节存储的形式。也就是你需要几个字节我给你放</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">几个字节，比如A我给你放一个字节，比如"中&#8220;，我就给你放两个字节，这样的字符表示形式就是MBCS。<br />在基于GBK的windows中，不会超过2个字节，所以windows这种表示形式有叫做DBCS（Double-Byte Chactacter System</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">），其实算是MBCS的一个特例。<br />C语言默认存放字符串就是用的MBCS格式。从原理上来说，这样是非常经济的一种方式。<br />4.CodePage<br />&nbsp;<span class="Apple-converted-space">&nbsp;</span><br />代码页，最早来自IBM，后来被微软，oracle ,SAP等广泛采用。因为ANSI编码每个国家都不统一，不兼容，可能导致冲</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">突，所以一个系统在处理文字的时候，必须要告诉计算机你的ANSI是哪个国家和地区的标准，这种国家和标准的代号（</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">其实就是字符编码格式的代号），微软称为Codepage代码页，其实这个代码页和字符集编码的意思是一样的。告诉你代</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">码页，本质就是告诉了你编码格式。<br />但是不同厂家的代码页可能是完全不同，哪怕是同样的编码，比如， UTF-8字符编码 在IBM对应的代码页是1208，在微</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">软对应的是65001,在德国的SAP公司对应的是 4110 。所以啊，其实本来就是一个东西，大家各自为政，搞那么多新名</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">词，实在没必要！所以标准还是很重要的！！！<br />比如GBK的在微软的代码页是936，告诉你代码页是936其实和告诉你我编码格式是GBK效果完全相同。那么处理文本的时</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">候就不会有问题，不会去考虑某个代码是显示的韩文还是中文，同样，日文和韩文的代码页就和中文不同，这样就可以</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">避免编码冲突导致计算机不知如何处理的问题。当然用这个也可以很容易的切换语言版本。<br />但是这都是治标不治本的方法，还是无法解决同时显示多种语言的问题，所以最后还是都用unicode吧，永远不会有冲</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">突了。<br />5.Unicode(Universal Code)<br />&nbsp; 这是一个编码方案，说白了就是一张包含全世界所有文字的一个编码表，不管你用的上，用不上，不管是现在用的，</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">还是以前用过的，只要这个世界上存在的文字符号，统统给你一个唯一的编码，这样就不可能有任何冲突了。不管你要</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">同时显示任何文字，都没有问题。<br />&nbsp; 因此在这样的方案下，Unicode出现了。Unicode编码范围是：0-0x10FFFF，可以容纳1114112个字符，100多万啊。全</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">世界的字符根本用不完了，Unicode 5.0版本中，才用了238605个码位。所以足够了。<br />因此从码位范围看，严格的unicode需要3个字节来存储。但是考虑到理解性和计算机处理的方便性，理论上还是用4个</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">字节来描述。<br />&nbsp;&nbsp; Unicode采用的汉字相关编码用的是《CJK统一汉字编码字符集》&#8212; 国家标准 GB13000.1 是完全等同于国际标准《</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">通用多八位编码字符集 (UCS)》 ISO 10646.1。《GB13000.1》中最重要的也经常被采用的是其双字节形式的基本多文</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">种平面。在这65536个码位的空间中，定义了几乎所有国家或地区的语言文字和符号。其中从0x4E00到 0x9FA5 的连续</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">区域包含了 20902 个来自中国（包括台湾）、日本、韩国的汉字，称为 CJK (Chinese Japanese Korean) 汉字。CJK</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">是《GB2312-80》、《BIG5》等字符集的超集。<br />&nbsp; CJK包含了中国，日本，韩国，越南，香港，也就是CJKVH。这个在UNICODE的Charset chart中可以明显看到。<br />&nbsp; unicode的相关标准可以从unicode.org上面获得，目前已经进行到了6.0版本。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">下面这段描述来自百度百科：<br />&nbsp;&nbsp; Unicode字符集可以简写为UCS（Unicode Character Set）。早期的&nbsp; unicodeUnicode标准有UCS-2、UCS-4的说法。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">UCS-2用两个字节编码，UCS-4用4个字节编码。UCS-4根据最高位为0的最高字节分成2^7=128个group。每个group再根据</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">次高字节分为256个平面（plane）。每个平面根据第3个字节分为256行 （row），每行有256个码位（cell）。group 0</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">的平面0被称作BMP（Basic Multilingual Plane）。将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。 　　每个平</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">面有2^16=65536个码位。Unicode计划使用了17个平面，一共有17*65536=1114112个码位。在Unicode 5.0.0版本中，已</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">定义的码位只有238605个，分布在平面0、平面1、平面2、平面14、平面15、平面16。其中平面15和平面16上只是定义</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">了两个各占65534个码位的专用区（Private Use Area），分别是0xF0000-0xFFFFD和0x100000-0x10FFFD。所谓专用区</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">，就是保留给大家放自定义字符的区域，可以简写为PUA。 　　平面0也有一个专用区：0xE000-0xF8FF，有6400个码位</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">。平面0的0xD800-0xDFFF，共2048个码位，是一个被称作代理区（Surrogate）的特殊区域。代理区的目的用两个UTF-</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">16字符表示BMP以外的字符。在介绍UTF-16编码时会介绍。 　　如前所述在Unicode 5.0.0版本中，238605-65534*2-</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">6400-2408=99089。余下的99089个已定义码位分布在平面0、平面1、平面2和平面14上，它们对应着Unicode目前定义的</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">99089个字符，其中包括71226个汉字。平面0、平面1、平面2和平面14上分别定义了52080、3419、43253和337个字符。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">平面2的43253个字符都是汉字。平面0上定义了27973个汉字。<br />&nbsp;</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">6.Unicode的实现方案<br />&nbsp;&nbsp; Unicode其实只是一张巨大的编码表。要在计算机里面实现，也出现了几种不同的方案。也就是说如何表示unicode</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">编码的问题。<br />（1）UTF-8（UCS Transformation Format 8bit)<br />&nbsp;&nbsp;&nbsp; 这个方案的意思以8位为单位来标识文字，注意并不是说一个文字用8位标识。他其实是一种MBCS方案，可变字节的</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">。到底需要几个字节表示一个符号，这个要根据这个符号的unicode编码来决定，最多4个字节。<br />编码规则如下：<br />&nbsp;&nbsp; Unicode编码(16进制)　&#9553;　UTF-8 字节流(二进制) 　<br />　000000 - 00007F　&#9553;　0xxxxxxx 　　<br />000080 - 0007FF　&#9553;　110xxxxx 10xxxxxx 　　<br />000800 - 00FFFF　&#9553;　1110xxxx 10xxxxxx 10xxxxxx 　　<br />010000 - 10FFFF　&#9553;　11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 　　<br />UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符，UTF-8编码与ASCII编码完全相同。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">UTF-8编码的最大长度是4个字节。从上表可以看出，4字节模板有21个x，即可以容纳21位二进制数字。Unicode的最大</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">码位0x10FFFF也只有21位。 　　<br />例1：&#8220;汉&#8221;字的Unicode编码是0x6C49。0x6C49在0x0800-0xFFFF之间，使用用3字节模板了：1110xxxx 10xxxxxx</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">10xxxxxx。将0x6C49写成二进制是：0110 1100 0100 1001， 用这个比特流依次代替模板中的x，得到：11100110</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">10110001 10001001，即E6 B1 89。 　　<br />例2：Unicode编码0x20C30在0x010000-0x10FFFF之间，使用用4字节模板了：11110xxx 10xxxxxx 10xxxxxx 10xxxxxx。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">将0x20C30写成21位二进制数字（不足21位就在前面补0）：0 0010 0000 1100 0011 0000，用这个比特流依次代替模板</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">中的x，得到：11110000 10100000 10110000 10110000，即F0 A0 B0 B0。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">（2）UTF-16<br />&nbsp;UTF-16编码以16位无符号整数为单位。注意是16位为一个单位，不表示一个字符就只有16位。现在机器上的unicode编</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">码一般指的就是UTF-16。绝大部分2个字节就够了，但是不能绝对的说所有字符都是2个字节。这个要看字符的unicode</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">编码处于什么范围而定，有可能是2个字节，也可能是4个字节。这点请注意！<br />下面算法解释来自百度百科。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">我们把Unicode&nbsp; unicode编码记作U。编码规则如下：<span class="Apple-converted-space">&nbsp;</span><br />　　如果U&lt;0x10000，U的UTF-16编码就是U对应的16位无符号整数（为书写简便，下文将16位无符号整数记作WORD）。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">　　如果U&#8805;0x10000，我们先计算U'=U-0x10000，然后将U'写成二进制形式：yyyy yyyy yyxx xxxx xxxx，U的UTF-16</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">编码（二进制）就是：110110yyyyyyyyyy 110111xxxxxxxxxx。为什么U'可以被写成20个二进制位？Unicode的最大码位</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">是0x10ffff，减去0x10000后，U'的最大值是0xfffff，所以肯定可以用20个二进制位表示。<br />&nbsp;&nbsp;&nbsp; 例如：Unicode编码0x20C30，减去0x10000后，得到0x10C30，写成二进制是：0001 0000 1100 0011 0000。用前10</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">位依次替代模板中的y，用后10位依次替代模板中的x，就得到：1101100001000011 1101110000110000，即0xD843</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">0xDC30。 　　<br />&nbsp;&nbsp;&nbsp; 按照上述规则，Unicode编码0x10000-0x10FFFF的UTF-16编码有两个WORD，第一个WORD的高6位是110110，第二个</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">WORD的高6位是110111。可见，第一个WORD的取值范围（二进制）是11011000 00000000到11011011 11111111，即</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">0xD800-0xDBFF。第二个WORD的取值范围（二进制）是11011100 00000000到11011111 11111111，即0xDC00-0xDFFF。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">　　为了将一个WORD的UTF-16编码与两个WORD的UTF-16编码区分开来，Unicode编码的设计者将0xD800-0xDFFF保留下来</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">，并称为代理区（Surrogate）： 　　<br />D800－DB7F　&#9553;　High Surrogates　&#9553;　高位替代 　　<br />DB80－DBFF　&#9553;　High Private Use Surrogates　&#9553;　高位专用替代 　　<br />DC00－DFFF　&#9553;　Low Surrogates　&#9553;　低位替代 　　<br />&nbsp;&nbsp; 高位替代就是指这个范围的码位是两个WORD的UTF-16编码的第一个WORD。低位替代就是指这个范围的码位是两个</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">WORD的UTF-16编码的第二个WORD。那么，高位专用替代是什么意思？我们来解答这个问题，顺便看看怎么由UTF-16编码</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">推导Unicode编码。 　　<br />&nbsp; 如果一个字符的UTF-16编码的第一个WORD在0xDB80到0xDBFF之间，那么它的Unicode编码在什么范围内？我们知道第</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">二个WORD的取值范围是0xDC00-0xDFFF，所以这个字符的UTF-16编码范围应该是0xDB80 0xDC00到0xDBFF 0xDFFF。我们</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">将这个范围写成二进制： 　　1101101110000000 11011100 00000000 - 1101101111111111 1101111111111111 　　按</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">照编码的相反步骤，取出高低WORD的后10位，并拼在一起，得到 　　1110 0000 0000 0000 0000 - 1111 1111 1111</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">1111 1111&nbsp;<span class="Apple-converted-space">&nbsp;</span><br />即0xe0000-0xfffff，按照编码的相反步骤再加上0x10000，得到0xf0000-0x10ffff。这就是UTF-16编码的第一个WORD在</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">0xdb80到0xdbff之间的Unicode编码范围，即平面15和平面16。因为Unicode标准将平面15和平面16都作为专用区，所以</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">0xDB80到0xDBFF之间的保留码位被称作高位专用替代。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">（3）UTF-32<br />&nbsp;这个就简单了，和Unicode码表基本一一对应，固定四个字节。<br />&nbsp;为什么不采用UTF-32呢，因为unicode定义的范围太大了，其实99%的人使用的字符编码不会超过2个字节，所以如同统</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">一用4个字节，简单倒是简单了，但是数据冗余确实太大了，不好，所以16位是最好的。就算遇到超过16位能表示的字</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">符，我们也可以通过上面讲到的代理技术，采用32位标识，这样的方案是最好的。所以现在绝大部分机器实现unicode</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">还是采用的utf-16的方案。当然也有UTF-8的方案。比如windows用的就是UTF16方案，不少linux用的就是utf8方案。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">7. 编码存储差异</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">这里就要引出两个名词：<br />LE（little endian):小字节字节序，意思就是一个单元在计算机中的存放时按照低位在前（低地址），高位在后（高</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">地址）的模式存放。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">BE（big endian):大字节字节序，和LE相反，是高位在前，低位在后。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">比如一个unicode编码为：0x006C49，如果是LE，那么在文件中的存放顺序应该是：49 6c 00<br />如果是BE ,那么顺序应该是：00 6c 49</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">8.编码格式的检测</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">到底采用什么编码，如果能检测就好了。专家们也是这么想的，所以专家给每种格式和字节序规定了一些特殊的编码，</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">这些编码在unicode 中是没有使用的，所以不用担心会冲突。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">这个叫做BOM（Byte Order Mark）头。意思是字节序标志头。通过它基本能确定编码格式和字节序。<br />UTF编码　&#9553;　Byte Order Mark 　　<br />UTF-8　&nbsp; &#9553;　EF BB BF 　　<br />UTF-16LE &#9553;　FF FE 　　<br />UTF-16BE &#9553;　FE FF 　　<br />UTF-32LE &#9553;　FF FE 00 00 　　<br />UTF-32BE &#9553;　00 00 FE FF<br />所以通过检测文件前面的BOM头，基本能确定编码格式和字节序。<br />但是这个BOM头只是建议添加，不是强制的，所以不少软件和系统没有添加这个BOM头（所以有些软件格式中有带BOM头</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">和NoBOM头的选择），这个时候要检测什么格式，就比较麻烦了<br />当然可以检测，但是不能保证100%准确，只能通过编码范围从概率上来检查，虽然准确度还是比较高，但是不能保证</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">100%。所以，时常看到检测错误的软件，也不奇怪了。</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">总结：<br />&nbsp;&nbsp; 终于写完了，其实这些问题都是不统一导致的，属于历史问题，所以才会有这些困惑，这里也呼吁所有的软件 开发</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">人员自觉的采用Unicode标准进行文字处理，我相信在不久的将来，这些困扰都不会存在了，因为所有软件都是unicode</p>
<p style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/26px Arial; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">d ,只要有字库，任何文字都能同时显示，也可以到任何语言的平台上的去运行，不再有乱码的困惑！<br />&nbsp; 其实现在绝大部分软件已经是这么做的了！<br />&nbsp;&nbsp; 另外也不要被很多名词属于所迷惑，其实这些只是标准的问题，根本没有什么新的东西，更没有什么复杂的东西。</p></div><img src ="http://www.cppblog.com/Tongy0/aggbug/205021.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2013-12-26 18:57 <a href="http://www.cppblog.com/Tongy0/archive/2013/12/26/205021.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转载】Win7 下Android NDK + Cygwin环境配置</title><link>http://www.cppblog.com/Tongy0/archive/2013/12/23/204965.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Mon, 23 Dec 2013 08:10:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2013/12/23/204965.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/204965.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2013/12/23/204965.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/204965.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/204965.html</trackback:ping><description><![CDATA[<div>原谅转载自：<a href="http://woniu1983.iteye.com/blog/1895724">http://woniu1983.iteye.com/blog/1895724</a><br /><br />
<div style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; font: 12px/18px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; margin-bottom: 15px; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="blog_title">
<h3 style="padding-bottom: 0px; line-height: 1.5em; margin: 0px 0px 0.5em; padding-left: 0px; padding-right: 0px; color: black; font-size: 16px; padding-top: 10px"><a style="color: rgb(16,138,198); text-decoration: underline" href="http://woniu1983.iteye.com/blog/1895724">Win7 下Android NDK + Cygwin环境配置</a><em style="font-style: italic" class="actions"></em></h3>
<ul style="padding-bottom: 0px; list-style-type: none; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" class="blog_categories"><strong style="font-weight: bold">博客分类：</strong><span class="Apple-converted-space">&nbsp;</span><li style="padding-bottom: 0px; list-style-type: none; margin: 0px 5px 0px 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px"><a style="color: rgb(16,138,198); text-decoration: underline" href="http://woniu1983.iteye.com/category/140063">Android</a></li></ul>
<div style="line-height: 20px; margin: 10px 0px 5px; display: block; clear: both" class="news_tag">&nbsp;</div></div>
<div style="text-align: left; widows: 2; text-transform: none; text-indent: 0px; font: 14px/1.8em Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" id="blog_content" class="blog_content">之前一直尝试配置Ubuntu下的环境的，我的Ubuntu12.04是VirtualBox虚拟机下的，整了半天，其他都好了，就是Eclipse下面安装ADT的时候，发现Eclipse连不上网络，查过代理等都没问题，于是本地安装ADT，结果又是和网络上的一样的一堆错误。 时间关系没有整到底，于是还是使用大家通行的Cygwin来吧。<span class="Apple-converted-space">&nbsp;</span><br /><br />巴拉巴拉的介绍就不说了，直接记录步骤吧。<span class="Apple-converted-space">&nbsp;</span><br /><br /><br /><br />1. Android NDK下载<span class="Apple-converted-space">&nbsp;</span><br />&nbsp; 下载Windows系统下的版本，至于32位还是64位由你机器而定，我的是Win7 32位，下载的是：android-ndk-r8e-windows-x86.zip<span class="Apple-converted-space">&nbsp;</span><br />&nbsp; 电梯直达：<a style="color: rgb(16,138,198); text-decoration: underline" href="http://developer.android.com/tools/sdk/ndk/index.html#Installing" target="_blank">http://developer.android.com/tools/sdk/ndk/index.html#Installing</a><span class="Apple-converted-space">&nbsp;</span><br />&nbsp;<span class="Apple-converted-space">&nbsp;</span><br /><br />2. Cygwin下载<span class="Apple-converted-space">&nbsp;</span><br />&nbsp; 下载Setup.exe<span class="Apple-converted-space">&nbsp;</span><br />&nbsp; 电梯直达：<a style="color: rgb(16,138,198); text-decoration: underline" href="http://cygwin.com/install.html" target="_blank">http://cygwin.com/install.html</a><span class="Apple-converted-space">&nbsp;</span><br /><br />3. 安装 Android NDK<span class="Apple-converted-space">&nbsp;</span><br />&nbsp;&nbsp; 解压缩到某个目录即可，例如我的： E:\DevelopEnviroment\Android\<span class="Apple-converted-space">&nbsp;</span><br />&nbsp;&nbsp; 解压缩后的文件夹名字如下：android-ndk-r8e<span class="Apple-converted-space">&nbsp;</span><br /><br />4. 安装Cygwin<span class="Apple-converted-space">&nbsp;</span><br />&nbsp;&nbsp; 运行Setup.exe,如下图片是转载自别人的（请见参考Link）<span class="Apple-converted-space">&nbsp;<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/tongy0/001.jpg" width="546" longdesc="" height="393" /><br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/tongy0/002.jpg" width="546" longdesc="" height="393" /><br /></span></div><br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/tongy0/003.jpg" width="546" longdesc="" height="393" /><br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/tongy0/004.jpg" width="546" longdesc="" height="393" /><br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/tongy0/005.jpg" width="463" longdesc="" height="686" /><br /><br /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">5. 运行下Cygwin<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 第一次运行后，会为你创建当前的用户包括一些环境文件(类似于Linux下的bash文件等等)，下一步我们会修改其中的文件<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">6. 配置NDK环境变量<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; .cygwin的安装目录，找到一个home\&lt;你的用户名&gt;\.bash_profile文件末尾添加如下：<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp;&nbsp; 其中&#8220;e/DevelopEnviroment/Android/android-ndk-r8e<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&#8221;是表示Android NDK是安装在E:/DevelopEnviroment/Android/android-ndk-r8e<span class="Apple-converted-space">&nbsp;</span></span><br />
<div style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 12px/25px Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', Consolas, 'Courier New', monospace; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="bar">
<div style="text-align: left; padding-bottom: 3px; margin: 0px; padding-left: 3px; padding-right: 3px; color: black; font-weight: bold; padding-top: 3px" class="tools">Shell代码<span class="Apple-converted-space">&nbsp;</span><embed height="15" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" width="14" src="http://woniu1983.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" wmode="transparent" flashvars="clipboard=ANDK%3D%2Fcygdrive%2Fe%2FDevelopEnviroment%2FAndroid%2Fandroid-ndk-r8e%0Aexport%20ANDK" quality="high" allowscriptaccess="always">&nbsp;<a style="color: rgb(16,138,198); text-decoration: underline" title="收藏这段代码" onclick="code_favorites_do_favorite(this);return false;" href="javascript:void()"><img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" class="star" alt="收藏代码" src="http://woniu1983.iteye.com/images/icon_star.png" /></a></div></div>
<ol style="border-bottom: rgb(209,215,220) 1px solid; text-align: left; border-left: rgb(209,215,220) 1px solid; padding-bottom: 2px; widows: 2; text-transform: none; background-color: rgb(255,255,255); list-style-type: decimal; text-indent: 0px; margin: 0px 0px 1px; padding-left: 0px; padding-right: 0px; font: 12px/1.4em Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', Consolas, 'Courier New', monospace; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(43,145,175); border-top: rgb(209,215,220) 1px solid; border-right: rgb(209,215,220) 1px solid; word-spacing: 0px; padding-top: 2px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="dp-default"><li style="border-left: rgb(209,215,220) 1px solid; padding-bottom: 0px; line-height: 18px; background-color: rgb(250,250,250); margin: 0px 0px 0px 38px; padding-left: 10px; padding-right: 0px; font-size: 1em; padding-top: 0px"><span style="color: black"><span style="color: black">ANDK=/cygdrive/e/DevelopEnviroment/Android/android-ndk-r8e&nbsp;&nbsp;</span></span></li><li style="border-left: rgb(209,215,220) 1px solid; padding-bottom: 0px; line-height: 18px; background-color: rgb(250,250,250); margin: 0px 0px 0px 38px; padding-left: 10px; padding-right: 0px; font-size: 1em; padding-top: 0px"><span style="color: black">export&nbsp;ANDK&nbsp;&nbsp;</span></li></ol>
<ol style="border-bottom: rgb(209,215,220) 1px solid; text-align: left; border-left: rgb(209,215,220) 1px solid; padding-bottom: 2px; widows: 2; text-transform: none; background-color: rgb(255,255,255); list-style-type: decimal; text-indent: 0px; margin: 0px 0px 1px; padding-left: 0px; padding-right: 0px; font: 12px/1.4em Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', Consolas, 'Courier New', monospace; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(43,145,175); border-top: rgb(209,215,220) 1px solid; border-right: rgb(209,215,220) 1px solid; word-spacing: 0px; padding-top: 2px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="dp-default"></ol>
<ol style="border-bottom: rgb(209,215,220) 1px solid; text-align: left; border-left: rgb(209,215,220) 1px solid; padding-bottom: 2px; widows: 2; text-transform: none; background-color: rgb(255,255,255); list-style-type: decimal; text-indent: 0px; margin: 0px 0px 1px; padding-left: 0px; padding-right: 0px; font: 12px/1.4em Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', Consolas, 'Courier New', monospace; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(43,145,175); border-top: rgb(209,215,220) 1px solid; border-right: rgb(209,215,220) 1px solid; word-spacing: 0px; padding-top: 2px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="dp-default"><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">7. 测试NDK环境<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 输入 cd $ANDK, 进入/cygdrive/e/DevelopEnviroment/Android/android-ndk-r8e<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 进入/samples/hello-jni项目下，运行$ANDK/ndk-build<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 输出效果如下：<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" />
<div style="text-align: left; padding-bottom: 1px; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; padding-left: 1px; width: 679px; padding-right: 1px; font: 12px/25px Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', Consolas, 'Courier New', monospace; word-wrap: break-word; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); margin-left: 9px; overflow: auto; word-break: break-all; word-spacing: 0px; padding-top: 1px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="dp-highlighter">
<div class="bar">
<div style="text-align: left; padding-bottom: 3px; margin: 0px; padding-left: 3px; padding-right: 3px; color: black; font-weight: bold; padding-top: 3px" class="tools">Output代码<span class="Apple-converted-space">&nbsp;</span><embed height="15" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" width="14" src="http://woniu1983.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" wmode="transparent" flashvars="clipboard=%24%20%24ANDK%2Fndk-build%0AGdbserver%20%20%20%20%20%20%3A%20%5Barm-linux-androideabi-4.6%5D%20libs%2Farmeabi%2Fgdbserver%0AGdbsetup%20%20%20%20%20%20%20%3A%20libs%2Farmeabi%2Fgdb.setup%0AInstall%20%20%20%20%20%20%20%20%3A%20libhello-jni.so%20%3D%3E%20libs%2Farmeabi%2Flibhello-jni.so" quality="high" allowscriptaccess="always">&nbsp;<a style="color: rgb(16,138,198); text-decoration: underline" title="收藏这段代码" onclick="code_favorites_do_favorite(this);return false;" href="javascript:void()"><img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" class="star" alt="收藏代码" src="http://woniu1983.iteye.com/images/icon_star.png" /></a></div></div>
<ol style="border-bottom: rgb(209,215,220) 1px solid; border-left: rgb(209,215,220) 1px solid; padding-bottom: 2px; line-height: 1.4em; background-color: rgb(255,255,255); list-style-type: decimal; margin: 0px 0px 1px; padding-left: 0px; padding-right: 0px; color: rgb(43,145,175); font-size: 1em; border-top: rgb(209,215,220) 1px solid; border-right: rgb(209,215,220) 1px solid; padding-top: 2px" class="dp-default"><li style="border-left: rgb(209,215,220) 1px solid; padding-bottom: 0px; line-height: 18px; background-color: rgb(250,250,250); margin: 0px 0px 0px 38px; padding-left: 10px; padding-right: 0px; font-size: 1em; padding-top: 0px"><span style="color: black"><span style="color: black">$&nbsp;$ANDK/ndk-build&nbsp;&nbsp;</span></span></li><li style="border-left: rgb(209,215,220) 1px solid; padding-bottom: 0px; line-height: 18px; background-color: rgb(250,250,250); margin: 0px 0px 0px 38px; padding-left: 10px; padding-right: 0px; font-size: 1em; padding-top: 0px"><span style="color: black">Gdbserver&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;[arm-linux-androideabi-<span style="color: rgb(192,0,0)" class="number">4.6</span><span style="color: black">]&nbsp;libs/armeabi/gdbserver&nbsp;&nbsp;</span></span></li><li style="border-left: rgb(209,215,220) 1px solid; padding-bottom: 0px; line-height: 18px; background-color: rgb(250,250,250); margin: 0px 0px 0px 38px; padding-left: 10px; padding-right: 0px; font-size: 1em; padding-top: 0px"><span style="color: black">Gdbsetup&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;libs/armeabi/gdb.setup&nbsp;&nbsp;</span></li><li style="border-left: rgb(209,215,220) 1px solid; padding-bottom: 0px; line-height: 18px; background-color: rgb(250,250,250); margin: 0px 0px 0px 38px; padding-left: 10px; padding-right: 0px; font-size: 1em; padding-top: 0px"><span style="color: black">Install&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;libhello-jni.so&nbsp;=&gt;&nbsp;libs/armeabi/libhello-jni.so&nbsp;&nbsp;</span></li></ol></div><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;&nbsp; 以上即表明安装完毕。<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&nbsp;<span class="Apple-converted-space">&nbsp;</span></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">参考Link：<span class="Apple-converted-space">&nbsp;</span></span><a style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(16,138,198); word-spacing: 0px; text-decoration: underline; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" href="http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece7631046893b4c4380146d96864968d4e414c42246121b30a8e16071405f8f90613441e9120db4a72b24604573ecc589954fdbb0922d288f33712d5cd04e418f4fef961d73d620e106bff60ee7cbe74290b9a5d1c82253dd24756d8081c3045b44&amp;p=c2769a4786cc42a858b1d22454078b&amp;newp=927f861a85cc43ff57ee937e4e55a5231610db2151d4db15&amp;user=baidu&amp;fm=sc&amp;query=Android+NDK+%B1%E0%D2%EB+zlib&amp;qid=&amp;p1=7" target="_blank">http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece7631046893b4c4380146d96864968d4e414c42246121b30a8e16071405f8f90613441e9120db4a72b24604573ecc589954fdbb0922d288f33712d5cd04e418f4fef961d73d620e106bff60ee7cbe74290b9a5d1c82253dd24756d8081c3045b44&amp;p=c2769a4786cc42a858b1d22454078b&amp;newp=927f861a85cc43ff57ee937e4e55a5231610db2151d4db15&amp;user=baidu&amp;fm=sc&amp;query=Android+NDK+%B1%E0%D2%EB+zlib&amp;qid=&amp;p1=7</a><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; display: inline !important; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"></span><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><br style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" /><a style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; font: 14px/25px Helvetica, Tahoma, Arial, sans-serif; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(16,138,198); word-spacing: 0px; text-decoration: underline; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" href="http://wenku.baidu.com/view/63039e8071fe910ef12df86b.html" target="_blank">http://wenku.baidu.com/view/63039e8071fe910ef12df86b.html</a></ol></div><img src ="http://www.cppblog.com/Tongy0/aggbug/204965.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2013-12-23 16:10 <a href="http://www.cppblog.com/Tongy0/archive/2013/12/23/204965.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++ 逗号表达式(Note002)</title><link>http://www.cppblog.com/Tongy0/archive/2013/11/25/204439.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Mon, 25 Nov 2013 13:00:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2013/11/25/204439.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/204439.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2013/11/25/204439.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/204439.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/204439.html</trackback:ping><description><![CDATA[一个包含逗号的表达式首先计算逗号左边的表达式，然后计算逗<br />号右边的表达式；整个表达式的结果是逗号右边表达式的值。所以对于表达式：++i, --j;<br />编译器首先计算++i，然后是--j，逗号表达式的结果是--j。<img src ="http://www.cppblog.com/Tongy0/aggbug/204439.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2013-11-25 21:00 <a href="http://www.cppblog.com/Tongy0/archive/2013/11/25/204439.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++increment与decrement详解(Note001)</title><link>http://www.cppblog.com/Tongy0/archive/2013/11/25/204438.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Mon, 25 Nov 2013 12:50:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2013/11/25/204438.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/204438.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2013/11/25/204438.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/204438.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/204438.html</trackback:ping><description><![CDATA[1) 不论是 increment 或 decrement 的前缀还是后缀都只有一个参数。为了解决这个语言问题，C++<br />规定后缀形式有一个 int 类型参数，当函数被调用时，编译器传递一个 0 做为 int 参数的值<br />给该函数(即：decrement函数)。示例如下：
<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"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000">/*</span><span style="color: #008000">*****************************************************************************<br />@-Author&nbsp;&nbsp;:&nbsp;Jacc.Kim<br />@-create&nbsp;&nbsp;:&nbsp;[11-25-2013&nbsp;20:33:55]<br />@-summary&nbsp;:&nbsp;c++的increment与decrement学习<br />@-modified:&nbsp;<br />*****************************************************************************</span><span style="color: #008000">*/</span><span style="color: #000000"><br /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;UPInt<br />{<br /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">/*</span><span style="color: #008000">*************************************************************************<br />&nbsp;&nbsp;&nbsp;&nbsp;@-summary&nbsp;:&nbsp;++&nbsp;前递增操作符重载<br />&nbsp;&nbsp;&nbsp;&nbsp;@-in&nbsp;param:&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;@-return&nbsp;&nbsp;:&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;@-!!!note&nbsp;:&nbsp;1)&nbsp;该函数返回的是当前对象自增后的引用。一定注意：是引用。<br />&nbsp;&nbsp;&nbsp;&nbsp;@-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2)&nbsp;该函数没有输入参数<br />&nbsp;&nbsp;&nbsp;&nbsp;@-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3)&nbsp;下面的&nbsp;--&nbsp;前递减操作符重载类似<br />&nbsp;&nbsp;&nbsp;&nbsp;*************************************************************************</span><span style="color: #008000">*/</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;UPInt&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #0000ff">operator</span><span style="color: #000000">++</span><span style="color: #000000">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;处理递增操作<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;some&nbsp;code&nbsp;here&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"  alt="" /><img src="http://www.cppblog.com/Images/dot.gif"  alt="" />..<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;返回自身实例</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #0000ff">this</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">/*</span><span style="color: #008000">*************************************************************************<br />&nbsp;&nbsp;&nbsp;&nbsp;@-summary&nbsp;:&nbsp;++&nbsp;后递增操作符重载<br />&nbsp;&nbsp;&nbsp;&nbsp;@-in&nbsp;param:&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;@-return&nbsp;&nbsp;:&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;@-!!!note&nbsp;:&nbsp;1)&nbsp;该函数返回的是当前对象自增前的一个const副本。一定注意：是const副本。<br />&nbsp;&nbsp;&nbsp;&nbsp;@-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2)&nbsp;该函数接受一个int型参数，但实际上，该参数是没有任何作用的。<br />&nbsp;&nbsp;&nbsp;&nbsp;@-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3)&nbsp;下面的&nbsp;--&nbsp;后递减操作符重载类似<br />&nbsp;&nbsp;&nbsp;&nbsp;*************************************************************************</span><span style="color: #008000">*/</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;UPInt&nbsp;</span><span style="color: #0000ff">operator</span><span style="color: #000000">++</span><span style="color: #000000">(</span><span style="color: #0000ff">int</span><span style="color: #000000">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UPInt&nbsp;retObj&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #0000ff">this</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">++</span><span style="color: #000000">(</span><span style="color: #000000">*</span><span style="color: #0000ff">this</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;retObj;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">/*</span><span style="color: #008000">*************************************************************************<br />&nbsp;&nbsp;&nbsp;&nbsp;@-summary&nbsp;:&nbsp;--&nbsp;前递增操作符重载<br />&nbsp;&nbsp;&nbsp;&nbsp;@-in&nbsp;param:&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;@-return&nbsp;&nbsp;:&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;@-!!!note&nbsp;:&nbsp;1)&nbsp;该函数返回的是当前对象自减前的引用。一定注意：是引用。<br />&nbsp;&nbsp;&nbsp;&nbsp;@-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2)&nbsp;该函数没有输入参数<br />&nbsp;&nbsp;&nbsp;&nbsp;*************************************************************************</span><span style="color: #008000">*/</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;UPInt&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #0000ff">operator</span><span style="color: #000000">--</span><span style="color: #000000">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;处理递减操作<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;some&nbsp;code&nbsp;here&nbsp;<img src="http://www.cppblog.com/Images/dot.gif"  alt="" /><img src="http://www.cppblog.com/Images/dot.gif"  alt="" />..<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;返回自身实例</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #0000ff">this</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">/*</span><span style="color: #008000">*************************************************************************<br />&nbsp;&nbsp;&nbsp;&nbsp;@-summary&nbsp;:&nbsp;++&nbsp;后递减操作符重载<br />&nbsp;&nbsp;&nbsp;&nbsp;@-in&nbsp;param:&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;@-return&nbsp;&nbsp;:&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;@-!!!note&nbsp;:&nbsp;1)&nbsp;该函数返回的是当前对象自减前的一个const副本。一定注意：是const副本。<br />&nbsp;&nbsp;&nbsp;&nbsp;@-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2)&nbsp;该函数接受一个int型参数，但实际上，该参数是没有任何作用的。<br />&nbsp;&nbsp;&nbsp;&nbsp;*************************************************************************</span><span style="color: #008000">*/</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;UPInt&nbsp;</span><span style="color: #0000ff">operator</span><span style="color: #000000">--</span><span style="color: #000000">(</span><span style="color: #0000ff">int</span><span style="color: #000000">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UPInt&nbsp;retObj&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #0000ff">this</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">--</span><span style="color: #000000">(</span><span style="color: #000000">*</span><span style="color: #0000ff">this</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;retObj;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;UPInt();<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">virtual</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">~</span><span style="color: #000000">UPInt();<br /><br />};</span><span style="color: #008000">//</span><span style="color: #008000">class&nbsp;UPInt</span><span style="color: #008000"><br /></span><span style="color: #000000"><br /></span><span style="color: #008000">/*</span><span style="color: #008000">*****************************************************************************<br />@-summary&nbsp;:&nbsp;示例使用UPInt的&nbsp;++&nbsp;与&nbsp;--&nbsp;的前、后操作符重载<br />@-in&nbsp;param:&nbsp;<br />@-return&nbsp;&nbsp;:&nbsp;<br />*****************************************************************************</span><span style="color: #008000">*/</span><span style="color: #000000"><br /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;testUPIntIncAndDecOperator()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;UPInt&nbsp;theObj;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">++</span><span style="color: #000000">theObj;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;调用&nbsp;theObj.operator++();&nbsp;</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;theObj</span><span style="color: #000000">++</span><span style="color: #000000">;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;调用&nbsp;theObj.operator++(0);</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">--</span><span style="color: #000000">theObj;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;调用&nbsp;theObj.operator--();&nbsp;</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;theObj</span><span style="color: #000000">--</span><span style="color: #000000">;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;调用&nbsp;theObj.operator--(0);</span><span style="color: #008000"><br /></span><span style="color: #000000">}</span></div><br /><br />2) 为什么前缀与后缀的返回值会不同？？<br />答：一个后缀 increment 必须返回一个对象（它返回的是增加前的值），但是为什么<br />是 const 对象呢？假设不是 const 对象，下面的代码就是正确的： <br />UPInt i; <br />i++++; // 两次 increment 后缀 <br />这组代码与下面的代码相同： <br />i.operator++(0).operator++(0); <br />很明显，第一个调用的 operator++函数返回的对象调用了第二个 operator++函数。 <br />有两个理由导致我们应该厌恶上述这种做法，第一是与内置类型行为不一致。当设计一<br />个类遇到问题时，一个好的准则是使该类的行为与 int 类型一致。而 int 类型不允许连续进<br />行两次后缀 increment： <br />int i; <br />i++++; // 错误! <br />第二个原因是使用两次后缀 increment 所产生的结果与调用者期望的不一致。如上所<br />示，第二次调用 operator++改变的值是第一次调用返回对象的值，而不是原始对象的值。<br />因此如果： <br />i++++; <br />是合法的，i 将仅仅增加了一次。这与人的直觉相违背，使人迷惑（对于 int 类型和 UPInt<br />都是一样）,所以最好禁止这么做。 <br /><br />3) 同样条件下，前缀比后缀操作符来的高效。<br /><img src ="http://www.cppblog.com/Tongy0/aggbug/204438.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2013-11-25 20:50 <a href="http://www.cppblog.com/Tongy0/archive/2013/11/25/204438.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转载】 C++拷贝构造函数(深拷贝，浅拷贝)</title><link>http://www.cppblog.com/Tongy0/archive/2013/03/15/198449.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Fri, 15 Mar 2013 09:49:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2013/03/15/198449.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/198449.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2013/03/15/198449.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/198449.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/198449.html</trackback:ping><description><![CDATA[<div>转载自：<a href="http://blog.sina.com.cn/s/blog_6056c8830100zh1c.html">http://blog.sina.com.cn/s/blog_6056c8830100zh1c.html</a><br /><br />对于普通类型的对象来说，它们之间的复制是很简单的，例如：<br />
<p><font face="Verdana"><font face="Verdana">int a=88;<br />int b=a;<br /></font><font face="Verdana">而类对象与普通对象不同，类对象内部结构一般较为复杂，存在各种成员变量。下面看一个类对象拷贝的简单例子。<br /></font></font></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"><font face="Verdana"><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><font style="background-color: #eeeeee"><span style="color: #000000">#include <wbr></span><span style="color: #000000">&lt;</span><span style="color: #000000">iostream</span><span style="color: #000000">&gt;</span></font><span style="color: #000000"><br /><font style="background-color: #eeeeee"><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></font></span><font size="+0"><font style="background-color: #eeeeee"><span style="color: #0000ff">using</span><span style="color: #000000"> <wbr></span><span style="color: #0000ff">namespace</span></font></font><font size="+0"><font style="background-color: #eeeeee"><font size="+0"><span style="color: #000000"><font size="+0"><font size="+0"> <wbr></font>std;<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" name="Codehighlighter1_57_153_Open_Image" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" /></font></span><span style="color: #0000ff">class</span></font><span style="color: #000000"><font size="+0"> <wbr></font>CExample <wbr></span></font></font><span><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000">{<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></span><span style="color: #0000ff">private</span></font></font><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0"><font size="+0">:<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr></font>　</font></span><span style="color: #0000ff">int</span></font></font><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0"> <wbr></font>a;<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font></span><span style="color: #0000ff">public</span></font></font><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0"><font size="+0">:<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr></font>　CExample(</font></span><span style="color: #0000ff">int</span></font></font><span style="color: #000000"><font size="+0"><font style="background-color: #eeeeee"><font size="+0"><font size="+0"><font size="+0"> <wbr></font>b)<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" name="Codehighlighter1_105_112_Open_Image" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" /></font> <wbr><wbr><wbr><wbr></font>　</font></font></span><span><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0">{ <wbr></font>a</font></span><span style="color: #000000">=</span><span style="color: #000000">b;}</span></font></span><span style="color: #000000"><br /><font size="+0"><font style="background-color: #eeeeee"><font size="+0"><font size="+0"><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr></font>　</font></font></span><span style="color: #0000ff"><font style="background-color: #eeeeee">void</font></span><span style="color: #000000"><font size="+0"><font style="background-color: #eeeeee"><font size="+0"><font size="+0"><font size="+0"> <wbr></font>Show <wbr>()<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" name="Codehighlighter1_130_151_Open_Image" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" /></font> <wbr><wbr><wbr><wbr></font>　</font></font></span><span><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0"><font size="+0">{<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr></font>cout</font></span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">a</span><span style="color: #000000">&lt;&lt;</span></font></font><span style="color: #000000"><font style="background-color: #eeeeee"><font size="+0"><font size="+0">endl;<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" /></font> <wbr><wbr><wbr><wbr></font>}</font></span></span><span style="color: #000000"><br /><font size="+0"><font style="background-color: #eeeeee"><font size="+0"><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" /></font>}</font></font></span></span><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000">;<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #0000ff">int</span></font></font><span style="color: #000000"><font size="+0"><font style="background-color: #eeeeee"><font size="+0"> <wbr></font>main()<br /><img style="display: inline" title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" name="Codehighlighter1_167_230_Open_Image" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" /></font></font></span><span style="display: inline"><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0"><font size="+0">{<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr></font>　CExample <wbr>A(</font></span><span style="color: #800080">100</span></font></font><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0"><font size="+0">);<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr></font>　CExample <wbr>B</font></span><span style="color: #000000">=</span></font></font><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0">A;<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr></font>　B.Show <wbr>();<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr></font>　</font></span><span style="color: #0000ff">return</span><span style="color: #000000"> <wbr></span><span style="color: #800080">0</span></font></font><span style="color: #000000"><font size="+0"><font style="background-color: #eeeeee"><font size="+0">;<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" /></font>}</font></font></span></span><span style="color: #000000"><font style="background-color: #eeeeee"> <wbr></font></span></font></div>
<p><font face="Verdana">运行程序，屏幕输出100。从以上代码的运行结果可以看出，系统为对象B分配了内存并完成了与对象A的复制过程。就类对象而言，相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。下面举例说明拷贝构造函数的工作过程。</font></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"><font face="Verdana"><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><font style="background-color: #eeeeee"><span style="color: #000000">#include <wbr></span><span style="color: #000000">&lt;</span><span style="color: #000000">iostream</span><span style="color: #000000">&gt;</span></font><span style="color: #000000"><br /><font style="background-color: #eeeeee"><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></font></span><font size="+0"><font style="background-color: #eeeeee"><span style="color: #0000ff">using</span><span style="color: #000000"> <wbr></span><span style="color: #0000ff">namespace</span></font></font><font size="+0"><font style="background-color: #eeeeee"><font size="+0"><span style="color: #000000"><font size="+0"><font size="+0"> <wbr></font>std;<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" name="Codehighlighter1_57_194_Open_Image" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" /></font></span><span style="color: #0000ff">class</span></font><span style="color: #000000"><font size="+0"> <wbr></font>CExample <wbr></span></font></font><span><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000">{<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></span><span style="color: #0000ff">private</span></font></font><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0">:<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr></font></span><span style="color: #0000ff">int</span></font></font><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0"> <wbr></font>a;<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font></span><span style="color: #0000ff">public</span></font></font><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0"><font size="+0">:<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr></font>CExample(</font></span><span style="color: #0000ff">int</span></font></font><span style="color: #000000"><font size="+0"><font style="background-color: #eeeeee"><font size="+0"><font size="+0"> <wbr></font>b)<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" name="Codehighlighter1_102_109_Open_Image" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" /></font> <wbr><wbr><wbr><wbr></font></font></span><span><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0">{ <wbr></font>a</font></span><span style="color: #000000">=</span><span style="color: #000000">b;}</span></font></span><span style="color: #000000"><br /><font size="+0"><font style="background-color: #eeeeee"><font size="+0"><font size="+0"><font size="+0"><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr><br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr></font>CExample(</font></font></span><font size="+0"><font style="background-color: #eeeeee"><font size="+0"><span style="color: #0000ff"><font size="+0">const</font></span><span style="color: #000000"><font size="+0"> <wbr></font>CExample</span></font><span style="color: #000000">&amp;</span></font></font><span style="color: #000000"><font size="+0"><font style="background-color: #eeeeee"><font size="+0"><font size="+0"> <wbr></font>C)<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" name="Codehighlighter1_142_155_Open_Image" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" /></font> <wbr><wbr><wbr><wbr></font></font></span><span><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0"><font size="+0">{<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr></font>a</font></span><span style="color: #000000">=</span></font></font><span style="color: #000000"><font style="background-color: #eeeeee"><font size="+0"><font size="+0">C.a;<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" /></font> <wbr><wbr><wbr><wbr></font>}</font></span></span><span style="color: #000000"><br /><font size="+0"><font style="background-color: #eeeeee"><font size="+0"><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr></font></font></span><span style="color: #0000ff"><font style="background-color: #eeeeee">void</font></span><span style="color: #000000"><font size="+0"><font style="background-color: #eeeeee"><font size="+0"><font size="+0"> <wbr></font>Show <wbr>()<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" name="Codehighlighter1_171_192_Open_Image" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" /></font> <wbr><wbr><wbr><wbr></font></font></span><span><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0"><font size="+0">{<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr></font>cout</font></span><span style="color: #000000">&lt;&lt;</span><span style="color: #000000">a</span><span style="color: #000000">&lt;&lt;</span></font></font><span style="color: #000000"><font style="background-color: #eeeeee"><font size="+0"><font size="+0">endl;<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" /></font> <wbr><wbr><wbr><wbr></font>}</font></span></span><span style="color: #000000"><br /><font size="+0"><font style="background-color: #eeeeee"><font size="+0"><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" /></font>}</font></font></span></span><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000">;<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /><br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" /></span><span style="color: #0000ff">int</span></font></font><span style="color: #000000"><font size="+0"><font style="background-color: #eeeeee"><font size="+0"> <wbr></font>main()<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" name="Codehighlighter1_208_267_Open_Image" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" /></font></font></span><span><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0"><font size="+0">{<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr></font>CExample <wbr>A(</font></span><span style="color: #800080">100</span></font></font><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0"><font size="+0">);<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr></font>CExample <wbr>B</font></span><span style="color: #000000">=</span></font></font><font size="+0"><font style="background-color: #eeeeee"><span style="color: #000000"><font size="+0"><font size="+0"><font size="+0"><font size="+0">A;<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr></font>B.Show <wbr>();<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" /></font> <wbr><wbr><wbr><wbr></font></span><span style="color: #0000ff">return</span><span style="color: #000000"> <wbr></span><span style="color: #800080">0</span></font></font><span style="color: #000000"><font size="+0"><font style="background-color: #eeeeee"><font size="+0">;<br /><img title="(转)C++拷贝构造函数(深拷贝，浅拷贝)" alt="" align="top" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" real_src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" /></font>}</font></font></span></span><span style="color: #000000"><font style="background-color: #eeeeee"> <wbr></font></span></font></div>
<p><font face="Verdana"><span style="font-family: 'Courier new'; font-size: 10pt"><span style="background: #ffffff; color: #000000">CExample</span></span>(const <span style="font-family: 'Courier new'; font-size: 10pt"><span style="background: #ffffff; color: #000000">CExample</span></span>&amp; C)就是我们自定义的拷贝构造函数。可见，拷贝构造函数是一种特殊的构造函数，函数的名称必须和类名称一致，它的唯一的一个参数是本类型的一个引用变量，该参数是const类型，不可变的。例如：类X的拷贝构造函数的形式为X(X&amp; x)。</font></p>
<p><font face="Verdana">当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候，拷贝构造函数就会被自动调用。也就是说，当类的对象需要拷贝时，拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数：<br /></font><font face="Verdana">一个对象以值传递的方式传入函数体<br /></font><font face="Verdana">一个对象以值传递的方式从函数返回<br /></font><font face="Verdana">一个对象需要通过另外一个对象进行初始化。</font></p>
<p><font face="Verdana">如果在类中没有显式地声明一个拷贝构造函数，那么，编译器将会自动生成一个默认的拷贝构造函数，该构造函数完成对象之间的位拷贝。位拷贝又称浅拷贝，后面将进行说明。</font></p>
<p><font face="Verdana">自定义拷贝构造函数是一种良好的编程风格，它可以阻止编译器形成默认的拷贝构造函数，提高源码效率。<br /></font><font face="Verdana"><br />浅拷贝和深拷贝</font></p>
<p><font face="Verdana">　　在某些状况下，类内成员变量需要动态开辟堆内存，如果实行位拷贝，也就是把对象里的值完全复制给另一个对象，如A=B。这时，如果B中有一个成员变量指针已经申请了内存，那A中的那个成员变量也指向同一块内存。这就出现了问题：当B把内存释放了（如：析构），这时A内的指针就是野指针了，出现运行错误。</font></p>
<p><font face="Verdana">　　深拷贝和浅拷贝可以简单理解为：如果一个类拥有资源，当这个类的对象发生复制过程的时候，资源重新分配，这个过程就是深拷贝，反之，没有重新分配资源，就是浅拷贝。下面举个深拷贝的例子。</font></p>
<p><font face="Verdana">#include &lt;iostream&gt;<br />using namespace std;<br />class CA<br />{<br />　public:<br />　　CA(int b,char* cstr)<br />　　{<br />　　　a=b;<br />　　　str=new char[b];<br />　　　strcpy(str,cstr);<br />　　}<br />　　CA(const CA&amp; C)<br />　　{<br />　　　a=C.a;<br />　　　str=new char[a]; //深拷贝<br />　　　if(str!=0)<br />　　　　strcpy(str,C.str);<br />　　}<br />　　void Show()<br />　　{<br />　　　cout&lt;&lt;str&lt;&lt;endl;<br />　　}<br />　　~CA()<br />　　{<br />　　　delete str;<br />　　}<br />　private:<br />　　int a;<br />　　char *str;<br />};</font></p>
<p><font face="Verdana"><font face="Verdana">int main()<br />{<br />　CA A(10,"Hello!");<br />　CA B=A;<br />　B.Show();<br />　return 0;<br />}<br /></font><br />深拷贝和浅拷贝的定义可以简单理解成：如果一个类拥有资源(堆，或者是其它系统资源)，当这个类的对象发生复制过程的时候，这个过程就可以叫做深拷贝，反之对象存在资源，但复制过程并未复制资源的情况视为浅拷贝。</font></p>
<p><font face="Verdana">浅拷贝资源后在释放资源的时候会产生资源归属不清的情况导致程序运行出错。</font></p>
<p><font face="Verdana"><wbr><wbr><wbr><wbr><wbr><wbr><wbr>Test(Test &amp;c_t)是自定义的拷贝构造函数，拷贝构造函数的名称必须与类名称一致，函数的形式参数是本类型的一个引用变量,且必须是引用。</font></p><font face="Verdana">当用一个已经初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候，拷贝构造函数就会被自动调用，如果你没有自定义拷贝构造函数的时候，系统将会提供给一个默认的拷贝构造函数来完成这个过程，上面代码的复制核心语句就是通过Test(Test &amp;c_t)拷贝构造函数内的p1=c_t.p1;语句完成的。</font></div><img src ="http://www.cppblog.com/Tongy0/aggbug/198449.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2013-03-15 17:49 <a href="http://www.cppblog.com/Tongy0/archive/2013/03/15/198449.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>LogProvider 自己封装的一个日志服务类(很好用)</title><link>http://www.cppblog.com/Tongy0/archive/2013/03/13/198380.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Wed, 13 Mar 2013 04:51:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2013/03/13/198380.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/198380.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2013/03/13/198380.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/198380.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/198380.html</trackback:ping><description><![CDATA[<div>许多时候，设计项目，日志是必不可少的。<br />比如：有时候你自己就是觉得自己设计的功能，肯定没有问题。可偏偏别人会说你设计的有问题。这时候，如果没有日志报告，则你只能调试跟代码。如此必须浪费许多时间。（这点本人也是感受很深啦）。相反，如果有了日志报告，则一看，就清楚是否真的有问题，以及问题出在哪里。。<br />于是，基于此体会，以下是本人设计的一个日志服务提供器。虽然，简单，但可以提供十分便捷的日志服务。（个人认为十分好用）<br /><br />提示：具体文件，可从附件下载。<br />附件共4个文件：<br />LogUserConfig.h<br />LogConfig.h<br />LogProvider.h<br />LogProvider.cpp<br /><br />附件:<br /><a title="LogProvider.zip" href="/Files/Tongy0/LogProvider.zip">LogProvider.zip</a></div><img src ="http://www.cppblog.com/Tongy0/aggbug/198380.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2013-03-13 12:51 <a href="http://www.cppblog.com/Tongy0/archive/2013/03/13/198380.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++ ANSI、UNICODE、UTF8互转</title><link>http://www.cppblog.com/Tongy0/archive/2013/03/13/198378.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Wed, 13 Mar 2013 03:32:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2013/03/13/198378.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/198378.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2013/03/13/198378.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/198378.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/198378.html</trackback:ping><description><![CDATA[<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"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff">&nbsp;&nbsp;&nbsp; static</span><span style="color: #000000">&nbsp;std::wstring&nbsp;MBytesToWString(</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;lpcszString);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;std::</span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;WStringToMBytes(</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;wchar_t</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;lpwcszWString);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;std::wstring&nbsp;UTF8ToWString(</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;lpcszString);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;std::</span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;WStringToUTF8(</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;wchar_t</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;lpwcszWString);</span></div><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"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">std::wstring&nbsp;KKLogObject::MBytesToWString(</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;lpcszString)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;len&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;strlen(lpcszString);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;unicodeLen&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;::MultiByteToWideChar(CP_ACP,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;lpcszString,&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;NULL,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;wchar_t</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;pUnicode&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;wchar_t[unicodeLen&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;memset(pUnicode,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;(unicodeLen&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">)&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(wchar_t));<br />&nbsp;&nbsp;&nbsp;&nbsp;::MultiByteToWideChar(CP_ACP,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;lpcszString,&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;(LPWSTR)pUnicode,&nbsp;unicodeLen);<br />&nbsp;&nbsp;&nbsp;&nbsp;wstring&nbsp;wString&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;(wchar_t</span><span style="color: #000000">*</span><span style="color: #000000">)pUnicode;<br />&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;[]&nbsp;pUnicode;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;wString;<br />}<br /><br />std::</span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;KKLogObject::WStringToMBytes(</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;wchar_t</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;lpwcszWString)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;pElementText;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;iTextLen;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;wide&nbsp;char&nbsp;to&nbsp;multi&nbsp;char</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;iTextLen&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;::WideCharToMultiByte(CP_ACP,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;lpwcszWString,&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;NULL,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;NULL,&nbsp;NULL);<br />&nbsp;&nbsp;&nbsp;&nbsp;pElementText&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">[iTextLen&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;memset((</span><span style="color: #0000ff">void</span><span style="color: #000000">*</span><span style="color: #000000">)pElementText,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;(iTextLen&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">)&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(</span><span style="color: #0000ff">char</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;::WideCharToMultiByte(CP_ACP,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;lpwcszWString,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;pElementText,&nbsp;iTextLen,&nbsp;NULL,&nbsp;NULL);<br />&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;strReturn(pElementText);<br />&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;[]&nbsp;pElementText;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;strReturn;<br />}<br /><br />std::wstring&nbsp;KKLogObject::UTF8ToWString(</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;lpcszString)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;len&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;strlen(lpcszString);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;unicodeLen&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;::MultiByteToWideChar(CP_UTF8,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;lpcszString,&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;NULL,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;wchar_t</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;pUnicode;<br />&nbsp;&nbsp;&nbsp;&nbsp;pUnicode&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;wchar_t[unicodeLen&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;memset((</span><span style="color: #0000ff">void</span><span style="color: #000000">*</span><span style="color: #000000">)pUnicode,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;(unicodeLen&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">)&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(wchar_t));<br />&nbsp;&nbsp;&nbsp;&nbsp;::MultiByteToWideChar(CP_UTF8,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;lpcszString,&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;(LPWSTR)pUnicode,&nbsp;unicodeLen);<br />&nbsp;&nbsp;&nbsp;&nbsp;wstring&nbsp;wstrReturn(pUnicode);<br />&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;[]&nbsp;pUnicode;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;wstrReturn;<br />}<br /><br />std::</span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;KKLogObject::WStringToUTF8(</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;wchar_t</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;lpwcszWString)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;pElementText;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;iTextLen&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;::WideCharToMultiByte(CP_UTF8,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;(LPWSTR)lpwcszWString,&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;NULL,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;NULL,&nbsp;NULL);<br />&nbsp;&nbsp;&nbsp;&nbsp;pElementText&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">char</span><span style="color: #000000">[iTextLen&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;memset((</span><span style="color: #0000ff">void</span><span style="color: #000000">*</span><span style="color: #000000">)pElementText,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;(iTextLen&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">)&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(</span><span style="color: #0000ff">char</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;::WideCharToMultiByte(CP_UTF8,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;(LPWSTR)lpwcszWString,&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;pElementText,&nbsp;iTextLen,&nbsp;NULL,&nbsp;NULL);<br />&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;strReturn(pElementText);<br />&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;[]&nbsp;pElementText;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;strReturn;<br />}</span></div><br /><img src ="http://www.cppblog.com/Tongy0/aggbug/198378.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2013-03-13 11:32 <a href="http://www.cppblog.com/Tongy0/archive/2013/03/13/198378.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转载】 try catch throw用法 </title><link>http://www.cppblog.com/Tongy0/archive/2013/03/11/198344.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Mon, 11 Mar 2013 08:51:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2013/03/11/198344.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/198344.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2013/03/11/198344.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/198344.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/198344.html</trackback:ping><description><![CDATA[<div>转载自：<a href="http://blog.csdn.net/sky04/article/details/6536011">http://blog.csdn.net/sky04/article/details/6536011</a><br /><br />
<p>要防止因为异常产生的内存泄漏，可以使用智能指针，也可以用 <br />__try <br />{ <br />} <br />__finally <br />{ <br />} <br />《Windows核心编程》一书第23~25章是很好的参考资料。</p>
<p>----------------------------------------------------</p>
<p>try,catch,throw:</p>
<p>try包含你要防护的<span class="t_tag">代码</span>,称为防护块. 防护块如果出现异常,会自动生成异常对象并抛出.</p>
<p>catch捕捉特定的异常,并在其中进行适当处理.</p>
<p>throw可以直接抛出/产生异常,导致控制流程转到catch块.</p>
<p>重要观点: C++中异常是用对象来表示的,称为异常对象.</p>
<p><br />基本格式:</p>
<p>try { your code; }</p>
<p>catch(T1 t1) //T1可以是任意类型,int,char, CException...</p>
<p>{ /*T1指定了你要捕捉的异常的类型,t1指定了异常 对象的名称,当有异常抛出,异常对象将被复制到t1 中,这样你就可以在本处理块中使用该对象,获取相关 信息,进行适当处理. 处理代码;*/}</p>
<p>catch(T2* pt1)</p>
<p>//上面的catch是值传递,这里使用指针传递.</p>
<p>{ 处理代码; }</p>
<p>catch(...)</p>
<p>//...是捕捉任意类型的异常.</p>
<p>{ 处理代码; }</p>
<p>//其他代码;</p>
<p>/*某个catch执行完,就跳转到这里继续执行. 在没有使用C++异常处理的情况下,如果在 此之前出现异常,则//这里的其他代码不会被执行 从而造成问题.请考虑在这里放置: delete pobj1; 如果不使用用try,catch机制,内存泄漏是必然的, 因为出现问题后,执行流程无法跳转到这里. */</p>
<p><br />/*说明: try{}之后可以跟任意个catch块. 发生异常后,会生成临时的异常对象,进行一些自动处理之后,<span class="t_tag">程序</span>流程跳转到后面的catch(),逐个检查这些catch(),如果与catch() 中指定的类型一致,则将对象拷贝给catch参数中的对象, 接着执行该catch块中的代码,然后跳过其他所有剩下的catch, 继续执行后续的代码. <br />上面所说的自动处理指的是堆栈回退,说白了就是为函数中的局部对象调用析构函数,保证这些局部对象行为良好. */</p>
<p><br />catch()的顺序通常按照:从特殊到一般的顺序: catch(Tsub o){} catch(Tbase o){} catch(...){} 如果第一个catch为catch(Tbase){},则它将捕捉其所有派生类的 异常对象. 如果第一个catch为catch(...){},则其后的所有catch永远不可能 被执行. <br />重新抛出异常: 从上面的处理机制可以看到,只有一个catch可能被执行, 如果一个catch被执行,其他后续的catch就会被跳过了. 有时候一个catch中可能无法完成异常的全部处理,需要将 异常提交给更高的层,以期望得到处理.重新抛出异常实现 了这种可能性. 语法: throw ; 空的throw语句,只能在catch中使用. 它重新抛出异常对象,其外层的catch可能可以捕捉这个重新抛出的异常并做适当处理.</p>
<p>---------------------------------------------------------------------------------------------------------</p>
<p>1、基础介绍<br />try<br />{<br />//程序中抛出异常<br />throw value;<br />}<br />catch(valuetype v)<br />{<br />//例外处理程序段<br />}<br />语法小结：throw抛出值，catch接受，当然，throw必须在&#8220;try语句块&#8221;中才有效。<br /><br />2、深入throw：<br />(i)、程序接受到throw语句后就会自动调用析构器，把该域（try后的括号内）对象clean up，然后再进<br />入catch语句（如果在循环体中就退出循环）。<br /><br />这种机制会引起一些致命的错误，比如，当&#8220;类&#8221;有指针成员变量时（又是指针！），在 &#8220;类的构建器<br />&#8221;中的throw语句引起的退出，会导致这个指针所指向的对象没有被析构。这里很基础，就不深入了，提<br />示一下，把指针改为类就行了，比如模板类来代替指针，在模板类的内部设置一个析构函数。<br /><br />(ii)、语句&#8220;throw;&#8221;抛出一个无法被捕获的异常，即使是catch(...)也不能捕捉到，这时进入终止函数<br />，见下catch。<br /><br />3、深入catch：<br />一般的catch出现的形式是：<br />try{}<br />catch(except1&amp;){}<br />catch(except2&amp;){}<br />catch(...){} //接受所有异常<br />一般都写成引用（except1&amp;），原因很简单，效率。<br /><br />问题a：抛出异常，但是catch不到异常怎么办？（注意没有<span>java</span>类似的finally语句）<br />在catch没有捕获到匹配的异常的时候，会调用默认的终止函数。可以调用set_terminate()来设置终止函数，参数是一个函数指针，类型是：void (*terminate)()。<br /><br />到这里，可以题个问题：&#8220;没有try-catch,直接在程序中"throw;"，会怎么样？&#8221;<br /><br /><br />其他一些技巧：<br />4、try一个函数体，形式如下<br />void fun(type1,type2) try－－－－try放在函数体后<br />{<br />函数定义<br />}<br />catch(typeX){}<br />这个用法的效果就相当于:<br />void fun()<br />{<br />try{函数定义}<br />}<br /><br /><br />5、throw一个函数体，形式如下：<br />void fun (); // 能抛出任何类型的异常<br />void fun () throw(except1,except2,except3)<br />// 后面括号里面是一个异常参数表，本例中只能抛出这3中异常<br />void fun () throw() // 参数表为空，不能抛出异常<br /><br />问题b：假设fun()中抛出了一个不在&#8220;异常参数表&#8221;中的异常，会怎么样？<br /><br />答：调用set_terminate()中设定的终止函数。然而，这只是表面现象，实际上是调用默认的unexpected()函数，然而这个默认的 unexpected()调用了set_terminate()中设定的终止函数。可以用set_unexpected()来设置unexpected, 就像set_terminate()一样的用法，但是在设定了新的&#8220;unexpected()&#8221;之后，就不会再调用set_terminater中设定的 终止函数了。<br /><br />这个语法是很有用的，因为在用别人的代码时，不知道哪个地方会调用什么函数又会抛出什么异常，用一个异常参数表在申明时限制一下，很实用。<br />++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++</p>
<h1>try{} catch(&#8230;){}</h1>
<p>以前都是用try{} catch(&#8230;){}来捕获C++中一些意想不到的异常，今天看了Winhack的帖子才知道，这种方法在VC中其实是靠不住的。例如下面的代码：</p>
<div>
<ol title="Double click to hide line number."><li><span style="color: green">try</span></li><li><span style="color: olive">{</span></li><li><span style="color: blue">BYTE</span><span style="color: gray">*</span><span style="color: blue">pch</span><span style="color: gray">;</span></li><li><span style="color: blue">pch</span><span style="color: gray">=</span><span style="color: olive">(</span><span style="color: gray"> </span><span style="color: blue">BYTE</span><span style="color: gray">*</span><span style="color: olive">)</span><span style="color: maroon">00001234</span><span style="color: gray">; </span><span style="color: rgb(255,165,0)">// 给予一个非法地址</span></li><li><span style="color: gray"></span></li><li><span style="color: gray">*</span><span style="color: blue">pch</span><span style="color: gray">=</span><span style="color: maroon">6</span><span style="color: gray">;</span><span style="color: rgb(255,165,0)">// 对非法地址赋值，会造成Access Violation 异常</span></li><li><span style="color: olive">}</span></li><li><span style="color: green">catch</span><span style="color: olive">(</span><span style="color: gray">...</span><span style="color: olive">)</span></li><li><span style="color: olive">{</span></li><li><span style="color: blue">AfxMessageBox</span><span style="color: olive">(</span><span style="color: gray"> </span><span style="color: rgb(139,0,0)">"</span><span style="color: red">catched</span><span style="color: rgb(139,0,0)">"</span><span style="color: olive">)</span><span style="color: gray">;</span></li><li><span style="color: olive">}</span></li></ol></div>
<p>这段代码在debug下没有问题，异常会被捕获，会弹出&#8221;catched&#8221;的消息框。但在Release方式下如果选择了编译器代码优化选项，则VC编译器会去搜索try块中的代码， 如果没有找到throw代码，他就会认为try catch结构是多余的， 给优化掉。这样造成在Release模式下，上述代码中的异常不能被捕获，从而迫使程序弹出错误提示框退出。</p>
<p>那么能否在release代码优化状态下捕获这个异常呢， 答案是有的。 就是__try, __except结构，上述代码如果改成如下代码异常即可捕获。</p>
<div>
<ol title="Double click to hide line number."><li><span style="color: blue">__try</span></li><li><span style="color: olive">{</span></li><li><span style="color: blue">BYTE</span><span style="color: gray">*</span><span style="color: blue">pch</span><span style="color: gray">;</span></li><li><span style="color: blue">pch</span><span style="color: gray">=</span><span style="color: olive">(</span><span style="color: gray"> </span><span style="color: blue">BYTE</span><span style="color: gray">*</span><span style="color: olive">)</span><span style="color: maroon">00001234</span><span style="color: gray">; </span><span style="color: rgb(255,165,0)">// 给予一个非法地址</span></li><li><span style="color: gray"></span></li><li><span style="color: gray">*</span><span style="color: blue">pch</span><span style="color: gray">=</span><span style="color: maroon">6</span><span style="color: gray">;</span><span style="color: rgb(255,165,0)">// 对非法地址赋值，会造成Access Violation 异常</span></li><li><span style="color: olive">}</span></li><li><span style="color: blue">__except</span><span style="color: olive">(</span><span style="color: gray"> </span><span style="color: blue">EXCEPTION_EXECUTE_HANDLER</span><span style="color: olive">)</span></li><li><span style="color: olive">{</span></li><li><span style="color: blue">AfxMessageBox</span><span style="color: olive">(</span><span style="color: gray"> </span><span style="color: rgb(139,0,0)">"</span><span style="color: red">catched</span><span style="color: rgb(139,0,0)">"</span><span style="color: olive">)</span><span style="color: gray">;</span></li><li><span style="color: olive">}</span></li></ol></div>
<p>但是用__try, __except块还有问题， 就是这个不是C++标准， 而是Windows平台特有的扩展。而且如果在使用过程中涉及局部对象析构函数的调用，则会出现<a href="http://www.google.com/url?sa=t&amp;ct=res&amp;cd=1&amp;url=http%3A%2F%2Fmsdn2.microsoft.com%2Fen-us%2Flibrary%2Fxwtb73ad.aspx&amp;ei=yG8FRcLRKpHisALKxaDJCQ&amp;sig=__0o26_U6kzjC5tci9Pyqb9tdM4BE=&amp;sig2=Gjdjsi-xt_pIbvGvMGAFlg"><span><font color="#336699">C2712</font></span></a>的编译错误。 那么还有没有别的办法呢？</p>
<p>当然有， 就是仍然使用C++标准的try{}catch(..){}， 但在编译命令行中加入 <strong>/EHa</strong>的参数。这样VC编译器不会把try catch模块给优化掉了。</p>
<p><span>一篇比较好的英文文章谈这个问题： <a href="http://members.cox.net/doug_web/eh.htm" target="_blank"><font color="#336699">http://members.cox.net/doug_web/eh.htm</font></a></span></p><br /></div><img src ="http://www.cppblog.com/Tongy0/aggbug/198344.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2013-03-11 16:51 <a href="http://www.cppblog.com/Tongy0/archive/2013/03/11/198344.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++左值与右值之间共同与不同点解析</title><link>http://www.cppblog.com/Tongy0/archive/2013/03/04/198219.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Mon, 04 Mar 2013 15:12:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2013/03/04/198219.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/198219.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2013/03/04/198219.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/198219.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/198219.html</trackback:ping><description><![CDATA[<h1>转载自：<a href="http://developer.51cto.com/art/201002/182799.htm">http://developer.51cto.com/art/201002/182799.htm</a></h1>
<h1>&nbsp;</h1>
<h1>C++左值与右值之间共同与不同点解析</h1>
<div class="msg">
<div>2010-02-03 17:32 佚名 博客园 <span class="f12-a"><a href="http://developer.51cto.com/art/201002/182799.htm#commment" target="_self">我要评论(<span id="pinglun_1">1</span>)</a></span> 字号：<span class="f14-b"><a href="javascript:setfont(12);" target="_self">T</a></span> | <span class="f16-b"><a href="javascript:setfont(16);" target="_self">T</a></span></div>
<div style="padding-bottom: 5px; padding-left: 25px; padding-right: 25px; display: none; padding-top: 5px" id="books" class="artHd"></div>
<div class="fav"><a title="一键收藏，随时查看，分享好友！" href="javascript:favorBox('open');" target="_self"><img border="0" alt="一键收藏，随时查看，分享好友！" src="http://images.51cto.com/images/art/newart1012/images/Fav.gif" /></a></div></div>
<div class="brieftext">
<p class="f14 green">C++左值与右值都有哪些不同之处，又有哪些联系呢？我们将会通过对这篇文章的介绍，为大家详细讲解有关内容，帮助大家理解。</p>
<p class="ad">AD： <a style="text-decoration: none" href="http://wot.51cto.com/bigdata2013/buyticket.html" target="_blank">2013大数据全球技术峰会低价抢票中</a> </p></div>
<div style="display: none" id="indexlist" class="tag bgF8F8F8">
<ul id="indexliststr"></ul><br class="dle" /></div>
<div class="content bgF8F8F8 f14">
<div id="content">
<p>
<p><a href="http://developer.51cto.com/art/200709/56340.htm">C++</a>编程语言与C语言相比有很多不同之处，而且这些不同的地方有都体现着非常重要的作用。现在我们将会为大家详细介绍一下有关C++左值与右值之间的一些联系，希望能帮助大家对这一语言有一个深刻的认识。 
<div class="tuij">
<ul><li><a href="http://developer.51cto.com/art/201002/182777.htm" target="_blank">C++回文实现方法介绍</a></li><li><a href="http://developer.51cto.com/art/201002/182780.htm" target="_blank">C++变量作用域使用注意事项</a></li><li><a href="http://developer.51cto.com/art/201002/182784.htm" target="_blank">C++自定义类实际操作代码浅析</a></li><li><a href="http://developer.51cto.com/art/201002/182787.htm" target="_blank">C++对象复制相关应用方式浅析</a></li><li><a href="http://developer.51cto.com/art/201002/182793.htm" target="_blank">C++使用接口基本实现方式解析</a> </li></ul></div>
<p>&nbsp;</p>
<p><strong>1. C++左值与右值概念 </strong></p>
<p>变量和文字常量都有存储区，并且有相关的类型，区别在于变量是可寻址的；</p>
<p>对于每个变量，都有2个值与其相关联：</p>
<p>1&gt;数据值，存储在某个内存地址中，也称右值（rvalue），右值是被读取的值（read value），文字常量和变量都可被用于右值。</p>
<p>2&gt;地址值，即存储数据值的那块内存地址，也称左值（lvalue），文字常量不能被用作左值。</p>
<p><strong>2 . C++左值与右值的相关问题 </strong></p>
<p>给表达式加上括号： ++a--</p>
<p>结果 ++(a--)</p>
<p>这个表达式是非法的，因为前增量操作要求一个可修改的左值，而 "a--" 不是左值（即右值）</p>
<p><strong>3 . C++左值与右值中前增量和后增量的区别 </strong></p>
<p>早期的c语言教材，for循环语句通常写成：</p>
<p>for(int i=0;i&lt;10;i++)</p>
<p>而现在多为：</p>
<p>for(int i=0;i&lt;10;++i)</p>
<p>两者有区别吗？</p>
<p>a++ 即是返回 a的值，然后变量 a 加 1，返回需要产生一个临时变量类似于</p><pre><ol class="dp-xml"><li class="alt"><span>{   </span></li><li><span>int </span><span class="attribute">temp</span><span> = </span><span class="attribute-value">a</span><span>;   </span></li><li class="alt"><span class="attribute">a</span><span class="attribute-value">a</span><span>=a+1;   </span></li><li><span>return temp; //返回右值   </span></li><li class="alt"><span>}  </span></li></ol></pre>
<p>&nbsp;</p>
<p>++a 则为：</p><pre><ol class="dp-xml"><li class="alt"><span>{   </span></li><li><span class="attribute">a</span><span class="attribute-value">a</span><span>=a+1;   </span></li><li class="alt"><span>return &amp;a; //返回左值   </span></li><li><span>}  </span></li></ol></pre>
<p>&nbsp;</p>
<p>显然，前增量不需要中间变量，效率更高。</p>
<p><strong>C++左值与右值的含义与误区</strong></p>
<p>术语 &#8220;L-Values&#8221; 和 &#8220;R-Values&#8221; 是很容易被搞混的，因为它们的历史渊源也是混淆。他们最初起源是编译器的设计者，从字面上来理解就是表达式左边的值和表达式右边的值。它们的含义一直在演化而名字却没变，现在已经&#8220;名&#8221;不副&#8220;实&#8221;了。虽然还是称为left-value 和right-value,但是他们的含义已经大大不同了。</p>
<p>C++ 03 标准上是这样写的： &#8220;每一个表达式要么是一个 lvalue，要么就是一个 rvalue。&#8221;</p>
<p>记住，lvalue和rvalue是针对表达式而言的。</p>
<p>lvalue 是指那些单一表达式结束之后依然存在的持久对象。例如： obj，*ptr， prt[index]， ++x 都是 lvalue。</p>
<p>rvalue 是指那些表达式结束时（在分号处）就不复存在了的临时对象。例如：1729 ， x + y ， std::string("meow") ， 和 x++ 都是 rvalue。</p>
<p>++x 和 x++ 的区别的语义上的区别： 当写 int i = 10 ; 时， i 是一个 lvalue，它实际代表一个内存里的地址，是持久的。 表达式 ++x 也是一个 lvalue，它修改了 x 的值，但还是代表原来那个持久对象。但是，表达式 i++ 却是一个 rvalue，它只是拷贝一份i的初值，再修改i的值，最后返回那份临时的拷贝，那份拷贝是临时对象。 ++i 和 i++ 都递增i，但 ++i 返回i本身，而 i++ 返回临时拷贝。这就是为什么 ++i 之所以是一个 lvalue，而 i++ 是一个 rvalue。</p>
<p>lvalue 与 rvalue 之分不在于表达式做了什么，而在于表达式代表了什么（持久对象或临时产物）。 判断一个表达式是不是 lvalue 的直接方法就是&#8220;能不能对表达式取址？&#8221;，如果能够，那就是一个 lvalue；如果不能，那就是一个 rvalue。</p>
<p>以上就是我们为大家介绍的有关C++左值与右值的相关介绍。</p>
<div align="right">【责任编辑：<a class="ln" href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#108;&#105;&#117;&#115;&#110;&#64;&#53;&#49;&#99;&#116;&#111;&#46;&#99;&#111;&#109;">曹凯</a> TEL：（010）68476606】</div></div></div><img src ="http://www.cppblog.com/Tongy0/aggbug/198219.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2013-03-04 23:12 <a href="http://www.cppblog.com/Tongy0/archive/2013/03/04/198219.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用tolua++调用c/c++</title><link>http://www.cppblog.com/Tongy0/archive/2013/02/22/197991.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Fri, 22 Feb 2013 01:56:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2013/02/22/197991.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/197991.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2013/02/22/197991.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/197991.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/197991.html</trackback:ping><description><![CDATA[<div>首先，先温故一下c/c++调用lua的步骤：<br />1) 下载lua源码包(提示：下载后，需要自行编译，编译后才会有相应的lib)<br />2) 将编译好的lib链入项目<br />3) 包含相应的lua头文件，如下：<br />#ifdef __cplusplus<br />extern "C" {<br />#endif<br />#include "lua.h"<br />#include "lualib.h"<br />#include "lauxlib.h"<br />#ifdef __cplusplus<br />}<br />#endif<br />此处头跟尾处的__cplusplus宏判断是有必要的。<br />4)&nbsp;创建一个lua解析器：lua_State *L; L = lua_open();<br />5) 调用lua库接口：luaL_openlibs(L);打开lua库<br />6) 至此，就可以使用lua相关的功能了。如：加载lua脚本(luaL_dofileL, luaFileName);等等<br />7) 在使用完lua后，一定要关掉lua解析器。luaL_close(L);<br /><br />接下来要介绍的是相反的调用工作。即：通过lua调用c/c++相关的功能。在此就需要用到tolua++了。<br />在此同样先介绍一下实现步骤：<br />1) 同样需要先下载tolua++库<br />2) 将相关的tolua++库链入项目<br />3) 将需要导给lua脚本使用的c/c++常量、变量、宏、接口、甚至类以及其接口，整理到相应的干净包中。<br />4) 使用tolua++工具(即：.exe文件)，解析干净包。解析成功后，将自动生成相应的c/c++的头文件及源码<br />5) 包含同 4) 生成的头文件，同时包含tolua++要关的头文件<br />6) 明确初始化包。具体为：tolua_XXXX_open(L);<br />7) 此后就可以在lua脚本中使用c/c++相关的功能了。<br />至此c/c++与lua间的相互调用就全部介绍完毕。<br /><br />另外，以个人实际游戏框架设计的经验来看，其实，我们可以定义一个协议接口，将项目与lua的接口连接起来。这样，我们在c/c++与lua间的调用就可以通过通用的一个或很少的几个接口来工作。如此整个框架就搭建起来了。</div><img src ="http://www.cppblog.com/Tongy0/aggbug/197991.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2013-02-22 09:56 <a href="http://www.cppblog.com/Tongy0/archive/2013/02/22/197991.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vs2008 编译后链接exe时的一个错误(Post-Build Event)</title><link>http://www.cppblog.com/Tongy0/archive/2013/01/31/197647.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Thu, 31 Jan 2013 03:54:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2013/01/31/197647.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/197647.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2013/01/31/197647.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/197647.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/197647.html</trackback:ping><description><![CDATA[<div>今日编译链接一个exe时，提示如下错误：<br />vs2008 Project : error PRJ0019: A tool returned an error code: "Performing Post-Build Event..."<br /><br />经过网上查询，可使用如下方法解决：<br /><br />
<p style="text-align: left; line-height: 26px; background-color: rgb(255,255,255); font-family: Arial; color: rgb(51,51,51); font-size: 14px">打开properties属性页，找到Build Events选项，选择Post-build event选项，</p>
<p style="text-align: left; line-height: 26px; background-color: rgb(255,255,255); font-family: Arial; color: rgb(51,51,51); font-size: 14px">它的command line选项置成空</p>
<p style="text-align: left; line-height: 26px; background-color: rgb(255,255,255); font-family: Arial; color: rgb(51,51,51); font-size: 14px"></p>
<p style="text-align: left; line-height: 26px; background-color: rgb(255,255,255); font-family: Arial; color: rgb(51,51,51); font-size: 14px">/////////</p>
<p style="text-align: left; line-height: 26px; background-color: rgb(255,255,255); font-family: Arial; color: rgb(51,51,51); font-size: 14px">工程中command line</p>
<p style="text-align: left; background-color: rgb(255,255,255)"><font color="#333333" face="Arial"><span style="line-height: 26px; font-size: 14px">内容为</span></font></p>
<p style="text-align: left; background-color: rgb(255,255,255)"><font color="#333333" face="Arial"><span style="line-height: 26px; font-size: 14px">mkdir ..\..\..\..\发布组件\服务器组件\Release</span></font></p>
<p style="text-align: left; background-color: rgb(255,255,255)"><font color="#333333" face="Arial"><span style="line-height: 26px; font-size: 14px">copy /y ..\..\..\..\运行\Release\$(TargetFileName) ..\..\..\..\发布组件\服务器组件\Release\$(TargetFileName)</span></font></p><br /><br />作用 是生成完了拷贝文件用的。</div><img src ="http://www.cppblog.com/Tongy0/aggbug/197647.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2013-01-31 11:54 <a href="http://www.cppblog.com/Tongy0/archive/2013/01/31/197647.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>boost 时间使用一点小结(2)</title><link>http://www.cppblog.com/Tongy0/archive/2013/01/02/196908.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Wed, 02 Jan 2013 08:27:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2013/01/02/196908.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/196908.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2013/01/02/196908.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/196908.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/196908.html</trackback:ping><description><![CDATA[<div>此篇文章打算介绍两个，在平时工作中，使用频繁并且十分有价值的功能。(因为你的项目不用到还好，只要用到，下面这两个一般是必不可少)<br />功能点1：将本地时间转成格林威治时间，或者是将格林威治时间转成本地时间。<br />功能点2：将时间转成时间戳，以及如何将时间戳转成时间。<br />有些人可看刚看到上面的功能点概述，可能会觉得这没什么难的。也的确，事实上，确实不难。但如果你要是没真正处理过的话，可能一时还真会壁。比如：功能点1，将本地时间转成格林威治时间。因为我们根本不知道我们当前的本地时间与标准时间的时差到底是多少。所以你要怎么转？？（我们不能单纯地认为，我们是中国人，所以时差都是8个小时。那如果你的游戏要是发布到世界其他国家了？？那时差就完全不同。甚至就算是中国，你在上海，跟在西藏，那时间也是有差别的。因此，我们需要根据本地时刻值，精确地计算出与标准时间的时差。从而才可以准确转换成格林威治时间。看下面处理方法：<br />a) 将格林威治时间转成标准时间<br />&nbsp;ptime CommonHelper::utcToLocal(ptime utctime)<br />&nbsp;{<br />&nbsp;&nbsp;return boost::date_time::c_local_adjustor&lt;ptime&gt;::utc_to_local(utctime);<br />&nbsp; //说明：c_local_adjustor对象的utc_to_local()接口就是用来处理本地时间跟标准时间的偏差的。<br />&nbsp; //此处所谓的本地时间，并不是固定指说北京时间。而是你的计算处在地球的哪条经线上，该经线<br />&nbsp; //跟格林威治所处的经线的时差量。（我刚看到这个功能时，实在太让我惊讶了都！）<br /><br />&nbsp; //但是有一点需要注意：boost中，只提供了标准时间转本地时间的上述接口，却没有<br />&nbsp; //直接提供将本地时间转成标准时间的接口。不过，既然有了utc_to_loca()这样的神兵利器<br />&nbsp; //我们同样可以很方便地处理将本地时间转成标准时间的问题。见如何：<br />&nbsp;}<br /><br />b) 将本地时间转成格林威治时间<br />ptime CommonHelper::localToUtc(ptime ltime)<br />&nbsp;{<br />&nbsp;&nbsp;return ltime - (utcToLocal(epoch) - epoch);<br />&nbsp; //说明：(utcToLocal(epoch) - epoch)这部分内容您的计算机的当地时差量(如果是在北京，那就是8小时)<br />&nbsp;}<br /><br />接下来介绍一下第二部分的功能点。即：功能点2：将时间转时间戳以及将时间戳转时间<br />c) 将boost中的时间转成时间戳，其实很简单。中需要做如下处理即可。（在此就不多说）<br />&nbsp;WE::int64 CommonHelper::getUTCTimestamp()<br />&nbsp;{&nbsp;&nbsp;<br />&nbsp;&nbsp;return (microsec_clock::universal_time() - epoch).total_milliseconds(); <br />&nbsp;}<br /><br />d) 此处重点介绍一下，如何将时间戳转成时间。这个确实有点令人头痛。为什么这么说？因为时间戳，其实只是一个<br />数量值。这个数量值记载的信息的意义是指：自：1970-1-1到指定时刻所走过的时间量值。如此，或许有人就会说，<br />既然你都说了，是从1970到指定时刻的量值，两个时间相加不就好了。确实是这样子的，但有个小问题是：因为我们<br />没法清楚这个量值的单位是什么。如果单位是：毫秒，而你把它当成秒或当成微秒来处理，结果都将是错的。关于这点，<br />其实boost有个时间处理的决策&#8220;的开关&#8221;，这个似乎还要看自己编译的boost的lib是使用到哪个精度的级别。关于这块<br />本人暂时还没深入到这方面，所以也不敢妄言。不过，有个接口，大家可以参考着使用下。time_duration::resolution()<br />这个就可以用来识别，当前系统中boost在时间这方面使用到的精度值。（例如本人目前项目中，使用到的是微秒级别的。<br />所以返回值为：micro。）<br />下面给他几种实现时间戳转时间的小例子：(以下假定，时间戳的单位为毫秒)<br />e) 通过接口：from_time_t();<br />ptime time_5 = from_time_t(timestamp);<br />f) 通过time_duration<br />milliseconds xx(time_1_stamp);<br />ptime xxxxxxxxxxxx = CommonHelper::epoch + xx;<br />g) 直接通过手动计算。此方法实现思路很简单，但操作起来个人感觉易错。写的代码量又多，所以本人还是建议使用上面两种，特别是第2种<br />假如：timestamp是时间戳。则先计算出它的小时，再计算出它的分钟，计算出它的秒数，最后计算出它的毫秒数。然后与commonhelper::epoch相加即可。<br />注意：上面的e) f) g) 其实还是有区别的。用e)跟f)转出来的精度值方面会不中方法g)。但在项目使用中，前两者计算出来的精度值，一般<br />情况下，是绝对可够的。这是一个注意点，给大家提醒一下。<br /><br />好了，这篇文章暂时就先写到这吧。。其实关于boost时间，还有非常多的内容可以挖掘，改天有机会再写吧。希望对大伙有帮助。<br />如果有错误之处，还请指教。:)</div><img src ="http://www.cppblog.com/Tongy0/aggbug/196908.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2013-01-02 16:27 <a href="http://www.cppblog.com/Tongy0/archive/2013/01/02/196908.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[ 转载 ] Lua编译要考虑extern “C”</title><link>http://www.cppblog.com/Tongy0/archive/2012/12/03/195908.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Mon, 03 Dec 2012 02:28:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2012/12/03/195908.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/195908.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2012/12/03/195908.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/195908.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/195908.html</trackback:ping><description><![CDATA[<h3><span class="link_title">原文转载自：<a href="http://blog.csdn.net/leishiwei/article/details/4009307">http://blog.csdn.net/leishiwei/article/details/4009307</a><br /><br /></span><span style="font-size: 8pt" class="link_title">看完下面这篇文章，即可明白为什么在使用lua时，需要对所包含的头文件添加：extern "C"这样的符号来括起来。</span><span class="link_title"><br /></span><span style="font-size: 8pt" class="link_title">extern "C"<br /></span><span style="font-size: 8pt" class="link_title">{<br /></span><span style="font-size: 8pt" class="link_title">&nbsp;&nbsp;&nbsp; #include "lua.h"<br /></span><span style="font-size: 8pt" class="link_title">&nbsp;&nbsp;&nbsp; #include "lualib.h"<br /></span><span style="font-size: 8pt" class="link_title">&nbsp;&nbsp;&nbsp; #include "luaxlib.h"<br /></span><span style="font-size: 8pt" class="link_title">}<a href="/leishiwei/article/details/4009307"><br /><br />Lua编译要考虑extern &#8220;C&#8221; </a></span></h3>
<div class="article_manage"><span class="link_categories">分类： <a href="/leishiwei/article/category/526079">游戏脚本</a> </span><span class="link_postdate">2009-03-20 21:43</span> <span class="link_view" title="阅读次数">219人阅读</span> <span class="link_comments" title="评论次数"><a href="#comments">评论</a>(1)</span> <span class="link_collect"><a title="收藏" onclick="javascript:collectArticle('Lua编译要考虑extern &#8220;C&#8221; ','4009307');return false;" href="javascript:void(0);">收藏</a></span> <span class="link_report"><a title="举报" onclick="javascript:report(4009307,2);return false;" href="#report">举报</a></span> </div>
<div id="article_content" class="article_content">
<p>&nbsp;（转 七星重剑） <br />C++项目要到了如Lua这种纯C写成的库时，如果链接不过，就考虑是包含头文件时没加extern &#8220;C&#8221;。 <br />#ifdef __cplusplus <br />extern "C" { <br />#endif <br />&nbsp;&nbsp;&nbsp;&nbsp;#include "lualib.h" <br />&nbsp;&nbsp;&nbsp;&nbsp;#include "lauxlib.h" <br />#ifdef __cplusplus <br />} <br />#endif <br />　　 <br />时常在cpp的代码之中看到这样的代码: <br />#ifdef __cplusplus <br />extern "C" { <br />#endif <br />//一段代码 <br />#ifdef __cplusplus <br />} <br />#endif <br />　　这样的代码到底是什么意思呢？首先，__cplusplus是cpp中的自定义宏，那么定义了这个宏的话表示这是一段cpp的代码，也就是说，上面的代码的含义是:如果这是一段cpp的代码，那么加入extern "C"{和}处理其中的代码。 <br />　　要明白为何使用extern "C"，还得从cpp中对函数的重载处理开始说起。在c++中，为了支持重载机制，在编译生成的汇编码中，要对函数的名字进行一些处理，加入比如函数的返回类型等等.而在C中，只是简单的函数名字而已，不会加入其他的信息.也就是说:C++和C对产生的函数名字的处理是不一样的. <br />　　比如下面的一段简单的函数，我们看看加入和不加入extern "C"产生的汇编代码都有哪些变化: <br />int f(void) <br />{ <br />return 1; <br />} <br />　　在加入extern "C"的时候产生的汇编代码是: <br />.file "test.cxx" <br />.text <br />.align 2 <br />.globl _f <br />.def _f; .scl 2; .type 32; .endef <br />_f: <br />pushl %ebp <br />movl %esp， %ebp <br />movl $1， %eax <br />popl %ebp <br />ret <br />　　但是不加入了extern "C"之后 <br />.file "test.cxx" <br />.text <br />.align 2 <br />.globl __Z1fv <br />.def __Z1fv; .scl 2; .type 32; .endef <br />__Z1fv: <br />pushl %ebp <br />movl %esp， %ebp <br />movl $1， %eax <br />popl %ebp <br />ret <br />　　两段汇编代码同样都是使用gcc -S命令产生的，所有的地方都是一样的，唯独是产生的函数名，一个是_f，一个是__Z1fv。 <br />　　明白了加入与不加入extern "C"之后对函数名称产生的影响，我们继续我们的讨论:为什么需要使用extern "C"呢？C++之父在设计C++之时，考虑到当时已经存在了大量的C代码，为了支持原来的C代码和已经写好C库，需要在C++中尽可能的支持C，而extern "C"就是其中的一个策略。 <br />　　试想这样的情况:一个库文件已经用C写好了而且运行得很良好，这个时候我们需要使用这个库文件，但是我们需要使用C++来写这个新的代码。如果这个代码使用的是C++的方式链接这个C库文件的话，那么就会出现链接错误.我们来看一段代码:首先，我们使用C的处理方式来写一个函数，也就是说假设这个函数当时是用C写成的: <br />//f1.c <br />extern "C" <br />{ <br />void f1() <br />{ <br />return; <br />} <br />} <br />　　编译命令是:gcc -c f1.c -o f1.o 产生了一个叫f1.o的库文件。再写一段代码调用这个f1函数: <br />// test.cxx <br />//这个extern表示f1函数在别的地方定义，这样可以通过 <br />//编译，但是链接的时候还是需要 <br />//链接上原来的库文件. <br />extern void f1(); <br />int main() <br />{ <br />f1(); <br />return 0; <br />} <br />　　通过gcc -c test.cxx -o test.o 产生一个叫test.o的文件。然后，我们使用gcc test.o f1.o来链接两个文件，可是出错了，错误的提示是: <br />test.o(.text + 0x1f):test.cxx: undefine reference to 'f1()' <br />　　也就是说，在编译test.cxx的时候编译器是使用C++的方式来处理f1()函数的，但是实际上链接的库文件却是用C的方式来处理函数的，所以就会出现链接过不去的错误:因为链接器找不到函数。 <br />　　因此，为了在C++代码中调用用C写成的库文件，就需要用extern "C"来告诉编译器:这是一个用C写成的库文件，请用C的方式来链接它们。 <br />　　比如，现在我们有了一个C库文件，它的头文件是f.h，产生的lib文件是f.lib，那么我们如果要在C++中使用这个库文件，我们需要这样写: <br />extern "C" <br />{ <br />#include "f.h" <br />} <br />　　回到上面的问题，如果要改正链接错误，我们需要这样子改写test.cxx: <br />extern "C" <br />{ <br />extern void f1(); <br />} <br />int main() <br />{ <br />f1(); <br />return 0; <br />} <br />　　重新编译并且链接就可以过去了. <br />　　总结 <br />　　C和C++对函数的处理方式是不同的.extern "C"是使C++能够调用C写作的库文件的一个手段，如果要对编译器提示使用C的方式来处理函数的话，那么就要使用extern "C"来说明。<!--v:2.2--> </p></div><img src ="http://www.cppblog.com/Tongy0/aggbug/195908.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2012-12-03 10:28 <a href="http://www.cppblog.com/Tongy0/archive/2012/12/03/195908.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>heap(隐式表达式部分)学习小结</title><link>http://www.cppblog.com/Tongy0/archive/2012/11/21/195454.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Wed, 21 Nov 2012 04:07:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2012/11/21/195454.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/195454.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2012/11/21/195454.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/195454.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/195454.html</trackback:ping><description><![CDATA[<div>1) 正如书中所述，stl所述的heap都是max-heap。即：父节点的&#8220;值&#8221;[注释1]，永远是 &gt;= 其子节点的值。<br />2) 正如书中所述，stl所述的heap不归属于容器。因为它是一组算法。这些算法的实现原理，在此[注释2]，是以一棵完全二叉树来设计的。<br />3) 以下对各个max-heap接口算法的小结：<br /><br /><strong>a) make_heap()</strong><br />说明：顾名思义，该接口就是用来&#8220;创建&#8221;一个heap的。是对原有的一堆任意存放的数据，按照第一点所述的规则，进行&#8220;排列&#8221;（注意：不是排序）。<br />示例(来自书中例子，抄出来，经常看，印象会更深刻。在此，我们重在理解算法与掌握运用)：<br />int ai[9] = {0, 1, 2, 3, 4, 8, 9, 3, 5};<br />vector&lt;int&gt; ivec(ia, ia + 9);<br /><strong>make_heap</strong>(ivec.begin(), ivec.end());//调用后，ivec中的数据的排列将改变掉，并且已经是按max-heap的结构存储的。<br />for (int i&nbsp;= 0; i &lt; ivec.size(); i++)<br />&nbsp;&nbsp;&nbsp; cout &lt;&lt; ivec[i] &lt;&lt;&nbsp;' ';&nbsp;<span style="color: #008000"> // 9 5 8 3 4 0 2 3 1 </span><br />cout &lt;&lt; endl;<br /><br /><strong>b) push_heap()</strong><br />说明：将新push_back()到ivec的末尾元素按照max-heap的要求规则，进行位置调整。使得新的整个ivec中的元素排列规则符合max-heap的规则要求。<br /><span style="color: #0000ff">注意：</span><br /><span style="color: #0000ff">&nbsp;&nbsp;&nbsp; 1) push_heap()的操作，一定都是针对最末尾的那个元素，对它的位置按照max-heap的要求，进行重新调整的。</span><br /><span style="color: #0000ff">&nbsp;&nbsp;&nbsp; 2) 执行push_heap()操作前，一定一定要保证除了最末尾的那个元素外，前面的元素的排列规则一定都满足max-heap()的规则存放的。</span><br />示例：<br />ivec.push_back(7);<br /><strong>push_heap</strong>(ivec.begin(), ivec.end());<br />for (int i = 0; i &lt; ivec.size(); i++)<br />&nbsp;&nbsp;&nbsp; cout &lt;&lt; ivec[i] &lt;&lt; ' '; <span style="color: #008000">// 9 7 8 3 5 0 2 3 1 4 </span><br />cout &lt;&lt; endl;<br /><br /><strong>c) pop_heap()<br /></strong>说明：该接口意即：要从整个heap中，取出元素。但这里取出的一定是&#8220;值&#8221;最大的那个元素。而不是像vector或list等那样，可以取出任意位置的元素。<br /><span style="color: #0000ff">注意：</span><br /><span style="color: #0000ff">&nbsp;&nbsp;&nbsp; 1) 调用该接口&#8220;取出&#8221;元素后，其实该元素（即：&#8220;值&#8221;最大的那个元素）并未真正被取出来，而是将该元素放到了ivec的最末尾位置。（也正是因此，如果对整个ivec进行多次的pop_heap()操作，即可完成ivec的排序功能）</span><br /><span style="color: #0000ff">&nbsp;&nbsp;&nbsp; 2) 正如 注意1) 所述的，则在pop_heap()后，ivec除了最末尾的那个元素外，前面的元素仍然是保持着max-heap的规则存储的。</span><br />示例：<br />pop_heap(ivec.begin(), ivec.end());<br />cout &lt;&lt; ivec.back() &lt;&lt; endl; // 9. <span style="color: #ff0000"><strong>return but not remove.<br /></strong></span>ivec.pop_back(); // remove last elem and no return;<br /><br /><strong>d) sort_heap()</strong><br />说明：顾名思义，是对一个heap进行排序。<br /><span style="color: #0000ff">注意：</span><br /><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1) 排序后的&#8220;heap"（即：原始的heap）将不复存在（理由很简单：排序后，原heap中的元素的存储规则不符合max-heap的规则，因此排序后的，就不能再称为heap）</span><br />示例：<br />sort_heap(ivec.begin(), ivec.end());<br />for (int i = 0; i&nbsp;&lt; ivec.size(); i++)<br />&nbsp;&nbsp;&nbsp; cout &lt;&lt; ivec[i] &lt;&lt; ' '; // 0 1 2 3 3 4 5 7 8<br />cout &lt;&lt; endl;<br /><br />补充：max-heap的隐式表达式的push_heap()与pop_heap()操作时间都只有：O(logN)。一种算是比较居中的，还算不错的时间性能参考值。<br /><br />最后再说两点：<br />&nbsp;&nbsp;&nbsp;1) 只要深刻理解了以上算法与接口的使用，对实际项目的动作，个人认为，是很有价值的。另外，理解了heap的原理，则我们也十分容易priority queue的实现细节。<br />&nbsp;&nbsp;&nbsp;2) 对知识的掌握，还是重在理解。<br /><br />以上表述有误之处，还望大伙多多指正啊。。:)<br /><br />[注释1]：此处的值：我们可以当它是节点本身的值，也可以当它是某种权值。依自己使用需要而定。<br />[注释2]：指的是隐匿表达式实现的heap.即：以完全二叉树方式实现的heap。</div><img src ="http://www.cppblog.com/Tongy0/aggbug/195454.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2012-11-21 12:07 <a href="http://www.cppblog.com/Tongy0/archive/2012/11/21/195454.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[ 转载 ] 模版偏特化--Partial Template Specialization</title><link>http://www.cppblog.com/Tongy0/archive/2012/11/15/195218.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Thu, 15 Nov 2012 02:23:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2012/11/15/195218.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/195218.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2012/11/15/195218.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/195218.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/195218.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 原文转载自：http://www.cppblog.com/shenhuafeng/archive/2006/12/30/17041.html模版偏特化--Partial Template Specialization(《Modern C++ Design读书笔记二》) Partial Template Specialization顾名思义，模版偏特化就是对模版进行特化的意思。举个例子：na...&nbsp;&nbsp;<a href='http://www.cppblog.com/Tongy0/archive/2012/11/15/195218.html'>阅读全文</a><img src ="http://www.cppblog.com/Tongy0/aggbug/195218.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2012-11-15 10:23 <a href="http://www.cppblog.com/Tongy0/archive/2012/11/15/195218.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[ 转载 ] explicit 修饰符的功能用介绍</title><link>http://www.cppblog.com/Tongy0/archive/2012/11/13/195118.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Tue, 13 Nov 2012 08:49:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2012/11/13/195118.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/195118.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2012/11/13/195118.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/195118.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/195118.html</trackback:ping><description><![CDATA[<div>原文转载自：<a href="http://www.cnblogs.com/cutepig/archive/2009/01/14/1375917.html">http://www.cnblogs.com/cutepig/archive/2009/01/14/1375917.html</a><br /><br />
<div><strong>按照默认规定，只有一个参数的构造函数也定义了一个隐式转换，将该构造函数对应数据类型的数据转换为该类对象，如下面所示：</strong></div>
<div>class String {</div>
<div>String ( const char* p );&nbsp;<span style="font-size: 9pt">// </span>用C风格的字符串p作为初始化值</div>
<div>//&#8230;</div>
<div>}</div>
<div>String s1 = &#8220;hello&#8221;;&nbsp;//OK 隐式转换，等价于String s1 = String（&#8220;hello&#8221;）;</div>
<div>&nbsp;</div>
<div><strong>但是有的时候可能会不需要这种隐式转换，如下：</strong></div>
<div>class String {</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String ( int n );&nbsp;//</span>本意是预先分配n个字节给字符串</div>
<div>String ( const char* p );&nbsp;<span style="font-size: 9pt">// </span>用C风格的字符串p作为初始化值</div>
<div>//&#8230;</div>
<div style="text-indent: 21pt">}</div>
<div style="text-indent: 21pt">&nbsp;</div>
<div>下面两种写法比较正常：</div>
<div style="text-indent: 21pt">String s2 ( 10 );<span>&nbsp;&nbsp; //OK&nbsp;</span>分配10个字节的空字符串</div>
<div style="text-indent: 21pt">String s3 = String ( 10 );&nbsp;//OK&nbsp;分配10个字节的空字符串</div>
<div style="text-indent: 21pt">&nbsp;</div>
<div>下面两种写法就比较疑惑了：</div>
<div style="text-indent: 21pt">String s4 = 10;&nbsp;//编译通过，也是分配10个字节的空字符串</div>
<div style="text-indent: 21pt">String s5 = &#8216;a&#8217;;&nbsp;//编译通过，分配int（&#8216;a&#8217;）个字节的空字符串</div>
<div style="text-indent: 21pt">&nbsp;</div>
<div>s4 和s5 分别把一个int型和char型，隐式转换成了分配若干字节的空字符串，容易令人误解。</div>
<div>为了避免这种错误的发生，我们可以声明显示的转换，使用<strong>explicit</strong> 关键字：</div>
<div>class String {</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>explicit</strong> String ( int n );&nbsp;//</span>本意是预先分配n个字节给字符串</div>
<div>String ( const char* p );&nbsp;<span style="font-size: 9pt">// </span>用C风格的字符串p作为初始化值</div>
<div>//&#8230;</div>
<div style="text-indent: 21pt">}</div>
<div>加上<strong>explicit</strong><strong>，</strong>就抑制了String ( int n )的隐式转换，</div>
<div>&nbsp;</div>
<div>下面两种写法仍然正确：</div>
<div style="text-indent: 21pt">String s2 ( 10 );<span>&nbsp;&nbsp; //OK&nbsp;</span>分配10个字节的空字符串</div>
<div style="text-indent: 21pt">String s3 = String ( 10 );&nbsp;//OK&nbsp;分配10个字节的空字符串</div>
<div style="text-indent: 21pt">&nbsp;</div>
<div>下面两种写法就不允许了：</div>
<div style="text-indent: 21pt">String s4 = 10;&nbsp;//编译不通过，不允许隐式的转换</div>
<div style="text-indent: 21pt">String s5 = &#8216;a&#8217;;&nbsp;//编译不通过，不允许隐式的转换</div>
<div style="text-indent: 21pt">&nbsp;</div>
<div>因此，某些时候，<strong>explicit</strong> 可以有效得防止构造函数的隐式转换带来的错误或者误解<br /><br />----------------------------------------------------------<br />explicit &nbsp; 只对构造函数起作用，用来抑制隐式转换。如： &nbsp; <br />&nbsp; class &nbsp; A &nbsp; { &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; A(int &nbsp; a); &nbsp; <br />&nbsp; }; &nbsp; <br />&nbsp; int &nbsp; Function(A &nbsp; a); &nbsp; <br />&nbsp; &nbsp; <br />&nbsp; 当调用 &nbsp; Function(2) &nbsp; 的时候，2 &nbsp; 会隐式转换为 &nbsp; A &nbsp; 类型。这种情况常常不是程序员想要的结果，所以，要避免之，就可以这样写： &nbsp; <br />&nbsp; &nbsp; <br />&nbsp; class &nbsp; A &nbsp; { &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; explicit &nbsp; A(int &nbsp; a); &nbsp; <br />&nbsp; }; &nbsp; <br />&nbsp; int &nbsp; Function(A &nbsp; a); &nbsp; <br />&nbsp; &nbsp; <br />&nbsp; 这样，当调用 &nbsp; Function(2) &nbsp; 的时候，编译器会给出错误信息（除非 &nbsp; Function &nbsp; 有个以 &nbsp; int &nbsp; 为参数的重载形式），这就避免了在程序员毫不知情的情况下出现错误。<br /><br /><span id="Post.ascx_ViewPost_PreviousAndNextEntriesUp"></span><script>function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</script><font color="#ff1493">总结：explicit &nbsp; 只对构造函数起作用，用来抑制隐式转换。</font><br /><br />参考：<br />http://blog.csdn.net/smilelance/archive/2007/03/14/1528737.aspx<br />http://topic.csdn.net/t/20040509/15/3046021.html<br /></div></div><img src ="http://www.cppblog.com/Tongy0/aggbug/195118.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2012-11-13 16:49 <a href="http://www.cppblog.com/Tongy0/archive/2012/11/13/195118.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载] volatile的作用与用法</title><link>http://www.cppblog.com/Tongy0/archive/2012/11/11/195046.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Sun, 11 Nov 2012 14:40:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2012/11/11/195046.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/195046.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2012/11/11/195046.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/195046.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/195046.html</trackback:ping><description><![CDATA[<div>原文转载自：<a href="http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html">http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html</a><br /><br /><span class="fl f14">volatile的作用与用法　 <input id="sharetitle" name="sharetitle" value="volatile的作用与用法" type="hidden" /><strong class="fn gray f12">2011-12-15 13:34</strong></span> 
<div class="fr pr8 f12 fn blue">
<div style="line-height: 24px; padding-right: 12px;background: url(http://www.cppblog.com/images/passport/ico/shaer_line.gif) no-repeat 63px 50%; float: left"></div>
<div style="float: left">
<div class="tools">
<div class="tools_txt"><a href="javascript:inFavorite();"><img border="0" align="absMiddle" src="http://www.eefocus.com/images/content/eefocus/ico_fav.gif"  alt="" /> 加入收藏</a></div>
<div class="tools_txt_none">
<ul id="tools_more" class="tools_list"><li><a href="http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html#7"><img border="0" align="absMiddle" src="http://www.eefocus.com/images/passport/ico/ico_more.gif"  alt="" /> 转发分享</a> 
<dl>
<dd><a href="javascript:window.open('http://share.renren.com/share/buttonshare.do?link=http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html','_blank','scrollbars=no,width=800,height=450,left=75,top=20,status=no,resizable=yes'); void 0"><img border="0" align="absMiddle" src="http://www.eefocus.com/images/passport/ico/ico_ren.gif"  alt="" /> 人人网</a></dd>
<dd><a href="javascript:window.open('http://www.kaixin001.com/repaste/share.php?rtitle='+sharetitle+'&amp;rcontent=http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html','_blank','scrollbars=no,width=800,height=450,left=75,top=20,status=no,resizable=yes'); void 0"><img border="0" align="absMiddle" src="http://www.eefocus.com/images/passport/ico/ico_kaixin.gif"  alt="" /> 开心网</a></dd>
<dd><a href="javascript:window.open('http://v.t.sina.com.cn/share/share.php?title='+sharetitle+'&amp;url=http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html','_blank','scrollbars=no,width=800,height=450,left=75,top=20,status=no,resizable=yes'); void 0"><img border="0" align="absMiddle" src="http://www.eefocus.com/images/passport/ico/ico_sina.gif"  alt="" /> 新浪微博</a></dd>
<dd><a href="javascript:window.open('http://share.blog.sohu.com/submit.jhtml?shareType=31&amp;url=http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html&amp;abstracts=http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html','_blank','scrollbars=no,width=800,height=450,left=75,top=20,status=no,resizable=yes'); void 0"><img border="0" align="absMiddle" src="http://www.eefocus.com/images/passport/ico/ico_sohu.gif"  alt="" /> 搜狐博客</a></dd>
<dd><a href="javascript:window.open('http://cang.baidu.com/do/add?it='+sharetitle+'&amp;iu=http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html&amp;fr=ien#nw=1','_blank','scrollbars=no,width=800,height=450,left=75,top=20,status=no,resizable=yes'); void 0"><img border="0" align="absMiddle" src="http://www.eefocus.com/images/passport/ico/ico_baidu.gif"  alt="" /> 百度收藏</a></dd>
<dd><a href="javascript:window.open('https://www.google.com/bookmarks/mark?op=add&amp;bkmk=http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html&amp;title='+sharetitle+'','_blank','scrollbars=no,width=800,height=450,left=75,top=20,status=no,resizable=yes'); void 0"><img border="0" align="absMiddle" src="http://www.eefocus.com/images/passport/ico/ico_google.gif"  alt="" /> 谷歌收藏</a></dd>
<dd><a href="javascript:window.open('http://shuqian.qq.com/post?from=3&amp;title='+sharetitle+'&amp;uri=http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html&amp;jumpback=2&amp;noui=1','_blank','scrollbars=no,width=800,height=450,left=75,top=20,status=no,resizable=yes'); void 0"><img border="0" align="absMiddle" src="http://www.eefocus.com/images/passport/ico/ico_qq.gif"  alt="" /> qq书签</a></dd>
<dd><a href="javascript:window.open('http://www.douban.com/recommend/?url=http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html&amp;title='+sharetitle+'','_blank','scrollbars=no,width=800,height=450,left=75,top=20,status=no,resizable=yes'); void 0"><img border="0" align="absMiddle" src="http://www.eefocus.com/images/passport/ico/ico_douban.gif"  alt="" /> 豆瓣</a></dd>
<dd><a href="javascript:window.open('http://share.jianghu.taobao.com/share/addShare.htm?url=http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html','_blank','scrollbars=no,width=800,height=450,left=75,top=20,status=no,resizable=yes'); void 0"><img border="0" align="absMiddle" src="http://www.eefocus.com/images/passport/ico/ico_taojianghu.gif"  alt="" /> 淘江湖</a></dd>
<dd><a href="javascript:window.open('http://www.facebook.com/sharer.php?Fu=http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html&amp;t='+sharetitle+'','_blank','scrollbars=no,width=800,height=450,left=75,top=20,status=no,resizable=yes'); void 0"><img border="0" align="absMiddle" src="http://www.eefocus.com/images/passport/ico/ico_facebook.gif"  alt="" /> Facebook</a></dd>
<dd><a href="javascript:window.open('http://twitter.com/home?Fstatus=http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html&amp;title='+sharetitle+'','_blank','scrollbars=no,width=800,height=450,left=75,top=20,status=no,resizable=yes'); void 0"><img border="0" align="absMiddle" src="http://www.eefocus.com/images/passport/ico/ico_twitter.gif"  alt="" /> Twitter</a></dd>
<dd><a href="javascript:window.open('http://digg.com/submit?Fphase=2&amp;url=http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html','_blank','scrollbars=no,width=800,height=450,left=75,top=20,status=no,resizable=yes'); void 0"><img border="0" align="absMiddle" src="http://www.eefocus.com/images/passport/ico/ico_digg.gif"  alt="" /> Digg</a></dd>
<dd><a href="javascript:window.open('http://myweb2.search.yahoo.com/myresults/bookmarklet?Ft='+sharetitle+'&amp;u=http://www.eefocus.com/wang312/blog/2012-05/229203_12ffa.html&amp;ei=UTF-8','_blank','scrollbars=no,width=800,height=450,left=75,top=20,status=no,resizable=yes'); void 0"><img border="0" align="absMiddle" src="http://www.eefocus.com/images/passport/ico/ico_yahoo.gif"  alt="" /> Yahoo!Bookmarks</a></dd></dl></li></ul></div></div></div></div>
<div class="article_con">
<div class="card-summary-content">
<p>本文引自百度百科volatile，就当作了笔记，和大家一起分享吧。</p>
<p>&nbsp;</p>
<p>先说说我的理解，volatile我们叫它&#8220;易变的&#8221;，是一个类型修修饰符，一般情况下，我们定义了一个变量，如果说这个变量在整个代码中都没有改变，那么编译器就会把这个变量放到寄存器中，cpu取值就只在寄存器中取。但是在嵌入式中就会出现特殊情况了，很多时候，我们在代码中都不会改变一些变量的值(特别是寄存器的状态，或者某个引脚的状态)，但是硬件很有可能去改变这个值，如按键改变某引脚的状态等一些情况，可是编译器并不知道这个变量已经发生改变，这个时候很有可能编译器所使用的值和实际值并不一致，所以C语言中采用volatile来修饰这一类变量，它的作用是让编译器每次取值的都会到内存单元中去重新读取该变量的值，而不是直接使用寄存器中的值。</p>
<p>在代码中经常可以看到(*((volatile unsigned short *)(x)))这样的代码，作用也就是这个了。</p>
<p>以下是百科原文：</p>
<p>就象大家更熟悉的const一样，volatile是一个类型修饰符（type specifier）。它是被设计用来修饰被不同线程访问和修改的变量。如果没有volatile，基本上会导致这样的结果：要么无法编写多线程程序，要么<a href="http://www.eefocus.com/blog/link2url.php?link=http%3A%2F%2Fbaike.baidu.com%2Fview%2F487018.htm" target="_blank"><font color="#136ec2">编译器</font></a>失去大量优化的机会。</p></div>
<div class="clear"></div>
<p>&nbsp;</p>
<div class="clear"></div>
<div id="lemmaContent-0" class="lemma-main-content">　　推荐一个定义为volatile的变量是说这变量可能会被意想不到地改变，这样，<a href="http://www.eefocus.com/blog/link2url.php?link=http%3A%2F%2Fbaike.baidu.com%2Fview%2F487018.htm" target="_blank"><font color="#136ec2">编译器</font></a>就不会去假设这个变量的值了。精确地说就是，优化器在用到这个变量时必须每次都小心地重新读取这个变量的值，而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子： 
<div class="spctrl"></div>　　1). 并行设备的硬件寄存器（如：状态寄存器） 
<div class="spctrl"></div>　　2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 
<div class="spctrl"></div>　　3). 多线程应用中被几个任务共享的变量 
<div class="spctrl"></div>　　回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道，所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。 
<div class="spctrl"></div>　　假设被面试者正确地回答了这是问题（嗯，怀疑是否会是这样），我将稍微深究一下，看一下这家伙是不是真正懂得volatile完全的重要性。 
<div class="spctrl"></div>　　1). 一个参数既可以是const还可以是volatile吗？解释为什么。 
<div class="spctrl"></div>　　2). 一个指针可以是volatile 吗？解释为什么。 
<div class="spctrl"></div>　　3). 下面的函数有什么错误： 
<div class="spctrl"></div>　　int square(volatile int *ptr) 
<div class="spctrl"></div>　　{ 
<div class="spctrl"></div>　　return *ptr * *ptr; 
<div class="spctrl"></div>　　} 
<div class="spctrl"></div>　　下面是答案： 
<div class="spctrl"></div>　　1).是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。 
<div class="spctrl"></div>　　2). 是的。尽管这并不很常见。一个例子是当一个中断服务子程序修改一个指向一个buffer的指针时。 
<div class="spctrl"></div>　　3).这段代码是个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方，但是，由于*ptr指向一个volatile型参数，编译器将产生类似下面的代码： 
<div class="spctrl"></div>　　int square(volatile int *ptr) 
<div class="spctrl"></div>　　{ 
<div class="spctrl"></div>　　int a,b; 
<div class="spctrl"></div>　　a = *ptr; 
<div class="spctrl"></div>　　b = *ptr; 
<div class="spctrl"></div>　　return a * b; 
<div class="spctrl"></div>　　} 
<div class="spctrl"></div>　　由于*ptr的值可能被意想不到地该变，因此a和b可能是不同的。结果，这段代码可能返不是你所期望的平方值！正确的代码如下： 
<div class="spctrl"></div>　　long square(volatile int *ptr) 
<div class="spctrl"></div>　　{ 
<div class="spctrl"></div>　　int a; 
<div class="spctrl"></div>　　a = *ptr; 
<div class="spctrl"></div>　　return a * a; 
<div class="spctrl"></div>　　} 
<div class="spctrl"></div>　　讲讲我的理解： （欢迎打板子...~~！） 
<div class="spctrl"></div>　　关键在于两个地方： 
<div class="spctrl"></div>　　1. 编译器的优化 (请高手帮我看看下面的理解) 
<div class="spctrl"></div>　　在本次线程内,当读取一个变量时，为提高存取速度，编译器优化时有时会先把变量读取到一个寄存器中；以后，再取变量值时，就直接从寄存器中取值； 
<div class="spctrl"></div>　　当变量值在本线程里改变时，会同时把变量的新值copy到该寄存器中，以便保持一致 
<div class="spctrl"></div>　　当变量在因别的线程等而改变了值，该寄存器的值不会相应改变，从而造成<a href="http://www.eefocus.com/blog/link2url.php?link=http%3A%2F%2Fbaike.baidu.com%2Fview%2F330120.htm" target="_blank"><font color="#136ec2">应用程序</font></a>读取的值和实际的变量值不一致 
<div class="spctrl"></div>　　当该寄存器在因别的线程等而改变了值，原变量的值不会改变，从而造成应用程序读取的值和实际的变量值不一致 
<div class="spctrl"></div>　　举一个不太准确的例子： 
<div class="spctrl"></div>　　发薪资时，会计每次都把员工叫来登记他们的银行卡号；一次会计为了省事，没有即时登记，用了以前登记的银行卡号；刚好一个员工的银行卡丢了，已挂失该银行卡号；从而造成该员工领不到工资 
<div class="spctrl"></div>　　员工 －－ 原始变量地址 
<div class="spctrl"></div>　　银行卡号 －－ 原始变量在寄存器的备份 
<div class="spctrl"></div>　　2. 在什么情况下会出现(如1楼所说) 
<div class="spctrl"></div>　　1). 并行设备的硬件寄存器（如：状态寄存器） 
<div class="spctrl"></div>　　2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 
<div class="spctrl"></div>　　3). 多线程应用中被几个任务共享的变量 
<div class="spctrl"></div>　　补充： volatile应该解释为&#8220;直接存取原始内存地址&#8221;比较合适，&#8220;易变的&#8221;这种解释简直有点误导人； 
<div class="spctrl"></div>　　&#8220;易变&#8221;是因为外在因素引起的，象多线程，中断等，并不是因为用volatile修饰了的变量就是&#8220;易变&#8221;了，假如没有外因，即使用volatile定义，它也不会变化； 
<div class="spctrl"></div>　　而用volatile定义之后，其实这个变量就不会因外因而变化了，可以放心使用了； 大家看看前面那种解释（易变的）是不是在误导人 
<div class="spctrl"></div>　　－－－－－－－－－－－－简明示例如下：－－－－－－－－－－－－－－－－－－ 
<div class="spctrl"></div>　　volatile关键字是一种类型修饰符，用它声明的类型变量表示可以被某些编译器未知的因素更改，比如：<a href="http://www.eefocus.com/blog/link2url.php?link=http%3A%2F%2Fbaike.baidu.com%2Fview%2F880.htm" target="_blank"><font color="#136ec2">操作系统</font></a>、硬件或者其它线程等。遇到这个关键字声明的变量，编译器对访问该变量的代码就不再进行优化，从而可以提供对特殊地址的稳定访问。 
<div class="spctrl"></div>　　使用该关键字的例子如下： 
<div class="spctrl"></div>　　int volatile nVint; 
<div class="spctrl"></div>　　&gt;&gt;&gt;&gt;当要求使用volatile声明的变量的值的时候，系统总是重新从它所在的内存读取数据，即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。 
<div class="spctrl"></div>　　例如： 
<div class="spctrl"></div>　　volatile int i=10; 
<div class="spctrl"></div>　　int a = i; 
<div class="spctrl"></div>　　... 
<div class="spctrl"></div>　　//其他代码，并未明确告诉编译器，对i进行过操作 
<div class="spctrl"></div>　　int b = i; 
<div class="spctrl"></div>　　&gt;&gt;&gt;&gt;volatile 指出i是随时可能发生变化的，每次使用它的时候必须从i的地址中读取，因而编译器生成的汇编代码会重新从i的地址读取数据放在b中。而优化做法是，由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作，它会自动把上次读的数据放在b中。而不是重新从i里面读。这样以来，如果i是一个寄存器变量或者表示一个端口数据就容易出错，所以说volatile可以保证对特殊地址的稳定访问。 
<div class="spctrl"></div>　　&gt;&gt;&gt;&gt;注意，在vc6中，一般调试模式没有进行代码优化，所以这个关键字的作用看不出来。下面通过插入汇编代码，测试有无volatile关键字，对程序最终代码的影响： 
<div class="spctrl"></div>　　&gt;&gt;&gt;&gt;首先，用classwizard建一个win32 console工程，插入一个voltest.cpp文件，输入下面的代码： 
<div class="spctrl"></div>　　&gt;&gt; 
<div class="spctrl"></div>　　#i nclude 
<div class="spctrl"></div>　　void main() 
<div class="spctrl"></div>　　{ 
<div class="spctrl"></div>　　int i=10; 
<div class="spctrl"></div>　　int a = i; 
<div class="spctrl"></div>　　printf("i= %d",a); 
<div class="spctrl"></div>　　//下面汇编语句的作用就是改变内存中i的值，但是又不让编译器知道 
<div class="spctrl"></div>　　__asm { 
<div class="spctrl"></div>　　mov dword ptr [ebp-4], 20h 
<div class="spctrl"></div>　　} 
<div class="spctrl"></div>　　int b = i; 
<div class="spctrl"></div>　　printf("i= %d",b); 
<div class="spctrl"></div>　　} 
<div class="spctrl"></div>　　然后，在调试版本模式运行程序，输出结果如下： 
<div class="spctrl"></div>　　i = 10 
<div class="spctrl"></div>　　i = 32 
<div class="spctrl"></div>　　然后，在release版本模式运行程序，输出结果如下： 
<div class="spctrl"></div>　　i = 10 
<div class="spctrl"></div>　　i = 10 
<div class="spctrl"></div>　　输出的结果明显表明，release模式下，编译器对代码进行了优化，第二次没有输出正确的i值。下面，我们把i的声明加上volatile关键字，看看有什么变化： 
<div class="spctrl"></div>　　#i nclude 
<div class="spctrl"></div>　　void main() 
<div class="spctrl"></div>　　{ 
<div class="spctrl"></div>　　volatile int i=10; 
<div class="spctrl"></div>　　int a = i; 
<div class="spctrl"></div>　　printf("i= %d",a); 
<div class="spctrl"></div>　　__asm { 
<div class="spctrl"></div>　　mov dword ptr [ebp-4], 20h 
<div class="spctrl"></div>　　} 
<div class="spctrl"></div>　　int b = i; 
<div class="spctrl"></div>　　printf("i= %d",b); 
<div class="spctrl"></div>　　} 
<div class="spctrl"></div>　　分别在调试版本和release版本运行程序，输出都是： 
<div class="spctrl"></div>　　i = 10 
<div class="spctrl"></div>　　i = 32 
<div class="spctrl"></div>　　这说明这个关键字发挥了它的作用！ 
<div class="spctrl"></div>　　－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－ 
<div class="spctrl"></div>　　volatile对应的变量可能在你的程序本身不知道的情况下发生改变 
<div class="spctrl"></div>　　比如多线程的程序，共同访问的内存当中，多个程序都可以操纵这个变量 
<div class="spctrl"></div>　　你自己的程序，是无法判定何时这个变量会发生变化 
<div class="spctrl"></div>　　还比如，他和一个外部设备的某个状态对应，当外部设备发生操作的时候，通过驱动程序和中断事件，系统改变了这个变量的数值，而你的程序并不知道。 
<div class="spctrl"></div>　　对于volatile类型的变量，系统每次用到他的时候都是直接从对应的内存当中提取，而不会利用cache当中的原有数值，以适应它的未知何时会发生的变化，系统对这种变量的处理不会做优化&#8212;&#8212;显然也是因为它的数值随时都可能变化的情况。 
<div class="spctrl"></div>　　-------------------------------------------------------------------------------- 
<div class="spctrl"></div>　　典型的例子 
<div class="spctrl"></div>　　for ( int i=0; i&lt;100000; i++); 
<div class="spctrl"></div>　　这个语句用来测试空循环的速度的 
<div class="spctrl"></div>　　但是编译器肯定要把它优化掉，根本就不执行 
<div class="spctrl"></div>　　如果你写成 
<div class="spctrl"></div>　　for ( volatile int i=0; i&lt;100000; i++); 
<div class="spctrl"></div>　　它就会执行了 
<div class="spctrl"></div>　　volatile的本意是&#8220;易变的&#8221; 
<div class="spctrl"></div>　　由于访问寄存器的速度要快过RAM，所以编译器一般都会作减少存取外部RAM的优化。比如： 
<div class="spctrl"></div>　　static int i=0; 
<div class="spctrl"></div>　　int main(void) 
<div class="spctrl"></div>　　{ 
<div class="spctrl"></div>　　... 
<div class="spctrl"></div>　　while (1) 
<div class="spctrl"></div>　　{ 
<div class="spctrl"></div>　　if (i) dosomething(); 
<div class="spctrl"></div>　　} 
<div class="spctrl"></div>　　} 
<div class="spctrl"></div>　　/* Interrupt service routine. */ 
<div class="spctrl"></div>　　void ISR_2(void) 
<div class="spctrl"></div>　　{ 
<div class="spctrl"></div>　　i=1; 
<div class="spctrl"></div>　　} 
<div class="spctrl"></div>　　程序的本意是希望ISR_2中断产生时，在main当中调用dosomething函数，但是，由于编译器判断在<a href="http://www.eefocus.com/blog/link2url.php?link=http%3A%2F%2Fbaike.baidu.com%2Fview%2F379148.htm" target="_blank"><font color="#136ec2">main函数</font></a>里面没有修改过i，因此 
<div class="spctrl"></div>　　可能只执行一次对从i到某寄存器的读操作，然后每次if判断都只使用这个寄存器里面的&#8220;i副本&#8221;，导致dosomething永远也不会被 
<div class="spctrl"></div>　　调用。如果将将变量加上volatile修饰，则编译器保证对此变量的读写操作都不会被优化（肯定执行）。此例中i也应该如此说明。 
<div class="spctrl"></div>　　一般说来，volatile用在如下的几个地方： 
<div class="spctrl"></div>　　1、<a href="http://www.eefocus.com/blog/link2url.php?link=http%3A%2F%2Fbaike.baidu.com%2Fview%2F600257.htm" target="_blank"><font color="#136ec2">中断服务程序</font></a>中修改的供其它程序检测的变量需要加volatile； 
<div class="spctrl"></div>　　2、多任务环境下各任务间共享的标志应该加volatile； 
<div class="spctrl"></div>　　3、存储器映射的硬件寄存器通常也要加volatile说明，因为每次对它的读写都可能由不同意义； 
<div class="spctrl"></div>　　另外，以上这几种情况经常还要同时考虑数据的完整性（相互关联的几个标志读了一半被打断了重写），在1中可以通过关中断来实 
<div class="spctrl"></div>　　现，2中可以禁止任务调度，3中则只能依靠硬件的良好设计了。</div></div></div><img src ="http://www.cppblog.com/Tongy0/aggbug/195046.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2012-11-11 22:40 <a href="http://www.cppblog.com/Tongy0/archive/2012/11/11/195046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>boost 时间使用一点小结</title><link>http://www.cppblog.com/Tongy0/archive/2012/11/06/194768.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Tue, 06 Nov 2012 12:18:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2012/11/06/194768.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/194768.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2012/11/06/194768.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/194768.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/194768.html</trackback:ping><description><![CDATA[<div>由于在处理游戏服务端时，必须考虑到使用的处理。在此，使用了boost中的时间相关的内容。<br />用boost的好处很多，下面是项目中对此的一点应用小结：<br />1) 支持跨平台。<br />2) 时间的精确度极高。取得毫秒级的绝对没问题。（似乎微秒级的也可以）<br />3) 用法方便。<br />
<p>using namespace boost::posix_time;<br />using namespace boost::gregorian;<br />//using boost::gregorian::date;</p>
<p>#include &lt;boost/date_time/posix_time/posix_time.hpp&gt;<br />#define BOOST_DATE_TIME_SOURCE</p><br />static ptime const epoch(date(1970, 1, 1));//一个基准点。<br />std::string&nbsp;currtimestamp = CommonHelper::format("%I64u", (WE::uint64)((microsec_clock::universal_time() - epoch).total_milliseconds()));<br />//提示：<br />&nbsp;&nbsp;&nbsp;1) microsec_clock::universal_time()是取得格林威治时间。<br />&nbsp;&nbsp;&nbsp;2) 如果是：microsec_clock::local_time()则取得的是本地时间。<br />&nbsp;&nbsp;&nbsp;3) 如果想取得北京时间，则只需要加上8小时即可。microsec_clock::universal_time() + hours(8);<br />&nbsp;&nbsp;&nbsp;4) 上面的语句是计算当前格林威治时间的时间戳。<br /><br />4) boost::posix_time::ptime 因重载了许多操作符运算。因此，对它的使用就如同基本类型一样。如：可以很方便计算两点时间点的差距。<br /><br />boost::posix_time::ptime pt1(date(xxxx, x, x), time_duration(10, 1, 23));<br />//上面也可以这样写：boost::posix_time::ptime pt1(date(xxxx, x, x), time_duration(hours(10), minutes(1), seconds(23)));<br />//再比如：boost::posix_time::ptime pt1(date(xxxx, x, x), hours(10));如果想要详细了解，请自行研究boost源码。<br /><br />boost::posix_time::ptime pt2(.....);//这边的构造函数参数就不写了。请自行参考上面的语句。<br /><br />time_duration td = pt1 - pt2;//注意：ptime是不支持 + 的。因为它没有重载该操作。计算它们的加，是没有意义的。而 - 有意义。所以可如此操作。<br /><br />5) 取得日期，取得时间都很方便。<br /><br /><br />此次，就暂时就写这么多吧。<br /></div><img src ="http://www.cppblog.com/Tongy0/aggbug/194768.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2012-11-06 20:18 <a href="http://www.cppblog.com/Tongy0/archive/2012/11/06/194768.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载] const 用法详细</title><link>http://www.cppblog.com/Tongy0/archive/2012/10/09/193053.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Tue, 09 Oct 2012 02:40:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2012/10/09/193053.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/193053.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2012/10/09/193053.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/193053.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/193053.html</trackback:ping><description><![CDATA[<div>
<div><strong>原文转处：<a href="http://www.cppblog.com/software8/archive/2012/10/09/193049.html">http://www.cppblog.com/software8/archive/2012/10/09/193049.html</a><br /><br />一、面向对象是C++的重要特性.</strong></div>
<div>&nbsp; &nbsp;但是c++在c的基础上新增加的几点优化也是很耀眼的,就const直接可以取代c中的#define，以下几点很重要,学不好后果也也很严重</div>
<div>1. 限定符声明变量只能被读</div>
<div>[cpp] view plaincopyprint?</div>
<div>const int i=5; &nbsp;</div>
<div>&nbsp; int j=0; &nbsp;</div>
<div>&nbsp; ... &nbsp;</div>
<div>&nbsp; i=j; //非法，导致编译错误 &nbsp;</div>
<div>&nbsp; j=i; //合法 &nbsp;</div>
<div>2. 必须初始化</div>
<div>[cpp] view plaincopyprint?</div>
<div>const int i=5; //合法 &nbsp;</div>
<div>&nbsp; const int j; //非法，导致编译错误 &nbsp;</div>
<div>3. 在另一连接文件中引用const常量</div>
<div>[cpp] view plaincopyprint?</div>
<div>extern const int i; //合法 &nbsp;</div>
<div>extern const int j=10; //非法，常量不可以被再次赋值 &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; 在C++中const默认具有内部链接性，也就是说如果声明const int i = 10;等价于 static const int i =10;通常可以将const 常量和inline函数放在头文件中。所以要在A文件定义时用extern const int i=10;B文件中引用时用extern const int i。在C中恰好相反，const 默认具有外部链接属性，所以在引用外部const 常量时无需加extern。</div>
<div>4. 便于进行类型检查</div>
<div>&nbsp; 用const方法可以使编译器对处理内容有更多了解。&nbsp;</div>
<div>[cpp] view plaincopyprint?</div>
<div>#define I=10 &nbsp;</div>
<div>const long &amp;i=10; /*dapingguo提醒:由于编译器的优化，使得在const long i=10; 时i不被分配内存，而是已10直接代入以后的引用中，以致在以后的代码中没有错误，为达到说教效&nbsp;</div>
<div>&nbsp; 果，特别地用&amp;i明确地给出了i的内存分配。不过一旦你关闭所&nbsp;</div>
<div>&nbsp; 有优化措施，即使const long i=10;也会引起后面的编译错误。*/ &nbsp;</div>
<div>&nbsp; char h=I; //没有错 &nbsp;</div>
<div>&nbsp; char h=i; //编译警告，可能由于数的截短带来错误赋值。 &nbsp;</div>
<div>5. 可以避免不必要的内存分配</div>
<div>[cpp] view plaincopyprint?</div>
<div>#define STRING "abcdefghijklmn\n" &nbsp;</div>
<div>&nbsp; const char string[]="abcdefghijklm\n"; &nbsp;</div>
<div>&nbsp; ... &nbsp;</div>
<div>&nbsp; printf(STRING); //为STRING分配了第一次内存 &nbsp;</div>
<div>&nbsp; printf(string); //为string一次分配了内存，以后不再分配 &nbsp;</div>
<div>&nbsp; ... &nbsp;</div>
<div>&nbsp; printf(STRING); //为STRING分配了第二次内存 &nbsp;</div>
<div>&nbsp; printf(string); &nbsp;</div>
<div>&nbsp; ... &nbsp; &nbsp;</div>
<div>&nbsp; 由于const定义常量从汇编的角度来看，只是给出了对应的内存地址， 而不是象#define一样给出的是立即数，所以，const定义的常量在程序运行过程中只有一份拷贝，而#define定义的常量在内存中有若干个拷贝。但是这个地方也有点其他问题，大家自己好好研究下吧，给个例子：</div>
<div>[cpp] view plaincopyprint?</div>
<div>#include &lt;stdio.h&gt; &nbsp;&nbsp;</div>
<div>#define ABCD &nbsp; &nbsp;"ABCD" &nbsp;</div>
<div>const char a[] = "ABCD"; &nbsp;</div>
<div>static void &nbsp;</div>
<div>p(const char *s) &nbsp;</div>
<div>{ &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; printf("%X\n", s); &nbsp;</div>
<div>} &nbsp;</div>
<div>int &nbsp; main(void) &nbsp;</div>
<div>{ &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; const char b[] = "ABCD"; &nbsp;</div>
<div>&nbsp;&nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; p(ABCD); &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; p(ABCD); &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; p(a); &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; p(b); &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp; return 0; &nbsp;</div>
<div>} &nbsp;</div>
<div>[plain] view plaincopyprint?</div>
<div>程序输出为： &nbsp;</div>
<div>400748 &nbsp;</div>
<div>400748 &nbsp;</div>
<div>40073F &nbsp;</div>
<div>FFFFEB00 &nbsp;</div>
<div>编译器管不了你运行是更改所谓的const int 变量。 但对于你声明的const int 变量。在它的编译空间里，它保留了这个数值。 所以，调用的时候，把立即数传过去了（这个值在编译时就确定了）。</div>
<div>6. 可以通过函数对常量进行初始化</div>
<div>[cpp] view plaincopyprint?</div>
<div>int value(); &nbsp; &nbsp;</div>
<div>const int i=value(); &nbsp;</div>
<div>&nbsp; dapingguo说：假定对ROM编写程序时，由于目标代码的不可改写，本语句将会无效，不过可以变通一下：</div>
<div>&nbsp; const int &amp;i=value();</div>
<div>&nbsp; 只要令i的地址处于ROM之外，即可实现：i通过函数初始化，而其值有不会被修改。</div>
<div><strong>7. 是不是const的常量值一定不可以被修改呢？</strong></div>
<div>&nbsp; 观察以下一段代码： &nbsp;</div>
<div>[cpp] view plaincopyprint?</div>
<div>const int i=0; &nbsp;</div>
<div>int *p=(int*)&amp;i; &nbsp;</div>
<div>p=100; &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp;通过强制类型转换，将地址赋给变量，再作修改即可以改变const常量值。</div>
<div>&nbsp; &nbsp; &nbsp;说明了申明为常量的数据也可能被改变。我这里补充的是不要对const 的滥用。强制绕过const 检查可能引起运行错误。把const int i=0 声明在函数内，能够达到你的目的把const int i=0 声明为全局变量，虽然仍然能够用强制转换绕过编译器检查，但会引起运行错误。</div>
<div>可参考下例：&nbsp;</div>
<div>[cpp] view plaincopyprint?</div>
<div>const int j=50; &nbsp;</div>
<div>void main() &nbsp;</div>
<div>{ &nbsp;</div>
<div>&nbsp; &nbsp; const int i=0; &nbsp;</div>
<div>&nbsp; &nbsp; int *p=(int*)&amp;i; &nbsp;</div>
<div>&nbsp; &nbsp; *p=100; &nbsp;&nbsp;</div>
<div>&nbsp; &nbsp; int *p2=(int *)&amp;j; &nbsp;</div>
<div>&nbsp; &nbsp; *p2=200; &nbsp;// runtime error &nbsp;</div>
<div>&nbsp; &nbsp; cout &lt;&lt; &amp;i &lt;&lt; &amp;j; &nbsp;</div>
<div>&nbsp; &nbsp; system("pause"); &nbsp;</div>
<div>} &nbsp;</div>
<div></div>
<div><strong>8. 请分清数值常量和指针常量，以下声明颇为玩味：</strong></div>
<div>[cpp] view plaincopyprint?</div>
<div>int ii=0; &nbsp;</div>
<div>const int i=0; //i是常量，i的值不会被修改 &nbsp;</div>
<div>const int *p1i=&amp;i; //指针p1i所指内容是常量，可以不初始化 &nbsp;</div>
<div>int * const p2i=&amp;ii //指针p2i是常量，所指内容可修改 &nbsp;</div>
<div>const int * const p3i=&amp;i; //指针p3i是常量，所指内容也是常量 &nbsp;</div>
<div>p1i=&amp;ii //不合法 左操作数包含&#8220;int *&#8221;类型 &nbsp;</div>
<div>*p2i=100; //不合法 &nbsp;右操作数包含&#8220;int *const &#8221;类型 &nbsp;</div>
<div>指向常量的指针并不能保证所指向的值不被改变</div>
<div>[cpp] view plaincopyprint?</div>
<div>const int i=10; &nbsp;</div>
<div>void main() &nbsp;</div>
<div>{ &nbsp;</div>
<div>&nbsp; &nbsp; const int j=20; &nbsp;</div>
<div>&nbsp; &nbsp; int k = 30; &nbsp;</div>
<div>&nbsp; &nbsp; const int * p1=&amp;i; &nbsp;</div>
<div>&nbsp; &nbsp; const int * p2 = &amp;j; &nbsp;</div>
<div>&nbsp; &nbsp; const int * p3 = &amp;k; &nbsp;</div>
<div>&nbsp; &nbsp; // i=80; fail &nbsp;</div>
<div>&nbsp; &nbsp; // j= 20; fail &nbsp;</div>
<div>&nbsp; &nbsp; // *p3 = 50; fail &nbsp;</div>
<div>&nbsp; &nbsp; // 以上三种均未逃过编译器检查 &nbsp;</div>
<div>&nbsp; &nbsp; k=80; &nbsp; // succeed 逃过了编译器检查。 *p3 不行，但直接改k 允许。 &nbsp;</div>
<div>&nbsp; &nbsp; system("pause"); &nbsp;</div>
<div>} &nbsp;</div>
<div>所以对const 的理解，全局变量不仅有编译的保护，还有运行的保护。对局部变量，则只有编译的保护。</div>
<div>所以，当你声明一个局部const变量时，它可能在运行期被改变。</div>
<div><strong>二、关于C++中的const关键字的用法非常灵活</strong></div>
<div>1. const常量，如：</div>
<div>[cpp] view plaincopyprint?</div>
<div>const int max = 100; &nbsp;&lt;span style="font-family: simsun; "&gt; &lt;/span&gt; &nbsp;</div>
<div>优点：const常量有数据类型，而宏常量没有数据类型。编译器可以对前者进行类型安全检查，而对后者只进行字符替换，没有类型安全检查，并且在字符替换时可能会产生意料不到的错误（边际效应）</div>
<div>2. const 修饰类的数据成员。</div>
<div>如：</div>
<div>[cpp] view plaincopyprint?</div>
<div>class A &nbsp;</div>
<div>{ &nbsp;</div>
<div>&nbsp; const int size; &nbsp;</div>
<div>&nbsp; &#8230; &nbsp; &nbsp;</div>
<div>} &nbsp;</div>
<div>const数据成员只在某个对象生存期内是常量，而对于整个类而言却是可变的。因为类可以创建多个对象，不同的对象其const数据成员的值可以不同。所以不能在类声明中初始化const数据成员，因为类的对象未被创建时，编译器不知道const 数据成员的值是什么。如</div>
<div>[cpp] view plaincopyprint?</div>
<div>class A &nbsp;</div>
<div>{ &nbsp;</div>
<div>&nbsp; &nbsp; const int size = 100; //错误 &nbsp;</div>
<div>&nbsp; &nbsp; int array[size]; //错误，未知的size &nbsp;</div>
<div>} &nbsp;</div>
<div>const数据成员的初始化只能在类的构造函数的初始化表中进行。要想建立在整个类中都恒定的常量，应该用类中的枚举常量来实现。如</div>
<div>[cpp] view plaincopyprint?</div>
<div>class A &nbsp;</div>
<div>{ &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp;&#8230; &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp;enum {size1=100, size2 = 200 }; &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp;int array1[size1]; &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp;int array2[size2]; &nbsp; &nbsp;</div>
<div>} &nbsp;</div>
<div>枚举常量不会占用对象的存储空间，他们在编译时被全部求值。但是枚举常量的隐含数据类型是整数，其最大值有限，且不能表示浮点数。</div>
<div>3. const修饰指针的情况，见下式：</div>
<div>[cpp] view plaincopyprint?</div>
<div>int b = 500; &nbsp; &nbsp;</div>
<div>const int* a = &amp;b;//[1] &nbsp;</div>
<div>int const *a = &amp;b;//[2] &nbsp;</div>
<div>int* const a = &amp;b;//[3] &nbsp;&nbsp;</div>
<div>const int* const a = &amp;b;//[4] &nbsp;&nbsp;</div>
<div>如果你能区分出上述四种情况，那么，恭喜你，你已经迈出了可喜的一步。不知道，也没关系，我们可以参考《Effective c++》Item21上的做法，如果const位于星号的左侧，则const就是用来修饰指针所指向的变量，即指针指向为常量；如果const位于星号的右侧，const就是修饰指针本身，即指针本身是常量。因此，[1]和[2]的情况相同，都是指针所指向的内容为常量（const放在变量声明符的位置无关），这种情况下不允许对内容进行更改操作，如不能*a = 3 ；[3]为指针本身是常量，而指针所指向的内容不是常量，这种情况下不能对指针本身进行更改操作，如a++是错误的；[4]为指针本身和指向的内容均为常量。 &nbsp;</div>
<div>4. const的初始化 &nbsp;</div>
<div>先看一下const变量初始化的情况 &nbsp;</div>
<div>1) 非指针const常量初始化的情况：A b; &nbsp;</div>
<div>[cpp] view plaincopyprint?</div>
<div>const A a = b; &nbsp; &nbsp;</div>
<div>2) 指针const常量初始化的情况：</div>
<div>[cpp] view plaincopyprint?</div>
<div>A* d = new A(); &nbsp; &nbsp;</div>
<div>const A* c = d; &nbsp;//或者：const A* c = new A(); &nbsp; &nbsp;</div>
<div>3）引用const常量初始化的情况： &nbsp;</div>
<div>[cpp] view plaincopyprint?</div>
<div>A f; &nbsp; &nbsp;</div>
<div>const A&amp; e = f; // 这样作e只能访问声明为const的函数，而不能访问一般的成员函数&lt;span style="font-family: simsun; font-size: 14px; line-height: 23px; text-align: left; "&gt;； &nbsp;&lt;/span&gt; &nbsp;</div>
<div>&nbsp; [思考1]： 以下的这种赋值方法正确吗？ &nbsp;</div>
<div>&nbsp; const A* c=new A(); &nbsp;</div>
<div>&nbsp; A* e = c; &nbsp;</div>
<div>&nbsp; [思考2]： 以下的这种赋值方法正确吗？ &nbsp;</div>
<div>&nbsp; A* const c = new A(); &nbsp;</div>
<div>&nbsp; A* b = c;</div>
<div>5. 函数声明中的运用</div>
<div>&nbsp; &nbsp; &nbsp; 另外const 的一些强大的功能在于它在函数声明中的应用。在一个函数声明中，const 可以修饰函数的返回值，或某个参数；对于成员函数，还可以修饰是整个函数。有如下几种情况，以下会逐渐的说明用法：A&amp; operator=(const A&amp; a); &nbsp;</div>
<div>[cpp] view plaincopyprint?</div>
<div>void fun0(const A* a ); &nbsp; &nbsp;</div>
<div>void fun1( ) const; // fun1( ) 为类成员函数 &nbsp;&nbsp;</div>
<div>const A fun2( ); &nbsp;</div>
<div>1） 修饰参数的const，如：</div>
<div>[cpp] view plaincopyprint?</div>
<div>void fun0(const A* a ); &nbsp;</div>
<div>void fun1(const A&amp; a); &nbsp; &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp;调用函数的时候，用相应的变量初始化const常量，则在函数体中，按照const所修饰的部分进行常量化，如形参为const A* a，则不能对传递进来的指针的内容进行改变，保护了原指针所指向的内容；如形参为const A&amp; a，则不能对传递进来的引用对象进行改变，保护了原对象的属性。 &nbsp;</div>
<div>[注意]：参数const通常用于参数为指针或引用的情况，且只能修饰输入参数;若输入参数采用&#8220;值传递&#8221;方式，由于函数将自动产生临时变量用于复制该参数，该参数本就不需要保护，所以不用const修饰。</div>
<div>[总结] &nbsp; &nbsp;&nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp;对于非内部数据类型的输入参数，因该将&#8220;值传递&#8221;的方式改为&#8220;const引用传递&#8221;，目的是为了提高效率。例如，将void Func(A a)改为void Func(const A &amp;a)。对于内部数据类型的输入参数，不要将&#8220;值传递&#8221;的方式改为&#8220;const引用传递&#8221;。否则既达不到提高效率的目的，又降低了函数的可理解性。例如void Func(int x)不应该改为void Func(const int &amp;x)； 修饰返回值的const，如：</div>
<div>[cpp] view plaincopyprint?</div>
<div>const A fun2( ); &nbsp;</div>
<div>const A* fun3( );&lt;span style="font-family: simsun; "&gt; &nbsp;&lt;/span&gt; &nbsp;</div>
<div>这样声明了返回值后，const按照"修饰原则"进行修饰，起到相应的保护作用。</div>
<div>[cpp] view plaincopyprint?</div>
<div>const Rational operator*(const Rational&amp; lhs, const Rational&amp; rhs) &nbsp; &nbsp;</div>
<div>{ &nbsp; &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; return Rational(lhs.numerator() * rhs.numerator(), &nbsp; &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; lhs.denominator() * rhs.denominator()); &nbsp; &nbsp;</div>
<div>} &lt;span style="font-family: simsun; "&gt; &lt;/span&gt; &nbsp;</div>
<div>返回值用const修饰可以防止允许这样的操作发生:</div>
<div>[cpp] view plaincopyprint?</div>
<div>Rational a,b; &nbsp; &nbsp;</div>
<div>Radional c; &nbsp; &nbsp;</div>
<div>(a*b) = c; &lt;span style="font-family: simsun; "&gt; &lt;/span&gt; &nbsp;</div>
<div>一般用const修饰返回值为对象本身（非引用和指针）的情况多用于二目操作符重载函数并产生新对象的时候。 &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; &nbsp;一般情况下，函数的返回值为某个对象时，如果将其声明为const时，多用于操作符的重载。通常，不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的情况。原因如下：如果返回值为某个对象为const（const A test = A 实例）或某个对象的引用为const（const A&amp; test = A实例） ，则返回值具有const属性，则返回实例只能访问类A中的公有（保护）数据成员和const成员函数，并且不允许对其进行赋值操作，这在一般情况下很少用到。如果给采用&#8220;指针传递&#8221;方式的函数返回值加const修饰，那么函数返回值（即指针）的内容不能被修改，该返回值只能被赋给加const 修饰的同类型指针。如：</div>
<div>[cpp] view plaincopyprint?</div>
<div>const char * GetString(void); &nbsp;</div>
<div>如下语句将出现编译错误：</div>
<div>[cpp] view plaincopyprint?</div>
<div>char *str=GetString(); &nbsp;</div>
<div>正确的用法是：</div>
<div>[cpp] view plaincopyprint?</div>
<div>const char *str=GetString(); &nbsp;</div>
<div>&nbsp; &nbsp; &nbsp;函数返回值采用&#8220;引用传递&#8221;的场合不多，这种方式一般只出现在类的赙值函数中，目的是为了实现链式表达。如：</div>
<div>[cpp] view plaincopyprint?</div>
<div>class A &nbsp;</div>
<div>{ &nbsp;</div>
<div>&nbsp; &nbsp; &#8230; &nbsp;</div>
<div>&nbsp; &nbsp; A &amp;operate = (const A &amp;other); //负值函数 &nbsp;</div>
<div>} &nbsp;</div>
<div>&nbsp; &nbsp;A a,b,c; //a,b,c为A的对象 &nbsp;</div>
<div>&nbsp; &nbsp;&#8230; &nbsp;</div>
<div>&nbsp; &nbsp;a=b=c; //正常 &nbsp;</div>
<div>&nbsp; &nbsp;(a=b)=c; //不正常，但是合法 &nbsp;</div>
<div>若负值函数的返回值加const修饰，那么该返回值的内容不允许修改，上例中a=b=c依然正确。(a=b)=c就不正确了。</div>
<div>[思考3]： 这样定义赋值操作符重载函数可以吗？ &nbsp;</div>
<div>const A&amp; operator=(const A&amp; a);</div>
<div>&nbsp; &nbsp; 类成员函数中const的使用，一般放在函数体后，形如：void fun() const; &nbsp;任何不会修改数据成员的函数都因该声明为const类型。如果在编写const成员函数时，不慎修改了数据成员，或者调用了其他非const成员函数，编译器将报错，这大大提高了程序的健壮性。如：</div>
<div>[cpp] view plaincopyprint?</div>
<div>class Stack &nbsp;</div>
<div>{ &nbsp;</div>
<div>public: &nbsp;</div>
<div>&nbsp; void Push(int elem); &nbsp;</div>
<div>&nbsp; int Pop(void); &nbsp;</div>
<div>&nbsp; int GetCount(void) const; //const 成员函数 &nbsp;</div>
<div>private: &nbsp; &nbsp;</div>
<div>&nbsp; int m_num; &nbsp;</div>
<div>&nbsp; int m_data[100]; &nbsp;</div>
<div>}; &nbsp;</div>
<div>int Stack::GetCount(void) const &nbsp;</div>
<div>{ &nbsp;</div>
<div>&nbsp; ++m_num; //编译错误，企图修改数据成员m_num &nbsp;</div>
<div>&nbsp; Pop(); //编译错误，企图调用非const函数 &nbsp;</div>
<div>&nbsp; Return m_num; &nbsp;</div>
<div>} &nbsp;</div>
<div>[思考题答案] &nbsp;</div>
<div>1 这种方法不正确，因为声明指针的目的是为了对其指向的内容进行改变，而声明的指针e指向的是一个常量，所以不正确； &nbsp;</div>
<div>2 这种方法正确，因为声明指针所指向的内容可变； &nbsp;</div>
<div>3 这种做法不正确； &nbsp;</div>
<div>在const A::operator=(const A&amp; a)中，参数列表中的const的用法正确，而当这样连续赋值的时侯，问题就出现了： &nbsp;</div>
<div>[cpp] view plaincopyprint?</div>
<div>A a,b,c: &nbsp; &nbsp;</div>
<div>(a=b)=c; &lt;span style="font-family: simsun; "&gt; &lt;/span&gt; &nbsp;</div>
<div>因为a.operator=(b)的返回值是对a的const引用，不能再将c赋值给const常量。</div></div><img src ="http://www.cppblog.com/Tongy0/aggbug/193053.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2012-10-09 10:40 <a href="http://www.cppblog.com/Tongy0/archive/2012/10/09/193053.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载] #include&lt;iomanip&gt;怎么用？在c++中</title><link>http://www.cppblog.com/Tongy0/archive/2012/09/27/192172.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Thu, 27 Sep 2012 09:14:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2012/09/27/192172.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/192172.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2012/09/27/192172.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/192172.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/192172.html</trackback:ping><description><![CDATA[原文出处：<a href="http://zhidao.baidu.com/question/385301217.html">http://zhidao.baidu.com/question/385301217.html</a><br /><br />[转载] #include&lt;iomanip&gt;怎么用？在c++中<br /><br />在c++程序里面经常见到下面的头文件<br />　　#include &lt;iomanip&gt;<br />　　io代表输入输出，manip是manipulator（操纵器）的缩写(在c++上只能通过输入缩写才有效。）<br />　　iomanip的作用:<br />　　主要是对cin,cout之类的一些操纵运算子，比如setfill,setw,setbase,setprecision等等。它是I/O流控制头文件,就像C里面的格式化输出一样.以下是一些常见的控制函数的:<br />　　dec 置基数为10 相当于"%d"<br />　　hex 置基数为16 相当于"%X"<br />　　oct 置基数为8 相当于"%o"<br />　　setfill( 'c' ) 设填充字符为c<br />　　setprecision( n ) 设显示小数精度为n位<br />　　setw( n ) 设域宽为n个字符<br />　　这个控制符的意思是保证输出宽度为n。如：<br />　　cout &lt;&lt; setw( 3 ) &lt;&lt; 1 &lt;&lt; setw( 3 ) &lt;&lt; 10 &lt;&lt; setw( 3 ) &lt;&lt; 100 &lt;&lt; endl; 输出结果为<br />　　1 10100 （默认是右对齐）当输出长度大于3时(&lt;&lt;1000)，setw(3)不起作用。<br />　　&#9650;setw(n)用法： 通俗地讲就是预设宽度<br />　　如 cout&lt;&lt;setw(5)&lt;&lt;255&lt;&lt;endl;<br />　　结果是:<br />　　(空格)(空格)255<br />　　&#9650;setfill(char c) 用法 : 就是在预设宽度中如果已存在没用完的宽度大小，则用设置的字符c填充<br />　　如 cout&lt;&lt;setfill(&#8216;@&#8216;)&lt;&lt;setw(5)&lt;&lt;255&lt;&lt;endl;<br />　　结果是:<br />　　@@255<br />　　&#9650;setbase(int n) : 将数字转换为 n 进制.<br />　　如 cout&lt;&lt;setbase(8)&lt;&lt;setw(5)&lt;&lt;255&lt;&lt;endl;<br />　　cout&lt;&lt;setbase(10)&lt;&lt;setw(5)&lt;&lt;255&lt;&lt;endl;<br />　　cout&lt;&lt;setbase(16)&lt;&lt;255&lt;&lt;endl;<br />　　结果是:<br />　　(空格)(空格)377<br />　　(空格)(空格) 255<br />　　(空格)(空格)(空格) f f<br />　　&#9650; setprecision用法<br />　　使用setprecision(n)可控制输出流显示浮点数的数字个数。C++默认的流输出数值有效位是6。<br />　　如果setprecision(n)与setiosflags(ios::fixed)合用，可以控制小数点右边的数字个数。setiosflags(ios::fixed)是用定点方式表示实数。<br />　　如果与setiosflags(ios::scientific)合用， 可以控制指数表示法的小数位数。setiosflags(ios::scientific)是用指数方式表示实数。<br />　　setiosflags(ios::fixed) 固定的浮点显示<br />　　setiosflags(ios::scientific) 指数表示<br />　　setiosflags(ios::left) 左对齐<br />　　setiosflags(ios::right) 右对齐<br />　　setiosflags(ios::skipws) 忽略前导空白<br />　　setiosflags(ios::uppercase) 16进制数大写输出<br />　　setiosflags(ios::lowercase) 16进制小写输出<br />　　setiosflags(ios::showpoint) 强制显示小数点<br />　　setiosflags(ios::showpos) 强制显示符号<br />　　举例：<br />　　#include &lt;iostream.h&gt;<br />　　#include &lt;iomanip.h&gt;<br />　　using namespace std;<br />　　int main()<br />　　{<br />　　cout&lt;&lt;12345.0&lt;&lt;endl;//输出"12345"<br />　　cout&lt;&lt;setiosflags(ios::fixed)&lt;&lt;setprecision(3)&lt;&lt;1.2345&lt;&lt;endl;输出"1.235"（应该输出"1.235",而不是"1.234".因为要遵循4舍5入的原则）<br />　　cout&lt;&lt;setiosflags(ios::scientific)&lt;&lt;12345.0&lt;&lt;endl;//输出"1.234500e+004 "<br />　　cout&lt;&lt;setprecision(3)&lt;&lt;12345.0&lt;&lt;endl;//输出"1.23e+004 "<br />　　return 0;<br />　　}<img src ="http://www.cppblog.com/Tongy0/aggbug/192172.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2012-09-27 17:14 <a href="http://www.cppblog.com/Tongy0/archive/2012/09/27/192172.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载] C++模板：函数模板和模板函数 </title><link>http://www.cppblog.com/Tongy0/archive/2012/09/27/192171.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Thu, 27 Sep 2012 08:59:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2012/09/27/192171.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/192171.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2012/09/27/192171.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/192171.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/192171.html</trackback:ping><description><![CDATA[<div class="article_content" id="article_content">
<p><strong><span style="font-size: 18px; font-family: 'Microsoft YaHei'">原来出处：<a href="http://blog.csdn.net/beyondhaven/article/details/4204345">http://blog.csdn.net/beyondhaven/article/details/4204345</a><br /><br />[转载] C++模板：函数模板和模板函数 <br /><br />1.函数模板的声明和模板函数的生成</span></strong></p>
<p>&nbsp;</p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><strong><span style="font-size: 12px; font-family: 'Microsoft YaHei'">1.1函数模板的声明</span></strong></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">函数模板可以用来创建一个通用的函数，以支持多种不同的形参，避免重载函数的函数体重复设计。它的最大特点是把函数使用的数据类型作为参数。</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">函数模板的声明形式为：</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><strong><span style="font-size: 12px; font-family: 'Microsoft YaHei'">template&lt;typename 数据类型参数标识符&gt;</span></strong></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><strong><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&lt;返回类型&gt;&lt;函数名&gt;(参数表)</span></strong></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><strong><span style="font-size: 12px; font-family: 'Microsoft YaHei'">{</span></strong></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><strong><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&nbsp;&nbsp;&nbsp; 函数体</span></strong></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><strong><span style="font-size: 12px; font-family: 'Microsoft YaHei'">}</span></strong></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">其中，<strong>template</strong>是定义模板函数的关键字；template后面的尖括号不能省略；typename（或class)是声明数据类型参数标识符的关键字，用以说明它后面的标识符是数据类型标识符。这样，在以后定义的这个函数中，凡希望根据实参数据类型来确定数据类型的变量，都可以用数据类型参数标识符来说明，从而使这个变量可以适应不同的数据类型。例如：</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">template&lt;typename T&gt;</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">T fuc(T x, int y)</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">{</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&nbsp;&nbsp;&nbsp; T x;</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&nbsp;&nbsp;&nbsp; //&#8230;&#8230;</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">}</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">如果主调函数中有以下语句：</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">double d;</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">int a;</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">fuc(d,a);</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">则系统将用实参d的数据类型double去代替函数模板中的T生成函数：</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">double fuc(double x,int y)</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">{</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&nbsp;&nbsp;&nbsp; double x;</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&nbsp;&nbsp;&nbsp; //&#8230;&#8230;</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">}</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">函数模板只是声明了一个函数的描述即模板，不是一个可以直接执行的函数，只有根据实际情况用实参的数据类型代替类型参数标识符之后，才能产生真正的函数。</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">关键字typename也可以使用关键字class，这时数据类型参数标识符就可以使用所有的C++数据类型。</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><strong><span style="font-size: 12px; font-family: 'Microsoft YaHei'">1.2.模板函数的生成</span></strong></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">函数模板的数据类型参数标识符实际上是一个类型形参，在使用函数模板时，要将这个形参实例化为确定的数据类型。将类型形参实例化的参数称为模板实参，用模板实参实例化的函数称为模板函数。模板函数的生成就是将函数模板的类型形参实例化的过程。例如：</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">使用中应注意的几个问题：</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&#9332; 函数模板允许使用多个类型参数，但在template定义部分的每个形参前必须有关键字typename或class，即：</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><strong><span style="font-size: 12px; font-family: 'Microsoft YaHei'">template&lt;class 数据类型参数标识符1，&#8230;，class 数据类型参数标识符n&gt;</span></strong></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><strong><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&lt;返回类型&gt;&lt;函数名&gt;(参数表)</span></strong></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><strong><span style="font-size: 12px; font-family: 'Microsoft YaHei'">{</span></strong></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><strong><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&nbsp;&nbsp;&nbsp;&nbsp; 函数体</span></strong></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><strong><span style="font-size: 12px; font-family: 'Microsoft YaHei'">}</span></strong></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&#9333; 在template语句与函数模板定义语句&lt;返回类型&gt;之间不允许有别的语句。如下面的声明是错误的：</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">template&lt;class T&gt;</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">int I;</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">T min(T x,T y)</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">{</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&nbsp;&nbsp; 函数体</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">}</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&#9334; 模板函数类似于重载函数，但两者有很大区别：函数重载时，每个函数体内可以执行不同的动作，但同一个函数模板实例化后的模板函数都必须执行相同的动作。</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px"><br /></span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 18px; font-family: 'Microsoft YaHei'"><strong>2 函数模板的异常处理</strong></span><br /></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">函数模板中的模板形参可实例化为各种类型，但当实例化模板形参的各模板实参之间不完全一致时，就可能发生错误，如：</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">template&lt;typename T&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">void min(T &amp;x, T &amp;y)</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">{&nbsp;&nbsp;return (x&lt;y)?x:y;&nbsp;&nbsp;}</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">void func(int i, char j)</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">{</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&nbsp;&nbsp;&nbsp;min(i, i);</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&nbsp;&nbsp;&nbsp;min(j, j);</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&nbsp;&nbsp;&nbsp;min(i, j);</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&nbsp;&nbsp;&nbsp;min(j, i);</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">}</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">例子中的后两个调用是错误的，出现错误的原因是，在调用时，编译器按最先遇到的实参的类型隐含地生成一个模板函数，并用它对所有模板函数进行一致性检查，例如对语句</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">min(i, j)；</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">先遇到的实参i是整型的，编译器就将模板形参解释为整型，此后出现的模板实参j不能解释为整型而产生错误，此时没有隐含的类型转换功能。解决此种异常的方法有两种：</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&#9332;采用强制类型转换，如将语句min(i, j);改写为min(i,int( j));</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&#9333;用非模板函数重载函数模板</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">方法有两种：</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&#9312; 借用函数模板的函数体</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">此时只声明非模板函数的原型，它的函数体借用函数模板的函数体。如改写上面的例子如下：</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">template&lt;typename T&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">void min(T &amp;x, T &amp;y)</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">{&nbsp;&nbsp;return (x&lt;y)?x:y;&nbsp;&nbsp;}</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">int min(int,int);</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">void func(int i, char j)</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">{</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&nbsp;&nbsp;&nbsp;min(i, i);</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&nbsp;&nbsp;&nbsp;min(j, j);</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&nbsp;&nbsp;&nbsp;min(i, j);</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&nbsp;&nbsp;&nbsp;min(j, i);</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">}</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">执行该程序就不会出错了，因为重载函数支持数据间的隐式类型转换。</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&#9313; 重新定义函数体</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">就像一般的重载函数一样，重新定义一个完整的非模板函数，它所带的参数可以随意。C++中，函数模板与同名的非模板函数重载时，应遵循下列调用原则：</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&#8226; 寻找一个参数完全匹配的函数，若找到就调用它。若参数完全匹配的函数多于一个，则这个调用是一个错误的调用。</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&#8226; 寻找一个函数模板，若找到就将其实例化生成一个匹配的模板函数并调用它。</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&#8226; 若上面两条都失败，则使用函数重载的方法，通过类型转换产生参数匹配，若找到就调用它。</span></p>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">&#8226;若上面三条都失败，还没有找都匹配的函数，则这个调用是一个错误的调用。</span></p><span style="font-size: 12px; font-family: 'Microsoft YaHei'"><br /></span>
<p style="margin-top: 1.5pt; text-indent: 30pt"><span style="font-size: 12px; font-family: 'Microsoft YaHei'">此为转载文章，文章出处没有了。请大家见谅。</span></p><br /></div><img src ="http://www.cppblog.com/Tongy0/aggbug/192171.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2012-09-27 16:59 <a href="http://www.cppblog.com/Tongy0/archive/2012/09/27/192171.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>矩阵变换需要注意的一点</title><link>http://www.cppblog.com/Tongy0/archive/2012/09/18/191122.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Tue, 18 Sep 2012 08:24:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2012/09/18/191122.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/191122.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2012/09/18/191122.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/191122.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/191122.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;多数情况下，在游戏开发过程中，我们需要经常用变换来设置角色的变换。下面以平移、缩放、旋转来说明一点在矩阵变换中需要注意的地方。<br />假设有如下数据：<br />D3DXMatrix rotateMat;<br />D3DXMatrix scaleMat;<br />D3DXMatrix translateMat;<br />......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 这里的 ...... 表示，经过了一系列的变换，在接下来的代码中，rotateMat、scalMat、translateMat已经是经过变换的了。<br />D3DXMatrix worldMat;//该矩阵用于保存上面三个合成的最终变换信息<br />D3DXMatrixIdentity(&amp;worldMat);<br /><span style="color: red">D3DXMatrixMultiply(&amp;worldMat, &amp;rotateMat, &amp;worldMat);//注意格式，需要如此写。</span><br /><span style="color: red">D3DXMatrixMultiply(&amp;worldMat, &amp;scaleMat, &amp;worldMat); //注意格式，需要如此写。</span><br /><span style="color: red">D3DXMatrixMultiply(&amp;worldMat, &amp;translateMat, &amp;world);//注意格式，需要如此写。</span><br /><img src ="http://www.cppblog.com/Tongy0/aggbug/191122.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2012-09-18 16:24 <a href="http://www.cppblog.com/Tongy0/archive/2012/09/18/191122.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>矩阵、欧拉角、轴-角对、四元数随笔</title><link>http://www.cppblog.com/Tongy0/archive/2012/09/10/190126.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Mon, 10 Sep 2012 09:08:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2012/09/10/190126.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/190126.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2012/09/10/190126.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/190126.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/190126.html</trackback:ping><description><![CDATA[<p>矩阵、欧拉角、轴-角对、四元数随笔</p>
<p>一、矩阵<br />&nbsp;&nbsp;在 3D 游戏中，可以使用矩阵来表示一个物体的旋转。<br />&nbsp;&nbsp;1) 优点：<br />&nbsp;&nbsp;&nbsp;&nbsp;个人认为，理解起来最为直观。<br />&nbsp;&nbsp;&nbsp;&nbsp;像现成的DXSDK库中也提供了十分完善的相关接口<br />&nbsp;&nbsp;&nbsp;&nbsp;一个矩阵即可表示多种变换的组合<br />&nbsp;&nbsp;2) 缺点：<br />&nbsp;&nbsp;&nbsp;&nbsp;每次计算都会产生误差，因此，需要经常规范化。<br />&nbsp;&nbsp;&nbsp;&nbsp;耗的内存较多些。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />二、欧拉角<br />&nbsp;&nbsp;欧拉角指的是：以世界坐标系为参考坐标系(一定记住是世界坐标系)，使用x,y,z三个值来分别表示绕(世界的)x轴、y轴、z轴旋转的角度量值。其取值是在[0, 360]间。一般用roll, pitch, yaw来表示这些分量的旋转值。因为是以世界坐标系为参考坐标系，因此每一次的旋转都不会影响到后续的旋转转轴。即：它无法表示任意轴的旋转。<br />&nbsp;&nbsp;1) 优点：<br />&nbsp;&nbsp;&nbsp;&nbsp;理解起来很直观。<br />&nbsp;&nbsp;2) 缺点：<br />&nbsp;&nbsp;&nbsp;&nbsp;会有万向锁问题。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />三、轴-角对<br />&nbsp;&nbsp;其实轴-角对与欧拉角(个人认为)是有一定的关系的。因为欧拉角说的是分别(注意：是分别)绕(以世界坐标系为参考坐标系的)三个轴旋转一定的角度。其实这三次的旋转可以最终转换到一次变换。即：最终可表示为：绕某一旋转轴旋转一定角度的变换。(意思就是说：那三次变换我们最终可以计算出旋转轴以及绕该旋转轴旋转的角度量)。<br />&nbsp;&nbsp;1) 缺点：<br />&nbsp;&nbsp;&nbsp;&nbsp;轴-角对表示法：插值不平滑，可能会有跳跃。(文档上说，欧拉角同样存在这个问题)<br />&nbsp;&nbsp;2) 优点：<br />&nbsp;&nbsp;&nbsp;&nbsp;可解决欧拉角的万向锁问题。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />四、四元数<br />&nbsp;&nbsp;四元数定义：q = w + xi + yj + zk<br />&nbsp;&nbsp;<br />&nbsp;&nbsp;注意：<br />&nbsp;&nbsp;&nbsp;&nbsp;1) 四元数可以归一化，并且只有归一化的四元数才用来描述旋转<br />&nbsp;&nbsp;&nbsp;&nbsp;2) 四元数与轴-角对很像。因为四元数描述的也是一个旋转轴与一个绕着该旋转轴旋转的量值(即：角度或弧度)。但四元数与轴-角对不等价。它们的关系如下：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;假如：轴-角对的值如下：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;轴为：n<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;角为：theta<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;则，对应的四元数中的w、x、y、z的值分别为：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w = cos(theta / 2)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x = nx * sin(theta / 2)&nbsp;&nbsp;// nx 是轴 n 的 x 分量<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y = ny * sin(theta / 2)&nbsp;&nbsp;// ny 是轴 n 的 y 分量<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;z = nz * sin(theta / 2)&nbsp;&nbsp;// nz 是轴 n 的 z 分量</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;3) 四元数的乘法意义：<br />&nbsp;&nbsp;&nbsp;&nbsp;Q = Q1 * Q2表示的是：Q先做Q2的旋转，再做Q1的旋转的结果，而且多个四元数的旋转也是要以合并的。<br />&nbsp;&nbsp;&nbsp;&nbsp;4) 四元数做一次乘法需要16次乘法和加法，而3x3矩阵需要27次。所以有多次旋转操作时，使用四元数计算效率更高些。<br />&nbsp;&nbsp;&nbsp;&nbsp;5) 四元数的插值过度平滑。最常用的是线性插值。</p><img src ="http://www.cppblog.com/Tongy0/aggbug/190126.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2012-09-10 17:08 <a href="http://www.cppblog.com/Tongy0/archive/2012/09/10/190126.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载] 三维变换</title><link>http://www.cppblog.com/Tongy0/archive/2012/08/31/188909.html</link><dc:creator>Jacc.Kim</dc:creator><author>Jacc.Kim</author><pubDate>Fri, 31 Aug 2012 08:31:00 GMT</pubDate><guid>http://www.cppblog.com/Tongy0/archive/2012/08/31/188909.html</guid><wfw:comment>http://www.cppblog.com/Tongy0/comments/188909.html</wfw:comment><comments>http://www.cppblog.com/Tongy0/archive/2012/08/31/188909.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Tongy0/comments/commentRss/188909.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Tongy0/services/trackbacks/188909.html</trackback:ping><description><![CDATA[<div>原文转自：<a href="http://www.gesoftfactory.com/developer/Transform.htm">http://www.gesoftfactory.com/developer/Transform.htm</a> 
<p>(提示：原文有图片。)<a name="三维变换"><strong><span style="font-size: 24pt; font-family: 宋体"><br /><br />三维变换</span></strong></a></p>
<p><span style="font-family: 宋体">在使用三维图形的应用程序中，可以用变换做以下事情：</span></p>
<ul type="disc"><li><span style="font-family: 宋体">描述一个物体相对于另一个物体的位置。</span></li><li><span style="font-family: 宋体">旋转并改变物体的大小。</span></li><li><span style="font-family: 宋体">改变观察的位置、方向和视角。</span> </li></ul>
<p><span style="font-family: 宋体">可以用一个4 x 4矩阵将任意点（x，y，z）变换为另一个点（x'，y'，z'）。</span></p>
<p><span style="font-family: 宋体"></span></p>
<p><span style="font-family: 宋体">对（x，y，z）和矩阵执行以下操作产生点（x'，y'，z'）。</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">最常见的变换是平移、旋转和缩放。可以将产生这些效果的矩阵合并成单个矩阵，这样就可以一次计算多种变换。例如，可以构造单个矩阵，对一系列的点进行平移和旋转。更多信息，请参阅<u>矩阵串接</u>。</span></p>
<p><span style="font-family: 宋体">矩阵以行列顺序书写。一个沿每根轴均匀缩放顶点的矩阵，也称为统一缩放，用如下数学符号表示。</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">在C++应用程序中，Microsoft&#174; Direct3D&#174;使用<u>D3DMATRIX</u>结构，将矩阵声明为一个二维数组。以下示例代码显示了如何初始化一个<strong>D3DMATRIX</strong>结构，使之成为一个统一缩放矩阵。</span></p>
<p><span style="font-size: 10pt; color: blue; font-family: 宋体">//</span><span style="font-size: 10pt; color: green; font-family: 宋体"> 本例中，s为浮点类型的变量</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 10pt; font-family: 宋体">D3DMATRIX scale = {</span></p>
<p><span style="font-size: 10pt; font-family: 宋体">&nbsp;&nbsp;&nbsp; s,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,</span></p>
<p><span style="font-size: 10pt; font-family: 宋体">&nbsp;&nbsp;&nbsp; 0.0f,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.0f,</span></p>
<p><span style="font-size: 10pt; font-family: 宋体">&nbsp;&nbsp;&nbsp; 0.0f,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,</span></p>
<p><span style="font-size: 10pt; font-family: 宋体">&nbsp;&nbsp;&nbsp; 0.0f,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0f,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0f</span></p>
<p><span style="font-size: 10pt; font-family: 宋体">};</span></p>
<div align="center"><span style="font-family: 宋体">
<hr align="center" width="100%" size="1" />
</span></div>
<h1><a name="平移和缩放">平移和缩放</a></h1>
<div align="center"><span>
<hr align="center" width="100%" size="1" />
</span></div>
<h2><span style="font-family: 黑体">平移</span></h2>
<p>以下变换将点（x，y，z）平移到一个新的点（x'，y'，z'）。</p>
<p>&nbsp;</p>
<p>可以在C++应用程序中手工创建一个平移矩阵。以下示例代码显示了的一个函数的源码，该函数创建一个矩阵用于平移顶点。</p><pre><span style="font-size: 10pt">D3DXMATRIX Translate(const float dx, const float dy, const float dz) {</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; D3DXMATRIX ret;</span></pre><pre>&nbsp;</pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; D3DXMatrixIdentity(&amp;ret);&nbsp;<span style="color: blue">//</span><span style="color: green"> 由Direct3DX实现</span></span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; ret(3, 0) = dx;</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; ret(3, 1) = dy;</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; ret(3, 2) = dz;</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; return ret;</span></pre><pre><span style="font-size: 10pt">}&nbsp;&nbsp;&nbsp; <span style="color: blue">//</span><span style="color: green"> 平移结束</span></span></pre>
<p>为了方便，Direct3DX工具库提供了<u>D3DXMatrixTranslation</u>函数。</p>
<h2><span style="font-family: 黑体">缩放</span></h2>
<p>以下变换用指定值缩放点（x，y，z）的x-，y-和z-方向，产生新的点（x'，y'，z'）。</p>
<p>&nbsp;</p>
<div align="center"><span>
<hr align="center" width="100%" size="1" />
</span></div>
<p><a name="旋转"><strong><span style="font-size: 24pt; font-family: 宋体">旋转</span></strong></a></p>
<div align="center"><span style="font-family: 宋体">
<hr align="center" width="100%" size="1" />
</span></div>
<p><span style="font-family: 宋体">这里描述的变换是基于左手坐标系的，也许和别处见到的变换矩阵不同。更多信息，请参阅<u>三维坐标系</u>。</span></p>
<p><span style="font-family: 宋体">以下变换将点（x，y，z）围绕x轴旋转，产生新的点（x'，y'，z'）。</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">以下变换将点围绕y轴旋转。</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">以下变换将点围绕z轴旋转。</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">在这些示例矩阵中，希腊字母（&#952;）表示旋转的角度，以弧度为单位。当沿着旋转轴朝原点看时，角度以顺时针方向计量。</span></p>
<p><span style="font-family: 宋体">C++应用程序可以用Direct3D扩展（D3DX）工具库提供的<u>D3DXMatrixRotationX</u>，<u>D3DXMatrixRotationX</u>和<u>D3DXMatrixRotationX</u>函数创建旋转矩阵。以下示例是<strong>D3DXMatrixRotationX</strong>函数的源码。</span></p><pre><span style="font-size: 10pt">D3DXMATRIX* WINAPI D3DXMatrixRotationX</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; ( D3DXMATRIX *pOut, float angle )</span></pre><pre><span style="font-size: 10pt">{</span></pre><pre><span style="font-size: 10pt">#if DBG</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; if(!pOut)</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return NULL;</span></pre><pre><span style="font-size: 10pt">#endif</span></pre><pre>&nbsp;</pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; float sin, cos;</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; sincosf(angle, &amp;sin, &amp;cos);&nbsp;<span style="color: blue">//</span><span style="color: green"> 计算角度的正弦和余弦值。</span></span></pre><pre>&nbsp;</pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; <span>pOut</span>-&gt;_11 = 1.0f; pOut-&gt;_12 =&nbsp;0.0f;&nbsp;&nbsp; pOut-&gt;_13 = 0.0f; pOut-&gt;_14 = 0.0f;</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; <span>pOut</span>-&gt;_21 = 0.0f; pOut-&gt;_22 =&nbsp;cos;&nbsp;&nbsp;&nbsp; pOut-&gt;_23 = sin;&nbsp;pOut-&gt;_24 = 0.0f;</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; <span>pOut</span>-&gt;_31 = 0.0f; pOut-&gt;_32 = -sin; &nbsp;&nbsp;&nbsp;pOut-&gt;_33 = cos;&nbsp;pOut-&gt;_34 = 0.0f;</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; <span>pOut</span>-&gt;_41 = 0.0f; pOut-&gt;_42 =&nbsp;0.0f;&nbsp;&nbsp; pOut-&gt;_43 = 0.0f; pOut-&gt;_44 = 1.0f;</span></pre><pre>&nbsp;</pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; return pOut;</span></pre><pre><span style="font-size: 10pt">}</span></pre>
<p>&nbsp;</p>
<p>( D3DXMATRIX *pOut, float angle )</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>if(!pOut)</span></p>
<p>return NULL;</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>float sin, cos;</span></p>
<p>sincosf(angle, &amp;sin, &amp;cos);&nbsp;<span style="color: blue">//</span><span style="color: green"> Determine sin and cos of angle.</span></span></p>
<p>&nbsp;</p>
<p>pOut-&gt;_11 = 1.0f; pOut-&gt;_12 =&nbsp;0.0f;&nbsp;&nbsp; pOut-&gt;_13 = 0.0f; pOut-&gt;_14 = 0.0f;</span></p>
<p>pOut-&gt;_21 = 0.0f; pOut-&gt;_22 =&nbsp;cos;&nbsp;&nbsp;&nbsp; pOut-&gt;_23 = sin;&nbsp;pOut-&gt;_24 = 0.0f;</span></p>
<p>pOut-&gt;_31 = 0.0f; pOut-&gt;_32 = -sin;&nbsp;&nbsp;&nbsp; pOut-&gt;_33 = cos;&nbsp;pOut-&gt;_34 = 0.0f;</span></p>
<p>pOut-&gt;_41 = 0.0f; pOut-&gt;_42 =&nbsp;0.0f;&nbsp;&nbsp; pOut-&gt;_43 = 0.0f; pOut-&gt;_44 = 1.0f;</span></p>
<p>&nbsp;</p>
<p>return pOut;</span></p>
<p>&nbsp;</p>
<div align="center"><span style="font-family: 宋体">
<hr align="center" width="100%" size="1" />
</span></div>
<p><a name="矩阵串接"><strong><span style="font-size: 24pt; font-family: 宋体">矩阵串接</span></strong></a></p>
<div align="center"><span style="font-family: 宋体">
<hr align="center" width="100%" size="1" />
</span></div>
<p><span style="font-family: 宋体">使用矩阵的一个优势就是可以通过把两个以上的矩阵相乘，将它们的效果合并在一起。这意味着，要先旋转一个建模然后把它平移到某个位置，无需使用两个矩阵，只要把旋转矩阵和平移矩阵相乘，产生一个包含了所有效果的合成矩阵。这个过程被称为矩阵串接，可以写成以下公式。</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">在这个公式中，C是将被创建的合成矩阵，M<sub>1</sub>到<span>M<sub>n</sub>是矩阵C包含的单个矩阵。虽然大多数情况下，只需要串接两三个矩阵，但实际上并没有数量上的限制。</span></span></p>
<p><span style="font-family: 宋体">可以使用<u>D3DXMatrixMultiply</u>函数进行矩阵乘法。</span></p>
<p><span style="font-family: 宋体">进行矩阵乘法时先后次序是至关重要的。前面的公式反映了矩阵串接从左到右的规则。也就是说，用来创建合成矩阵的每个矩阵产生的直观效果会按从左到右的次序出现。下面显示了一个典型的世界变换矩阵。想象一下给一个旋转飞行的碟子创建世界变换矩阵。应用程序也许想让飞行的碟子绕它的中心&#8212;&#8212;建模空间中的y轴&#8212;&#8212;旋转，然后把它平移到场景中的另一个位置。要实现这样的效果，首先创建一个旋转矩阵，然后将它与平移矩阵相乘，如以下公式所示。</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">在这个公式中，<span>R<sub>y</sub></span>是绕y轴的旋转矩阵，<span>T<sub>w</sub>是平移到世界坐标中某个位置的矩阵。</span></span></p>
<p><span style="font-family: 宋体">矩阵相乘的顺序很重要，因为矩阵乘法是不可交换的，这和两个标量相乘不同。将矩阵以相反的顺序相乘会产生这样的直观效果：先把飞行中的碟子平移到世界空间中的某个位置，然后将它围绕世界坐标的原点旋转。</span></p>
<p><span style="font-family: 宋体">无论创建何种类型的矩阵，都要记住从左到右的规则，这样才能保证得到想要的效果。</span></p>
<div align="center"><span style="font-family: 宋体">
<hr align="center" width="100%" size="1" />
</span></div>
<h1><a name="世界变换"></a><a name="_世界变换"></a>世界变换</h1>
<div align="center"><span>
<hr align="center" width="100%" size="1" />
</span></div>
<p>对世界变换的讨论介绍了基本概念，并提供了如何在Microsoft&#174; Direct3D&#174;应用程序中设置世界变换矩阵的细节。</p>
<h2><span style="font-family: 黑体">什么是世界变换</span></h2>
<p>世界变换将坐标从建模空间，在这个空间中的顶点相对于建模的局部原点定义，转变到世界空间，在这个空间中的顶点相对于场景中所有物体共有的原点定义。本质上，世界变换将一个建模放到世界中，并由此而得名。下图描绘了世界坐标系统和建模的局部坐标系统间的关系。</p>
<p>&nbsp;</p>
<p>世界变换可以包含任意数量的平移、旋转和缩放的合并。有关对变换的数学讨论，请参阅<u>三维变换</u>。</p>
<h2><span style="font-family: 黑体">设置世界矩阵</span></h2>
<p>同任何其它变换一样，通过将一系列变换矩阵串接成单个矩阵，应用程序可以创建包含这些矩阵全部效果的世界矩阵。最简单的情况下，建模在世界的原点并且它的局部坐标轴与世界空间的方向相同，这时世界矩阵就是单位矩阵。更通常的情况下，世界矩阵是一系列矩阵的合成，包含一个平移矩阵，并且根据需要可能有一个以上的旋转矩阵。</p>
<p>以下示例，来自一个用C++编写的假想三维建模类，使用Direct3D扩展（D3DX）工具库提供的帮助函数创建了一个世界矩阵，这个世界矩阵包含了三个旋转矩阵，用于调整三维建模的方向，以及一个平移矩阵，用来根据建模在世界空间中的相对坐标重新确定它的位置。</p><pre><span style="font-size: 10pt; color: blue">/*</span></pre><pre><span style="font-size: 10pt; color: green"> * 根据本示例的目的，假设以下变量都是有效的并经过初始化。</span></pre><pre style="text-indent: 5pt"><span style="font-size: 10pt; color: green">*</span></pre><pre><span style="font-size: 10pt; color: green"> * 变量m_xPos，m_yPos，m_zPos包含了建模在世界坐标中的位置。</span></pre><pre style="text-indent: 5pt"><span style="font-size: 10pt; color: green">*</span></pre><pre><span style="font-size: 10pt; color: green"> * 变量m_fPitch，m_fYaw和m_fRoll为浮点数，包含了建模的方向，</span></pre><pre><span style="font-size: 10pt; color: green"> * 用pitch，yaw和roll旋转角表示，以弧度为单位。</span></pre><pre> <span style="font-size: 10pt; color: blue">*/</span></pre><pre> </pre><pre><span style="font-size: 10pt">void</span><span style="font-size: 10pt"> C3DModel::MakeWorldMatrix( D3DXMATRIX* pMatWorld )</span></pre><pre><span style="font-size: 10pt">{</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; D3DXMATRIX MatTemp;&nbsp;<span style="color: blue">//</span><span style="color: green"> 用于旋转的临时矩阵</span></span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; D3DXMATRIX MatRot;&nbsp;&nbsp; <span style="color: blue">//</span><span style="color: green"> 最终的旋转矩阵，应用于pMatWorld.</span></span></pre><pre> </pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue">//</span><span style="color: green"> 使用从左到右的矩阵串接顺序，在旋转之前对物体在世界空间中</span></span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; <span style="color: blue">//</span><span style="color: green"> 的位置进行平移。</span></span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; D3DXMatrixTranslation(pMatWorld, m_xPos, m_yPos, m_zPos);</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; D3DXMatrixIdentity(&amp;MatRot);</span></pre><pre>&nbsp;</pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; <span style="color: blue">//</span><span style="color: green"> 现在将方向变量应用于世界矩阵</span></span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; if(m_fPitch || m_fYaw || m_fRoll) {</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">//</span><span style="color: green"> 产生并合成旋转矩阵。</span></span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D3DXMatrixRotationX(&amp;MatTemp, m_fPitch);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">//</span><span style="color: green"> Pitch</span></span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D3DXMatrixMultiply(&amp;MatRot, &amp;MatRot, &amp;MatTemp);</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D3DXMatrixRotationY(&amp;MatTemp, m_fYaw);&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue">//</span><span style="color: green"> Yaw</span></span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D3DXMatrixMultiply(&amp;MatRot, &amp;MatRot, &amp;MatTemp);</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D3DXMatrixRotationZ(&amp;MatTemp, m_fRoll);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: blue">//</span><span style="color: green"> Roll</span></span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D3DXMatrixMultiply(&amp;MatRot, &amp;MatRot, &amp;MatTemp);</span></pre><pre> </pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue">//</span><span style="color: green"> 应用旋转矩阵，得到最后的世界矩阵。</span></span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D3DXMatrixMultiply(pMatWorld, &amp;MatRot, pMatWorld);</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; }</span></pre><pre><span style="font-size: 10pt">}</span></pre>
<p>当准备好世界变换矩阵后，应该调用<u>IDirect3DDevice9::SetTransform</u>方法设置它，并把第一个参数指定<u>D3DTS_WORLD</u>宏。</p>
<p><strong><span style="font-family: 宋体">注意</span></strong><strong><span>&nbsp;&nbsp;&nbsp; </span></strong><span style="font-family: 宋体">Direct3D</span><span style="font-family: 宋体">使用应用程序设置的世界和观察矩阵配置许多内部数据结构。应用程序每次设置新的世界或观察矩阵时，系统都要重新计算相关的内部数据结构。频繁地设置这些矩阵&#8212;&#8212;例如，每帧上千次&#8212;&#8212;是计算量很大的。通过将世界矩阵和观察矩阵串接成一个世界</span>/<span style="font-family: 宋体">观察矩阵，并将该矩阵设置为世界矩阵，然后将观察矩阵设置为单位矩阵，应用程序可以将所需的计算次数减到最少。最好保存一份单独的世界矩阵和观察矩阵的副本在高速缓存中，这样就可以根据需要修改、串接及重置世界矩阵。为清晰起见，本文档中的</span>Direct3D<span style="font-family: 宋体">示例很少使用这项优化。</span></p>
<div align="center"><span>
<hr align="center" width="100%" size="1" />
</span></div>
<h1><a name="观察变换"></a><a name="_观察变换"></a>观察变换</h1>
<div align="center"><span>
<hr align="center" width="100%" size="1" />
</span></div>
<p>本节介绍观察变换的基本概念，并提供有关如何在Microsoft&#174; Direct3D&#174;应用程序中设置观察矩阵的细节。信息被分为以下主题。</p>
<ul type="disc"><li><u><a href="http://www.gesoftfactory.com/developer/Transform.htm#_什么是观察变换？"><span style="font-family: 宋体">什么是观察变换？</a></span></u></li><li><u><a href="http://www.gesoftfactory.com/developer/Transform.htm#_设置观察矩阵"><span style="font-family: 宋体">设置观察矩阵</a></span></u> </li></ul>
<h2><a name="什么是观察变换？"></a><a name="_什么是观察变换？"></a><span style="font-family: 黑体">什么是观察变换？</span></h2>
<p>观察变换根据观察者在世界空间中的位置，把顶点变换到摄像机空间。在摄像机空间中，摄像机，或观察者，位于原点，朝<span>sz</span>轴的正向看去。再次提醒一下，因为Direct3D使用左手坐标系，所以z轴的正向是朝着场景的。观察矩阵根据摄像机的位置&#8212;&#8212;摄像机空间的原点&#8212;&#8212;和方向重定位世界中的所有物体。</p>
<p>有两方法可以创建观察矩阵。所有情况下，摄像机在世界空间中的逻辑位置和方向会被用作起始点来创建观察矩阵，得到的观察矩阵会被应用于场景中的三维建模。观察矩阵平移并旋转物体，将它们放入摄像机空间中，摄像机位于原点。创建观察矩阵的一种方法是把平移矩阵和围绕每根坐标轴旋转的旋转矩阵合并。这种方法使用了以下通用矩阵公式。</p>
<p>&nbsp;</p>
<p>在这个公式中，<em>V</em>是要创建的观察矩阵，<em>T</em>是在世界中重定位物体的平移矩阵，<em>R</em><sub>x</sub>到<em><span>R</em><sub>z</sub></span>分别是绕x轴，y轴和z轴旋转物体的旋转矩阵。平移和旋转矩阵基于摄像机在世界空间中逻辑位置和方向。因此，如果摄像机在世界中的逻辑位置是&lt;10，20，100&gt;，那么平移矩阵的目的是沿x轴移动物体-10单位，沿y轴移动-20单位，沿z轴移动-100单位。公式中的旋转矩阵基于摄像机的方向，根据摄像机空间的坐标轴与世界空间的坐标轴间的夹角决定。例如，如果前面提到的摄像机是垂直向下放的，那么它的z轴与世界空间的z轴有90度夹角，如下图所示。</p>
<p>&nbsp;</p>
<p>旋转矩阵将角度相同但方向相反的旋转量应用于场景中的建模。这个摄像机的观察矩阵包含了一个绕x轴-90度的旋转。旋转矩阵与平移矩阵合并生成观察矩阵，观察矩阵调整物体在场景中的位置和方向，使它们的顶部朝着摄像机，看起来就好像摄像机在建模的上方一样。</p>
<h2><a name="设置观察矩阵"></a><a name="_设置观察矩阵"></a><span style="font-family: 黑体">设置观察矩阵</span></h2>
<p><u>D3DXMatrixLookAtLH</u>和<u>D3DXMatrixLookAtRH</u>辅助函数根据摄像机的位置和被观察点创建一个观察矩阵。</p>
<p>以下示例代码创建了一个用于右手系的观察矩阵。</p><pre>D3DXMATRIX out;</pre><pre>D3DXVECTOR3 <span>eye(2,3,3);</span></pre><pre>D3DXVECTOR3 <span>at(0,0,0);</span></pre><pre>D3DXVECTOR3 <span>up(0,1,0);</span></pre><pre><span>D3DXMatrixLookAtRH(</span>&amp;out, &amp;eye, &amp;at, &amp;up);</pre>
<p>Direct3D使用应用程序设置的世界矩阵和观察矩阵配置许多内部数据结构。每次应用程序设置一个新的世界矩阵或观察矩阵，系统都要重新计算相关的内部数据结构。频繁地设置这些矩阵&#8212;&#8212;例如，每帧20,000次&#8212;&#8212;计算量非常大。通过将世界矩阵和观察矩阵串接成一个世界/观察矩阵，并将之设置为世界矩阵，然后将观察矩阵设为单位矩阵，应用程序可以将所需的计算量减到最小。最好保存一份单独的世界矩阵和观察矩阵的副本在高速缓存中，这样就可以根据需要修改、串接及重置世界矩阵。为清晰起见，Direct3D示例很少使用这项优化。</p>
<div align="center"><span>
<hr align="center" width="100%" size="1" />
</span></div>
<h1><a name="投影变换"></a><a name="_投影变换"></a>投影变换</h1>
<div align="center"><span>
<hr align="center" width="100%" size="1" />
</span></div>
<p>可以认为投影变换是控制摄像机的内部参数，这选择摄像机的镜头有些相似。这是三种类型的变换中最为复杂的。对投影变换的讨论被分为以下主题。</p>
<ul type="disc"><li><u><a href="http://www.gesoftfactory.com/developer/Transform.htm#什么是投影变换？"><span style="font-family: 宋体">什么是投影变换？</a></span></u></li><li><u><a href="http://www.gesoftfactory.com/developer/Transform.htm#设置投影矩阵"><span style="font-family: 宋体">设置投影矩阵</a></span></u></li><li><u><a href="http://www.gesoftfactory.com/developer/Transform.htm#W友好投影矩阵">W<span style="font-family: 宋体">友好投影矩阵</a></span></u> </li></ul>
<div align="center"><span>
<hr align="center" width="100%" size="1" />
</span></div>
<p><a name="什么是投影变换？"><strong><span style="font-size: 24pt; font-family: 宋体">什么是投影变换？</span></strong></a></p>
<div align="center"><span style="font-family: 宋体">
<hr align="center" width="100%" size="1" />
</span></div>
<p><span style="font-family: 宋体">典型的投影变换就是一个缩放和透视投影。投影变换将视棱锥转变为一个立方体。因为视棱锥的近端比远端小，所以这就产生了离摄像机近的物体被放大的效果，这就是透视如何被应用于场景的。</span></p>
<p><span style="font-family: 宋体">在<u>视棱锥</u>中，摄像机与观察变换空间的原点之间的距离被定义为<em>D</em>，因此投影矩阵看起来是这样：</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">通过在z方向平移-<em>D</em>，观察矩阵将摄像机平移到原点。平移矩阵如下所示：</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">将平移矩阵与投影矩阵相乘（T*P），得到合成的投影矩阵。如下：</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">下图描绘了透视投影如何将视棱锥转变到新的坐标空间。注意棱锥变成了立方体，同时原点从场景的右上角移到了中心。（译注：应该是从前裁剪平面的中心移到了原点）</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">在透视变换中，x和y方向的边界值是-1和1。Z方向的边界值分别是，0对应于前平面，1对应于后平面。</span></p>
<p><span style="font-family: 宋体">这个矩阵根据指定的从摄像机到近裁剪平面的距离，平移并缩放物体，但没有考虑视角（<em><span>fov</em></span>），并且用它为远处物体产生的z值可能几乎相同，这使深度比较变得困难。以下矩阵解决了这些问题，并根据视区的纵横比调整顶点，这使它成为透视投影的一个很好的选择。</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">在这个矩阵中，<em>Z</em><sub>n</sub>是近裁剪平面的z值。变量<em>w</em>，<em>h</em>和<em>Q</em>有以下含义。注意<span><em>fov</em><sub>w</sub>和<em>fov</em><sub>h</sub>表示视区在水平和垂直方向上的视角，以弧度为单位。</span></span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">对应用程序而言，使用视角的角度定义x和y的比例系数可能不如使用视区在水平和垂直方向上的大小（在摄像机空间中）方便。可以用数学推导，得出下面两个使用视区大小计算<em>w</em>和<em>h</em>的公式，它们与前面的公式是等价的。</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">在这两个公式中，<em>Z</em><sub>n</sub>表示近裁剪平面的位置，<em><span>V</em><sub>w</sub></span>和<em><span>V</em><sub>h</sub></span>变量表示视区在摄像机空间的宽和高。</span></p>
<p><span style="font-family: 宋体">对于C++应用程序而言，这两个大小直接对应于<u>D3DVIEWPORT9</u>结构的<strong>Width</strong>和<strong>Height</strong>成员。（译注：虽然直接对应，但是不等价的，因为<span><em>V</em><sub>w</sub>和<em>V</em><sub>h</sub>位于摄像机空间，而<strong>Width</strong>和<strong>Height</strong>位于屏幕空间）</span></span></p>
<p><span style="font-family: 宋体">无论决定使用什么公式，非常重要的一点是要尽可能将<em>Z</em><sub>n</sub>设得大，因为接近摄像机的z值变化不大。这使得用16位z缓存的深度比较变得有点复杂。</span></p>
<p><span style="font-family: 宋体">同世界变换和观察变换一样，应用程序调用<u>IDirect3DDevice9::SetTransform</u>方法设置投影矩阵。</span></p>
<div align="center"><span style="font-family: 宋体">
<hr align="center" width="100%" size="1" />
</span></div>
<p><a name="设置投影矩阵"><strong><span style="font-size: 24pt; font-family: 宋体">设置投影矩阵</span></strong></a></p>
<div align="center"><span style="font-family: 宋体">
<hr align="center" width="100%" size="1" />
</span></div>
<p><span style="font-family: 宋体">以下<span>ProjectionMatrix</span>示例函数设置了前后裁剪平面，以及在水平和垂直方向上视角的角度。此处的代码与<u>什么是投影矩阵？</u>主题中讨论的方法相似。视角应该小于弧度&#960;。</span></p><pre><span style="font-size: 10pt">D3DXMATRIX </span></pre><pre><span style="font-size: 10pt">ProjectionMatrix</span><span style="font-size: 10pt">(const float near_plane, // 到近裁剪平面的距离</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const float far_plane,&nbsp;// 到远裁剪平面的距离</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const float fov_horiz,&nbsp;// 水平视角，用弧度表示</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;const float fov_vert)&nbsp;&nbsp; // 垂直视角，用弧度表示</span></pre><pre><span style="font-size: 10pt">{</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; float&nbsp;&nbsp;&nbsp; h, w, Q;</span></pre><pre>&nbsp;</pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; w = (float)1/tan(fov_horiz*0.5);&nbsp;// 1/tan(x) == cot(x)</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; h = (float)1/tan(fov_vert*0.5);&nbsp;&nbsp; // 1/tan(x) == cot(x)</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; Q = far_plane/(far_plane - near_plane);</span></pre><pre>&nbsp;</pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; D3DXMATRIX ret;</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; <span>ZeroMemory</span>(&amp;ret, sizeof(ret));</span></pre><pre>&nbsp;</pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; ret(0, 0) = w;</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; ret(1, 1) = h;</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; ret(2, 2) = Q;</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; ret(3, 2) = -Q*near_plane;</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; ret(2, 3) = 1;</span></pre><pre><span style="font-size: 10pt">&nbsp;&nbsp;&nbsp; return ret;</span></pre><pre><span style="font-size: 10pt">}&nbsp;&nbsp; // End of ProjectionMatrix</span></pre>
<p><span style="font-family: 宋体">在创建矩阵之后，调用<u>IDirect3DDevice9::SetTransform</u>方法设置投影矩阵，要将第一个参数设为<u>D3DTS_PROJECTION</u>。</span></p>
<p><span style="font-family: 宋体">Direct3D扩展（D3DX）工具库提供了以下函数，帮助应用程序设置投影矩阵。</span></p>
<ul type="disc"><li><u><span style="font-family: 宋体">D3DXMatrixPerspectiveLH</span></u></li><li><u><span style="font-family: 宋体">D3DXMatrixPerspectiveRH</span></u></li><li><u><span style="font-family: 宋体">D3DXMatrixPerspectiveFovLH</span></u></li><li><u><span style="font-family: 宋体">D3DXMatrixPerspectiveFovRH</span></u></li><li><u><span style="font-family: 宋体">D3DXMatrixPerspectiveOffCenterLH</span></u></li><li><u><span style="font-family: 宋体">D3DXMatrixPerspectiveOffCenterRH</span></u> </li></ul>
<div align="center"><span style="font-family: 宋体">
<hr align="center" width="100%" size="1" />
</span></div>
<p><a name="W友好投影矩阵"><strong><span style="font-size: 24pt; font-family: 宋体">W友好投影矩阵</span></strong></a><strong></strong></p>
<div align="center"><span style="font-family: 宋体">
<hr align="center" width="100%" size="1" />
</span></div>
<p><span style="font-family: 宋体">对于已经用世界、观察和投影矩阵变换过的顶点，Microsoft&#174; Direct3D&#174;使用顶点的W成员进行深度缓存中基于深度的计算或计算雾效果。类似这样的计算要求应用程序归一化投影矩阵，使生成的W与世界空间中的Z相同。简而言之，如果应用程序的投影矩阵包含的（3，4）系数不为1，那么为了生成适用的矩阵，应用程序必须用（3，4）系数的倒数缩放所有的系数。如果应用程序不提供符合这样要求的矩阵，那么会造成雾效果和深度缓存不正确。<u>什么是投影矩阵？</u>中推荐的矩阵符合基于w的计算的要求。</span></p>
<p><span style="font-family: 宋体">下图显示了不符合要求的投影矩阵，以及对同一个矩阵进行缩放，这样就可以启用基于视点的雾。</span></p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">我们假设在前面的矩阵中，所有变量都不为零。更多有关相对于视点的雾的信息，请参阅<u>基于视点的深度与基于Z的深度的比较</u>。更多有关基于w的深度缓存，请参阅<u>深度缓存</u>。</span></p>
<p><strong><span style="font-family: 宋体">注意&nbsp;</span></strong><span style="font-family: 宋体">Direct3D在基于w的深度计算中使用当前设置的投影矩阵。因此，即使应用程序不使用Direct3D变换流水线，但是为了使用基于w的特性，应用程序必须设置一个符合要求的投影矩阵。</span></p>
<p>&nbsp;</p><br /><br /></div><img src ="http://www.cppblog.com/Tongy0/aggbug/188909.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Tongy0/" target="_blank">Jacc.Kim</a> 2012-08-31 16:31 <a href="http://www.cppblog.com/Tongy0/archive/2012/08/31/188909.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>