﻿<?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++博客-Richard He-文章分类-[再转]</title><link>http://www.cppblog.com/richardhe/category/7632.html</link><description>学无止境!永远学下去!</description><language>zh-cn</language><lastBuildDate>Fri, 07 Nov 2008 11:58:02 GMT</lastBuildDate><pubDate>Fri, 07 Nov 2008 11:58:02 GMT</pubDate><ttl>60</ttl><item><title>.net中的 delegate的标准C++模拟(转)</title><link>http://www.cppblog.com/richardhe/articles/66190.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Fri, 07 Nov 2008 02:05:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/66190.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/66190.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/66190.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/66190.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/66190.html</trackback:ping><description><![CDATA[<span style="font-family: 宋体; font-size: 14px; line-height: 25px;">
<p>用模板的偏特化和成员模板，重载函数调用运算符成功的实现了delegate,既可以绑定普通函数，也可以绑定对象及其成员函数<br>在cygnuwin下编译通过,&nbsp;<br>还不支持一个delegate包含多个函数的用法,不过相信很简单，从std::list派生一个类&nbsp;<br>就可以了&nbsp;<br>我用的cygun有些毛病，&nbsp;<br>my_delegate d2=my_delegate(t,&amp;Test::f);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ^如果写成&amp;t，就会导致编译器内部错误，没办法了&nbsp;<br>&nbsp;&nbsp;<br>我本来写程序是加空行的，贴到BBS上就没了，忍受一下吧&nbsp;<br>Win32下的各种调用约定很讨厌，没有考虑，不过实现起来不费什么脑筋，就是麻烦，&nbsp;<br>不管了&nbsp;<br>&nbsp;&nbsp;<br>// Test.cpp : Defines the entry point for the console application.&nbsp;<br>//&nbsp;<br>#include &lt;stddef.h&gt;&nbsp;<br>template&lt;class T&gt;&nbsp;<br></p>
<p>//函数traits,用来提取函数的返回类型</p>
<p>struct function_traits&nbsp;<br>{&nbsp;<br>};&nbsp;<br>template&lt;class RT&gt;&nbsp;<br>struct function_traits&lt; RT(*)() &gt;&nbsp;<br>{&nbsp;<br>&nbsp;typedef RT result_type;&nbsp;<br>};&nbsp;<br>template&lt;class RT,class AT&gt;&nbsp;<br>struct function_traits&lt; RT(*)(AT) &gt;&nbsp;<br>{&nbsp;<br>&nbsp;typedef RT result_type;&nbsp;<br>&nbsp;typedef AT argument_type;&nbsp;<br>};&nbsp;<br>template&lt;class RT,class AT1,class AT2&gt;&nbsp;<br>struct function_traits&lt; RT(*)(AT1,AT2) &gt;&nbsp;<br>{&nbsp;<br>&nbsp;typedef RT result_type;&nbsp;<br>&nbsp;typedef AT1 first_argument_type;&nbsp;<br>&nbsp;typedef AT2 second_argument_type;&nbsp;<br>};</p>
<p>// 函数traits,用来提取类成员函数的返回类型</p>
<p><br>template&lt;class RT, class OT&gt;&nbsp;<br>struct function_traits&lt; RT (OT::*)() &gt;&nbsp;<br>{&nbsp;<br>&nbsp;typedef OT object_type;&nbsp;<br>&nbsp;typedef RT result_type;&nbsp;<br>};&nbsp;<br>template&lt;class RT, class OT, class AT&gt;&nbsp;<br>struct function_traits&lt; RT (OT::*)(AT) &gt;&nbsp;<br>{&nbsp;<br>&nbsp;typedef OT object_type;&nbsp;<br>&nbsp;typedef RT result_type;&nbsp;<br>&nbsp;typedef AT argument_type;&nbsp;<br>&nbsp;&nbsp;<br>&nbsp;typedef AT first_argument_type;&nbsp;<br>};&nbsp;<br>template&lt;class RT,class OT,class AT1,class AT2&gt;&nbsp;<br>struct function_traits&lt; RT (OT::*)(AT1,AT2) &gt;&nbsp;<br>{&nbsp;<br>&nbsp;typedef OT object_type;&nbsp;<br>&nbsp;typedef RT result_type;&nbsp;<br>&nbsp;typedef AT1 first_argument_type;&nbsp;<br>&nbsp;typedef AT2 second_argument_type;&nbsp;<br>};</p>
<p>// 把一个普通函数类向转化为类型兼容的指定类的成员函数类型&nbsp;<br>template &lt;typename OT, typename PFT&gt;&nbsp;<br>struct to_member_function_pointer&nbsp;<br>{&nbsp;<br>};&nbsp;<br>template &lt;typename OT,typename RT&gt;&nbsp;<br>struct to_member_function_pointer&lt; OT, RT(*)() &gt;&nbsp;<br>{&nbsp;<br>&nbsp;typedef RT (OT::*type)();&nbsp;<br>};&nbsp;<br>template &lt;typename OT, typename RT, typename AT&gt;&nbsp;<br>struct to_member_function_pointer&lt; OT, RT(*)(AT) &gt;&nbsp;<br>{&nbsp;<br>&nbsp;typedef RT (OT::*type)(AT);&nbsp;<br>};&nbsp;<br>template &lt;typename OT, typename RT, typename AT1, typename AT2&gt;&nbsp;<br>struct to_member_function_pointer&lt; OT, RT(*)(AT1,AT2) &gt;&nbsp;<br>{&nbsp;<br>&nbsp;typedef RT (OT::*type)(AT1,AT2);&nbsp;<br>};&nbsp;<br>template &lt;typename OT, typename RT, typename AT1, typename AT2, typename AT3&gt;&nbsp;<br>struct to_member_function_pointer&lt; OT, RT(*)(AT1,AT2,AT3) &gt;&nbsp;<br>{&nbsp;<br>&nbsp;typedef RT (OT::*type)(AT1,AT2,AT3);&nbsp;<br>};&nbsp;<br></p>
<p>// 转化为const 成员函数</p>
<p>template &lt;typename OT, typename PFT&gt;&nbsp;<br>struct to_const_member_function_pointer&nbsp;<br>{&nbsp;<br>};&nbsp;<br>template &lt;typename OT, typename RT&gt;&nbsp;<br>struct to_const_member_function_pointer&lt; OT, RT(*)() &gt;&nbsp;<br>{&nbsp;<br>&nbsp;typedef RT (OT::*type)() const;&nbsp;<br>};&nbsp;<br>template &lt;typename OT, typename RT, typename AT&gt;&nbsp;<br>struct to_const_member_function_pointer&lt; OT, RT(*)(AT) &gt;&nbsp;<br>{&nbsp;<br>&nbsp;typedef RT (OT::*type)(AT) const;&nbsp;<br>};&nbsp;<br>template &lt;typename OT, typename RT, typename AT1, typename AT2&gt;&nbsp;<br>struct to_const_member_function_pointer&lt; OT, RT(*)(AT1,AT2) &gt;&nbsp;<br>{&nbsp;<br>&nbsp;typedef RT (OT::*type)(AT1,AT2) const;&nbsp;<br>};&nbsp;<br>template &lt;typename OT, typename RT, typename AT1, typename AT2, typename AT3&gt;&nbsp;<br>struct to_const_member_function_pointer&lt; OT, RT(*)(AT1,AT2,AT3) &gt;&nbsp;<br>{&nbsp;<br>&nbsp;typedef RT (OT::*type)(AT1,AT2,AT3) const;&nbsp;<br>};&nbsp;<br></p>
<p>// delegate的实现</p>
<p>template &lt;typename PFT&gt;&nbsp;<br>class delegate&nbsp;<br>{&nbsp;<br>&nbsp;class object&nbsp;<br>&nbsp;{&nbsp;<br>&nbsp;}*m_pObject; // 对象指针，是一个代理对象<br>&nbsp;typedef typename to_member_function_pointer&lt;object, PFT&gt;::type object_member_fuunction_pointer;&nbsp;<br>&nbsp;union&nbsp;<br>&nbsp;{&nbsp;<br>&nbsp; PFT m_pf;&nbsp;<br>&nbsp; object_member_function_pointer m_pmf;&nbsp;<br>&nbsp;}; // 函数指针和成员函数指针的联合体<br>&nbsp;public:&nbsp;<br>&nbsp; typedef typename function_traits&lt;PFT&gt;::result_type result_type;&nbsp;<br>&nbsp;&nbsp;<br>&nbsp; delegate()&nbsp;<br>&nbsp; {&nbsp;<br>&nbsp;&nbsp; m_pObject=NULL;&nbsp;<br>&nbsp;&nbsp; m_pf=NULL;&nbsp;<br>&nbsp; }&nbsp;<br>&nbsp;&nbsp;<br>&nbsp; delegate(PFT pf)&nbsp;<br>&nbsp; {&nbsp;<br>&nbsp;&nbsp; operator=(pf);&nbsp;<br>&nbsp; }&nbsp;<br>&nbsp;&nbsp;<br>&nbsp; template&lt;typename OT&gt;&nbsp;<br>&nbsp;&nbsp; delegate(&nbsp;<br>&nbsp;&nbsp; OT *pObject,&nbsp;<br>&nbsp;&nbsp; typename to_member_function_pointer&lt;OT, PFT&gt;::type pmf&nbsp;<br>&nbsp;&nbsp; )&nbsp;<br>&nbsp; {&nbsp;<br>&nbsp;&nbsp; m_pObject=reinterpret_cast&lt;object*&gt;(pObject);&nbsp;<br>&nbsp;&nbsp; m_pmf=*(reinterpret_cast&lt;object_member_function_pointer*&gt;(&amp;pmf));&nbsp;<br>&nbsp; }&nbsp;<br>&nbsp;&nbsp;<br>&nbsp; template&lt;typename OT&gt;&nbsp;<br>&nbsp;&nbsp; delegate(&nbsp;<br>&nbsp;&nbsp; OT &amp;pObject,&nbsp;<br>&nbsp;&nbsp; typename to_member_function_pointer&lt;OT, PFT&gt;::type pmf&nbsp;<br>&nbsp;&nbsp; )&nbsp;<br>&nbsp; {&nbsp;<br>&nbsp;&nbsp; m_pObject=reinterpret_cast&lt;object*&gt;(&amp;pObject);&nbsp;<br>&nbsp;&nbsp; m_pmf=*(reinterpret_cast&lt;object_member_function_pointer*&gt;(&amp;pmf));&nbsp;<br>&nbsp; }&nbsp;<br>&nbsp;&nbsp;<br>&nbsp; template&lt;typename OT&gt;&nbsp;<br>&nbsp;&nbsp; delegate(&nbsp;<br>&nbsp;&nbsp; const OT *pObject,&nbsp;<br>&nbsp;&nbsp; typename to_const_member_function_pointer&lt;OT, PFT&gt;::type pmf&nbsp;<br>&nbsp;&nbsp; )&nbsp;<br>&nbsp; {&nbsp;<br>&nbsp;&nbsp; m_pObject=const_cast&lt;object*&gt;(reinterpret_cast&lt;object*&gt;(pObject));&nbsp;<br>&nbsp;&nbsp; m_pmf=*(reinterpret_cast&lt;object_member_function_pointer*&gt;(&amp;pmf));&nbsp;<br>&nbsp; }&nbsp;<br>&nbsp;&nbsp;<br>&nbsp; template&lt;typename OT&gt;&nbsp;<br>&nbsp;&nbsp; delegate(&nbsp;<br>&nbsp;&nbsp; const OT &amp;pObject,&nbsp;<br>&nbsp;&nbsp; typename to_const_member_function_pointer&lt;OT, PFT&gt;::type pmf&nbsp;<br>&nbsp;&nbsp; )&nbsp;<br>&nbsp; {&nbsp;<br>&nbsp;&nbsp; m_pObject=const_cast&lt;object*&gt;(reinterpret_cast&lt;object*&gt;(&amp;pObject));&nbsp;<br>&nbsp;&nbsp; m_pmf=*(reinterpret_cast&lt;object_member_function_pointer*&gt;(&amp;pmf));&nbsp;<br>&nbsp; }&nbsp;<br>&nbsp;&nbsp;<br>&nbsp; delegate &amp; operator=(PFT pf)&nbsp;<br>&nbsp; {&nbsp;<br>&nbsp;&nbsp; m_pf=pf;&nbsp;<br>&nbsp;&nbsp; m_pObject=0;&nbsp;<br>&nbsp;&nbsp; return *this;&nbsp;<br>&nbsp; }&nbsp;<br>&nbsp; template&lt;int&gt;&nbsp;<br>:gcc的函数模板不许无参数，加了个占位的"int"才能通过&nbsp;<br>&nbsp;&nbsp; result_type operator()()&nbsp;<br>&nbsp; {&nbsp;<br>&nbsp;&nbsp; if(m_pObject)&nbsp;<br>&nbsp;&nbsp;&nbsp; return (m_pObject-&gt;*m_pmf)();&nbsp;<br>&nbsp;&nbsp; else&nbsp;<br>&nbsp;&nbsp;&nbsp; return m_pf();&nbsp;<br>&nbsp; }&nbsp;<br>&nbsp; template&lt;typename AT&gt;&nbsp;<br>&nbsp;&nbsp; result_type operator()(&nbsp;<br>&nbsp;&nbsp; AT a1&nbsp;<br>&nbsp;&nbsp; )&nbsp;<br>&nbsp; {&nbsp;<br>&nbsp;&nbsp; if(m_pObject)&nbsp;<br>&nbsp;&nbsp;&nbsp; return (m_pObject-&gt;*m_pmf)(a1);&nbsp;<br>&nbsp;&nbsp; else&nbsp;<br>&nbsp;&nbsp;&nbsp; return m_pf(a1);&nbsp;<br>&nbsp; }&nbsp;<br>&nbsp; template&lt;typename AT1, typename AT2&gt;&nbsp;<br>&nbsp;&nbsp; result_type operator()(&nbsp;<br>&nbsp;&nbsp; AT1 a1,&nbsp;<br>&nbsp;&nbsp; AT2 a2&nbsp;<br>&nbsp;&nbsp; )&nbsp;</p>
<p>{&nbsp;<br>&nbsp;&nbsp; if(m_pObject)&nbsp;<br>&nbsp;&nbsp;&nbsp; return (m_pObject-&gt;*m_pmf)(a1,a2);&nbsp;<br>&nbsp;&nbsp; else&nbsp;<br>&nbsp;&nbsp;&nbsp; return m_pf(a1,a2);&nbsp;<br>&nbsp; }&nbsp;<br>&nbsp; template&lt;typename AT1, typename AT2, typename AT3&gt;&nbsp;<br>&nbsp;&nbsp; result_type operator()(&nbsp;<br>&nbsp;&nbsp; AT1 a1,&nbsp;<br>&nbsp;&nbsp; AT2 a2,&nbsp;<br>&nbsp;&nbsp; AT3 a3&nbsp;<br>&nbsp;&nbsp; )&nbsp;<br>&nbsp; {&nbsp;<br>&nbsp;&nbsp; if(m_pObject)&nbsp;<br>&nbsp;&nbsp;&nbsp; return (m_pObject-&gt;*m_pmf)(a1,a2,a3);&nbsp;<br>&nbsp;&nbsp; else&nbsp;<br>&nbsp;&nbsp;&nbsp; return m_pf(a1,a2,a3);&nbsp;<br>&nbsp; }&nbsp;<br>};&nbsp;<br>int gf(int)&nbsp;<br>{&nbsp;<br>&nbsp;return 0;&nbsp;<br>}&nbsp;<br>class Test&nbsp;<br>{&nbsp;<br>public:&nbsp;<br>&nbsp;int f(int){return 0;}&nbsp;<br>};&nbsp;<br>typedef delegate &lt; int (*)(int) &gt; my_delegate;&nbsp;<br>int main()&nbsp;<br>{&nbsp;<br>&nbsp;Test t;</p>
<p>&nbsp;</p>
<p>&nbsp;my_delegate d1=&amp;gf; // 普通函数<br>&nbsp;my_delegate d2=my_delegate(t,&amp;Test::f); //对象和类成员函数<br>&nbsp;d1(0); //调用<br>&nbsp;d2(2);&nbsp;<br>} <br></p>
</span><img src ="http://www.cppblog.com/richardhe/aggbug/66190.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-11-07 10:05 <a href="http://www.cppblog.com/richardhe/articles/66190.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏中的资源管理――资源高速缓存</title><link>http://www.cppblog.com/richardhe/articles/65198.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Mon, 27 Oct 2008 05:32:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/65198.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/65198.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/65198.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/65198.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/65198.html</trackback:ping><description><![CDATA[<p>《游戏中的资源管理――资源高速缓存》<br>转载请注明出处：<a  href="http://groups.google.com/group/jianguhan" target="_blank" rel="nofollow"><u><font color="#800080">http://groups.google.com/group/jianguhan</font></u></a> <br><br><br>1.什么是资源高速缓存 <br>&nbsp;&nbsp;&nbsp;
资源高速缓存的原理与其它内存高速缓存的工作原理是相似的。在游戏的状态转换过程中，有些数据是刚才使用过的，那么直接从资源高速缓存中载入即可。例
如，RPG&#173;游戏中主角从大地图进入一个房间，探索一番后主角退出房间，此时只要直接从缓存中载入大地图数据即可，节省了从硬盘载入数据的时间，要知道从
硬盘载入数据是非常&#173;慢的。当然，如果你的游戏所使用的数据文件很少，那么你可以在游戏运行过程中把这些数据完全储存在内存中，而不使用资源高速缓存。
</p>
<p><br>2.一个简单的资源高速缓存管理器 <br>&nbsp;&nbsp;&nbsp; 下面我将向你展示一个比较简单的资源高速缓存管理器，源代码来自我上一个游戏，如果你需要知道更多关于资源高速缓存方面的知识，请参考&lt;&lt;Game Coding Complete&gt;&gt;的第八章。 <br>首先，需要一个机制来唯一标识一个资源，我们用下面这个结构来做资源句柄： <br>struct ResHandle <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp; ResHandle(std::string &amp;resName, void *buffer, int size) <br>&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_resName = resName; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_size&nbsp;&nbsp; = size; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_buffer = buffer; <br>&nbsp;&nbsp;&nbsp;&nbsp; } </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp; ~ResHandle() <br>&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (m_buffer != 0) delete[] m_buffer; <br>&nbsp;&nbsp;&nbsp;&nbsp; } </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp; std::string&nbsp;&nbsp; m_resName;&nbsp;&nbsp;&nbsp; //资源名 <br>&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *m_buffer;&nbsp;&nbsp;&nbsp; //资源句柄所标识的资源 <br>&nbsp;&nbsp;&nbsp;&nbsp; DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_size;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //资源所占内存大小 </p>
<p><br>}; </p>
<p><br>好了，现在我们可以从资源名来找出这个资源了，接下来实现这个资源高速缓存管理器： <br>class CacheManager <br>{ <br>public: <br>&nbsp;&nbsp;&nbsp;&nbsp; CacheManager(); <br>&nbsp;&nbsp;&nbsp;&nbsp; ~CacheManager(); </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; //载入资源，resName为资源名，若载入成功size被设为该资源的大小 <br>&nbsp;&nbsp;&nbsp; //注意，管理中的资源不能在管理器外用delete显示的删除它 <br>&nbsp;&nbsp;&nbsp; void*&nbsp;&nbsp;&nbsp; Load(std::string resName, DWORD *size = 0); <br>&nbsp;&nbsp;&nbsp; //设置缓存大小，单位MB <br>&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SetCacheSize(int sizeMB)&nbsp;&nbsp;&nbsp; { m_cacheSize = sizeMB * 1024 * 1024; } <br>&nbsp;&nbsp;&nbsp;&nbsp; //得到缓存大小，单位MB <br>&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GetCacheSize()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { return m_cacheSize / 1024 /1024; } </p>
<p><br>private: <br>&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp; Free();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //释放lru链表中最后一个资源 <br>&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp; *Update(ResHandle *res);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //更新lru链表 <br>&nbsp;&nbsp;&nbsp;&nbsp; ResHandle *Find(std::string &amp;resName);&nbsp;&nbsp;&nbsp;&nbsp; //找出该资源名的资源句柄 </p>
<p><br>private: <br>&nbsp;&nbsp;&nbsp;&nbsp; DWORD m_cacheSize;&nbsp;&nbsp;&nbsp;&nbsp; //缓存大小 <br>&nbsp;&nbsp;&nbsp;&nbsp; DWORD m_allocated;&nbsp;&nbsp;&nbsp;&nbsp; //已使用的缓存大小 </p>
<p><br>//lru链表，记录最近被使用过的资源 <br>&nbsp;&nbsp;&nbsp;&nbsp; std::list&lt;ResHandle*&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_lru;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //资源标识映射 <br>&nbsp;&nbsp;&nbsp;&nbsp; std::map&lt;std::string, ResHandle*&gt;&nbsp;&nbsp;&nbsp; m_resources; </p>
<p>&nbsp;</p>
<p>}; </p>
<p><br>CacheManager:: CacheManager () <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp; m_cacheSize = 0; <br>&nbsp;&nbsp;&nbsp;&nbsp; m_allocated = 0; </p>
<p><br>} </p>
<p><br>CacheManager::~ CacheManager () <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (!m_lru.empty()) Free();&nbsp;&nbsp; //释放所有管理中的资源 </p>
<p><br>} </p>
<p><br>void * CacheManager::Load(std::string resName, DWORD *size) <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp; ResHandle *handle = Find(resName);&nbsp;&nbsp; //查找该资源是否在缓存中 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; if (handle != 0) //如果找到该资源句柄，则返回该资源并更新lru链表 <br>&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (size != 0) *size = handle-&gt;m_size; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return Update(handle); <br>&nbsp;&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp;&nbsp; else <br>&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //先检测资源大小 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD _size = 资源大小; </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //是否有足够空间? <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (_size &gt; (m_cacheSize - m_allocated)) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (m_lru.empty()) break; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Free(); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_allocated += _size; </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer = new char[_size]; <br>//在这里用任何你能想到的办法载入资源文件到buffer <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230; </p>
<p><br>//记录当前资源 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ResHandle *handle = new ResHandle(resName, buffer, _size); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_lru.push_front(handle); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_resources[resName] = handle; </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (size != 0) *size = _size; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return buffer; <br>&nbsp;&nbsp;&nbsp;&nbsp; } </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp; return 0; </p>
<p>&nbsp;</p>
<p>} </p>
<p><br>void CacheManager::Free() <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp; std::list&lt;ResHandle*&gt;::iterator gonner = m_lru.end(); <br>&nbsp;&nbsp;&nbsp;&nbsp; gonner--; <br>&nbsp;&nbsp;&nbsp;&nbsp; ResHandle *handle = *gonner; <br>&nbsp;&nbsp;&nbsp;&nbsp; m_lru.pop_back(); <br>&nbsp;&nbsp;&nbsp;&nbsp; m_resources.erase(handle-&gt;m_resName); <br>&nbsp;&nbsp;&nbsp;&nbsp; m_allocated -= handle-&gt;m_size; <br>&nbsp;&nbsp;&nbsp;&nbsp; delete handle; </p>
<p><br>} </p>
<p><br>void * CacheManager::Update(ResHandle *res) <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp; m_lru.remove(res); <br>&nbsp;&nbsp;&nbsp;&nbsp; m_lru.push_front(res); <br>&nbsp;&nbsp;&nbsp;&nbsp; m_size = res-&gt;m_size; <br>&nbsp;&nbsp;&nbsp;&nbsp; return res-&gt;m_buffer; </p>
<p><br>} <br><br>ResHandle * CacheManager::Find(std::string &amp;resName) <br>{ <br>&nbsp;&nbsp;&nbsp;&nbsp; std::map&lt;std::string, ResHandle*&gt;::iterator it = m_resources.find(resName); <br>&nbsp;&nbsp;&nbsp;&nbsp; if (it == m_resources.end()) return 0; <br>&nbsp;&nbsp;&nbsp;&nbsp; return (*it).second; </p>
<p><br>} <br><br>至此，你已经可以在游戏中缓存任何你想缓存的资源了^_^ </p>
<p>3. 资源管理进阶 <br>&nbsp;&nbsp;&nbsp; 至此你已经可以在游戏中缓存任何你想缓存的资源了，但是你的任务还没完成，当你请求的资源存在于缓存之外时，那个闪耀的硬盘灯可能就是玩家最感兴趣的东西了。 <br>因此你必须根据不同的游戏类型使用不同的载入方式：&nbsp;<br>&nbsp;&nbsp;&nbsp; 一次载入所有东西：适用于任何以界面或关卡切换的游戏&nbsp;<br>&nbsp;&nbsp;&nbsp; 只在关键点载入资源：很多射击游戏都使用这样的设计，如&#8220;半条命&#8221;&nbsp;<br>&nbsp;&nbsp;&nbsp; 持续载入：适用于开放型地图的游戏，如&#8220;侠盗猎车手&#8221; <br>&nbsp;&nbsp;&nbsp; 如果有可能的话，你还可以使用缓存预测机制，当CPU有额外时间的时候可以把未来可能用到的资源载入到资源高速缓存。 <br>&nbsp;&nbsp;&nbsp; 最后，尽管在游戏的资源管理中资源打包不是必须的，但仍然建议大家把资源文件按类型分别打包到单一的文件中，这将为你节省磁盘空间，并加快游戏的载入速度。 </p><img src ="http://www.cppblog.com/richardhe/aggbug/65198.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-10-27 13:32 <a href="http://www.cppblog.com/richardhe/articles/65198.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>FMOD音频引擎简单使用</title><link>http://www.cppblog.com/richardhe/articles/64473.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Mon, 20 Oct 2008 02:37:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/64473.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/64473.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/64473.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/64473.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/64473.html</trackback:ping><description><![CDATA[<h2>
<a  href="http://www.cppblog.com/rise-worlds/archive/2008/10/19/64397.html" id="viewpost1_TitleUrl">FMOD音频引擎简单使用</a>
</h2>
<p>现代游戏已经不能没有声音，所以音频引擎成为游戏引擎中不可缺少的一部分．这是一篇介绍现代音频引擎的文章(<a  href="http://hard.zol.com.cn/labs/2003/0520/60986.shtml">http://hard.zol.com.cn/labs/2003/0520/60986.shtml</a>)．FMOD音频引擎(<a  href="http://www.fmod.org/">http://www.fmod.org</a>)是一个非常不错的音频引擎，其使用也比较简单，下面做一些简单介绍：<br>一．基本准备<br>它是免费的，你可以从它们的主站上下载API等文件．之后，你需要添加头文件和库文件，如下（C/C++）：  </p>
<div class="post">
<li>fmodvc.lib 用于 Microsoft Visual C++ 和 Codewarrior  </li>
<li>fmodbc.lib 用于 Borland  </li>
<li>fmodwc.lib 用于 Watcom  </li>
<li>fmodcc.lib 用于 LCC-Win32  </li>
<li>libfmod.a 用于 MingW and CygWin  </li>
<li>fmod-3-7.lib 用于 GCC<br>（参考：<a  href="http://www.gamedev.net/reference/articles/article2098.asp">http://www.gamedev.net/reference/articles/article2098.asp</a>）<br>之后，只要添加fmod.h头文件后就可以使用了．<br>二．开始使用<br>１．初始化<br>开始播放声音前，需要进行初始化，很简单：<br>FSOUND_Init (44100, 32, 0);<br>第一个参数是输出HZ，第二是最大软件信道数可以不管也不会增加ＣＰＵ负担，第三个参数可以设置一些标志可以不设置则赋值为０．<br>２．基本常识<br>ＦＭＯＤ将音频分为声音(sound)和音乐(music)两种．前者如：.MOD, .S3M, .XM, .IT, .MID, .RMI, .SGT or .FSB<br>等，后者如： .WAV, .MP2, .MP3, .OGG or .RAW等．二者使用不同的函数处理．都可以通过采样后流的方式来处理．不过小文件一般通过采样方式，它可以多次播放但占用内存．大文件通过流方式，减少内存消耗．<br>３．播放音乐<br>首先定义一个FMUSIC_MODULE类型变量来作为文件句柄．然后就可以通过FMUSIC API来实现，如：<br>装入文件：<br>handle=FMUSIC_LoadSong("YourFileName");<br>FMUSIC_PlaySong(handle);<br>音量控制：FMUSIC_SetMasterVolume (handle, 255);后面的参数在0~255之间，值越大声音越大．<br>暂停播放：FMUSIC_SetPaused (handle, true);<br>重开始：FMUSIC_SetPaused (handle, false);<br>循环播放：FMUSIC_SetLooping (handle, true);<br>停止播放：FMUSIC_StopSong (handle);<br>释放音频内存：FMUSIC_FreeSong (handle);<br>下面是一个命令模式下的例子：<br>#include &lt;conio.h&gt;<br>#include "inc/fmod.h"<br>FMUSIC_MODULE* handle;<br>int main ()<br>{<br>&nbsp;&nbsp; // 初始化<br>&nbsp;&nbsp; FSOUND_Init (44100, 32, 0);<br>&nbsp;&nbsp; // 装如<br>&nbsp;&nbsp; handle=FMUSIC_LoadSong ("canyon.mid");<br>&nbsp;&nbsp; // 只播放一次<br>&nbsp;&nbsp; // 播放midi文件时请关闭循环播放<br>&nbsp;&nbsp;&nbsp; FMUSIC_SetLooping (handle, false);<br>&nbsp;&nbsp; //播放<br>&nbsp;&nbsp; FMUSIC_PlaySong (handle);<br>&nbsp; // 按任一键结束<br>&nbsp;&nbsp; while (!_kbhit())<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp; }<br>&nbsp;&nbsp; //释放<br>&nbsp;&nbsp; FMUSIC_FreeSong (handle);<br>&nbsp;&nbsp; FSOUND_Close();<br>}<br>４．播放声音<br>4.1 采样(Sample)方式<br>先定义FSOUND_SAMPLE类型变量，然后就可以使用FSOUND系列函数来实现，如：<br>装如文件：<br>handle=FSOUND_Sample_Load (0,"YourFileName",0,0,0);　　//除文件名外的参数用于多采样或其它等<br>FSOUND_PlaySound (0,handle);<br>设置音量：FSOUND_SetVolume (handle, 255);<br>暂听：FSOUND_SetPaused (handle, true);<br>重新开始：FSOUND_SetPaused (handle, false);<br>停止：FSOUND_StopSound (handle);<br>释放：FSOUND_Sample_Free (handle);<br>下面是一个简单的例子：<br>#include &lt;conio.h&gt;<br>#include "inc/fmod.h"<br>FSOUND_SAMPLE* handle;<br>int main ()<br>{<br>&nbsp;&nbsp; // 初始化<br>&nbsp;&nbsp; FSOUND_Init (44100, 32, 0);<br>&nbsp;&nbsp; // 装载和播放<br>&nbsp;&nbsp; handle=FSOUND_Sample_Load (0,"sample.mp3",0, 0, 0);<br>&nbsp;&nbsp; FSOUND_PlaySound (0,handle);<br>&nbsp;&nbsp; // 按任一键结束<br>&nbsp;&nbsp; while (!_kbhit())<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp; }<br>&nbsp;&nbsp; // 释放<br>&nbsp;&nbsp; FSOUND_Sample_Free (handle);<br>&nbsp;&nbsp; FSOUND_Close();<br>}<br>4.2 流(stream)方式<br>先定义一个FSOUND_STREAM 类型变量，然后：<br>装入文件：<br>handle=FSOUND_Stream_Open("YourFileName",0, 0, 0);<br>FSOUND_Stream_Play (0,handle);<br>　　　提示：3.7版本之前的方式是不一样的．<br>停止：FSOUND_Stream_Stop (handle);<br>释放：FSOUND_Stream_Close(handle);<br>其它和前面是一样的．下面是一个简单的例子：<br>#include &lt;conio.h&gt;<br>#include "inc/fmod.h"<br>FSOUND_STREAM* handle;<br>void main ()<br>{<br>&nbsp;&nbsp; //init FMOD sound system<br>&nbsp;&nbsp; FSOUND_Init (44100, 32, 0);<br>&nbsp;&nbsp; //load and play sample<br>&nbsp;&nbsp; handle=FSOUND_Stream_Open("sample.mp3",0, 0, 0);<br>&nbsp;&nbsp; FSOUND_Stream_Play (0,handle);<br>&nbsp;&nbsp; //wait until the users hits a key to end the app<br>&nbsp;&nbsp; while (!_kbhit())<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp; }<br>&nbsp;&nbsp; //clean up<br>&nbsp;&nbsp; FSOUND_Stream_Close(handle);<br>&nbsp;&nbsp; FSOUND_Close();<br>}<br>５．关闭<br>FSOUND_Close ();<br>参考：<br>A Quick Guide to FMOD by <a  href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#119;&#101;&#98;&#109;&#97;&#115;&#116;&#101;&#114;&#64;&#106;&#111;&#97;&#99;&#104;&#105;&#109;&#114;&#111;&#104;&#100;&#101;&#46;&#100;&#101;">Joachim Rohde</a>（<a  href="http://www.gamedev.net/reference/articles/article2098.asp">http://www.gamedev.net/reference/articles/article2098.asp</a>）<br>ＦＭＯＤ wiki（<a  href="http://www.devmaster.net/wiki/FMod">http://www.devmaster.net/wiki/FMod</a>）</li>
</div><img src ="http://www.cppblog.com/richardhe/aggbug/64473.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-10-20 10:37 <a href="http://www.cppblog.com/richardhe/articles/64473.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程程序设计的相关问题</title><link>http://www.cppblog.com/richardhe/articles/64465.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Mon, 20 Oct 2008 02:09:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/64465.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/64465.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/64465.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/64465.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/64465.html</trackback:ping><description><![CDATA[<span><font size="4">一、&nbsp;&nbsp;&nbsp;&nbsp;什么是进程？什么是线程？<br>　　　进程是一大堆系统对象拥有权的集合。如进程拥有内存上下
文，文件句柄，可以派生出很多线程，也可以拥有很多DLL模块。在windows系统中，进程并不完成实质的工作，只是提供一个相对独立的运行环境，线程
才是完成实际工作的载体。线程从属于进程，共享进程所拥有的系统对象。线程是操作系统调度的单位。实质上，线程就是一段可执行代码。<br></font><font size="4"><font color="#0000ff">采用多进程的优点和缺点：<br></font>优点：运行环境相对独立，某一进程的崩溃一般不会影响到其它进程的执行。<br>缺点：<br>耗时耗资源：启动一个进程需要申请大量的系统资源，其中包括虚拟内存、文件句柄以及加载各种必要的动态链接库；线程则不需要以上动作，因为它共享进程中的所有资源。<br>&#8220;系统准备一个进程环境可能需要好几M的空间&#8221;<br>通
信复杂：进程的地址空间独立，进程A的地址X，在进程B中可能是无意义的，这样，当进程间需要共享数据时，就需要特殊的机制来完成这些工作。线程则在同一
地址空间，数据共享方便快捷。&#8220;线程是一个物美价廉的选择，在一个Windows上拥有500个线程是一件很轻易的事情，但是500个进程将是难以想象的
&#8221;。<br><br>二、&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">为什么需要多线程</font>（解释何时考虑使用线程）<br>从用户的角度考虑，就是为了得到更好的系统服务；从程序自身的角度考虑，就是使目标任务能够尽可能快的完成，更有效的利用系统资源。综合考虑，一般以下场合需要使用多线程：<br>1、&nbsp;&nbsp;&nbsp;&nbsp;程序包含复杂的计算任务时<br>主要是利用多线程获取更多的CPU时间（资源）。<br>2、&nbsp;&nbsp;&nbsp;&nbsp;处理速度较慢的外围设备<br>比如：打印时。再比如网络程序，涉及数据包的收发，时间因素不定。使用独立的线程处理这些任务，可使程序无需专门等待结果。<br>3、&nbsp;&nbsp;&nbsp;&nbsp;程序设计自身的需要<br>WINDOWS系统是基于消息循环的抢占式多任务系统，为使消息循环系统不至于阻塞，程序需要多个线程的来共同完成某些任务。<br>三、&nbsp;&nbsp;&nbsp;&nbsp;使用多线程可能出现的问题（列举问题）<br>事
实上，单纯的使用线程不会产生任何问题，其启动、运行和结束都是非常简单的事情。在Win32环境下，启动：CreateThread，运行就是函数执行
的过程，中止就是函数返回的过程或者调用ExitThread。但是由于下列原因可能会使在使用线程的过程中带来一系列问题：<br>1、&nbsp;&nbsp;&nbsp;&nbsp;版本问题<br>多
任务的概念是随着实际需求的提出而产生，最初的程序设计者并没有考虑到代码需要在多线程环境下运行，在多线程环境下使用这些代码无疑将产生访问冲突。最典
型的例子就是C runtime library。最早的C runtime
library产生于20世纪70年代，当时连多任务都是一个新奇的概念，更别说什么多线程了，该版本的库中使用了大量全局变量和静态变量（产生竞争条件
的根源，对局部变量无此要求，因为局部变量都使用栈，每个线程都有自己的栈空间，另外在启动线程时，给线程函数的参数应该是尽量使用值，而非指针或引用，
这样可以避免因此带来的冲突问题），如在该库中统一使用一个errno变量来表明程序的错误码，如果在多线程中使用该库，并且都需要设置错误码时，此时即
产生了一个冲突。<br>VC为防止以上问题，提供了另外一个线程安全的C runtime
library，因此在写多线程程序时，需要注意所连接库的版本是否正确（该过程一般由应用程序向导完成，因此平时编程并无此问题）。与此有关的还有一些
其它版本：单线程版、多线程版调试版和多线程发行版。<br>2、&nbsp;&nbsp;&nbsp;&nbsp;线程间共享资源时形成竞争条件（race condition）<br>一般而
言，线程并不是单独行动，通常是多个线程分工协作，完成一个大任务中的不同小任务，此时，这些线程之间就需要共同操作一些资源，比较典型的例子是多个线程
进行文件操作或屏幕打印的情况：线程A在写文件进行了一半时，发生了context
switch，另外一个线程B继续进行写文件操作，此时文件的内容将会凌乱不堪。甚至造成异常错误。典型的例子是，三个线程，线程A在堆中申请了一块内存
并填入了一个值，线程B读取了该值后将该内存释放，如果线程C还要对该内存操作时，将导致异常。<br>3、&nbsp;&nbsp;&nbsp;&nbsp;线程间的通信问题<br>线程协作完
成某一任务时，有时还需要通信以控制任务的执行步骤，典型的例子就是读写者线程：写线程在对某内存区域写完数据后，需要通知读线程来取，读完之后又需要通
知写线程可以继续往里写入数据。更为广泛的例子是：某线程需要等待某一事件发生，以决定是否继续工作。此时，如果没有正确控制线程的执行过程，将导致不可
预料的错误发生。<br>4、&nbsp;&nbsp;&nbsp;&nbsp;由于不规范的使用线程导致系统效率下降<br>进程中包含了一个以上的线程，这些线程可能会动态的申请某些资源，如
某些数据库线程可能会动态加载数据库方面的动态链接库，但是在该线程结束时，并没有及时释放该动态链接库即被其他线程强行终止，于是该进程中的该动态链接
库引用计数不为0，从而导致该动态链接库在该进程中存有一个副本。当这种情况频繁时，将对系统效率产生很大的影响。<br>四、&nbsp;&nbsp;&nbsp;&nbsp;线程的类型（解释UI线程和WORKER线程的区别和联系）<br>严格说来，线程并没有什么本质区别，但是Win32编程文档中却反复强调UI线程和Worker线程的区别。并给出了它们的定义：<br>UI线程就是：拥有消息队列和窗口的线程，并且它的主要职责是处理窗口消息。Worker线程则没有消息队列，但是当Worker线程产生一个用户界面（消息框和模式对话框除外）时，则该线程则摇身一变，成为UI线程。<br>问题：<br>1、&nbsp;&nbsp;&nbsp;&nbsp;线程的消息队列和窗口的消息队列<br>在Win32中，每个线程都有它自己专属的消息队列，而窗口并不总是有消息队列，因为一个UI线程可以创建很多个窗口。<br>2、&nbsp;&nbsp;&nbsp;&nbsp;UI线程到底跟Worker线程存在什么差别？<br>职
责不一样：UI线程负责处理与用户界面有关的消息，一般而言，用户界面消息来自用户输入（如鼠标键盘消息）、系统消息（如WM_PAINT）以及程序产生
的用户自定义消息。因此，在该线程下一般不能存在等待(wait&#8230;)函数，这样该线程就会挂起，从而影响消息队列的处理。Worker线程不用处理用户界
面消息，而是完成一般性的计算任务，该线程等待计算过程中必要的资源时，不会影响到界面的刷新动作。<br>操作系统的管理不一样：对UI线程来说，产生一个UI线程实际上产生了两个线程，一个是其自身，另一个是操作系统为响应其GDI调用而产生的影子线程。<br>3、&nbsp;&nbsp;&nbsp;&nbsp;Worker线程变成UI线程有什么不好？<br>Worker线程一般用于计算，此时如果它转换为UI线程的话，将无暇顾及用户界面的消息响应。<br>4、&nbsp;&nbsp;&nbsp;&nbsp;Worker线程可否拥有自己的消息队列？<br>Worker线程同样可以拥有自己的消息队列，该队列一般通过PeekMessage()调用建立，通过GetMessage调用来解析。（具体实现看源码）<br>5、&nbsp;&nbsp;&nbsp;&nbsp;用以下规则来管理win32中线程、消息和窗口的互动<br>所有传送给某一窗口的消息，将由产生该窗口的线程负责处理。<br>五、&nbsp;&nbsp;&nbsp;&nbsp;线程的启动和中止（解释启动线程的不同方式及其它们的区别和实用场合）<br>随C Runtime Library库的更新和编程环境的不同，线程的启动方式也有所不同，以下介绍几种典型的线程启动方式。<br>1、_beginthread和_endthread<br>该
函数是C Runtime Library中的函数，它负责初始化函数库；其原型如下unsigned long _beginthread(
void( __cdecl *start_address )( void * ), unsigned stack_size, void
*arglist
);&#8220;该函数被认为是头脑简单的函数&#8221;，使用该函数导致无法有效的控制被创建线程，如不能在启动时将该线程挂起，无法为该线程设置优先权等。另外，该函数
为隐藏Win32的实现细节，启动线程的第一件事情即将自己的Handle关闭，因此也就无法利用这个Handle来等待该线程结束等操作。该函数是早期
的C Runtime Library的产物，不提倡使用，后期的改良版本为_beginthreadex。<br>通过_beginthread启动的线程在应当通过调用_endthread结束，以保证清除与线程相关的资源。<br>2、_beginthreadex和_endthreadex<br>该
函数是C Runtime
Library中的一个函数，用标准C实现，相比_beginthread，_beginthreadex对线程控制更为有力（比前者多三个参数）,是
_beginthread的加强版。其原型为unsigned long _beginthreadex( void *security,
unsigned stack_size, unsigned ( __stdcall *start_address )( void * ),
void *arglist, unsigned initflag, unsigned *thrdaddr
);该函数返回新线程的句柄，通过该句柄可实现对线程的控制。虽然，该函数是用标准C写的（即可不加修改就可以移植到其他系统执行），但是由于它与
Windows系统有着紧密的联系（需要手动关闭该线程产生的Handle），因此实现时，往往需要包含windows.h。<br>通过_beginthreadex启动的线程通过调用_endthreadex做相关清理。<br>3、CreateThread和ExitThread<br>CreateThread
是Win32 API函数集中的一个函数，其原型为HANDLE CreateThread(LPSECURITY_ATTRIBUTES
lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE
lpStartAddress,LPVOID lpParameter,DWORD wCreationFlags,LPDWORD
lpThreadId);该函数使用Win32编程环境中的类型约定，只适用于Windows系统。参数形式与_beginthreadex一致，对线程
控制能力也与之一致，只是该函数与C Runtime
Library没有任何关系，它不负责初始化该库，因此在多线程环境中，如果使用该函数启动线程，则不应使用C Runtime
Library中的多线程版本的函数。取而代之的应该是功能相对应的 Win32 API函数；另外，应当自己手工提供线程同步的代码。<br>通过CreateThread创建的线程则通过ExitThread做清理工作。<br>4、AfxBeginThread和AfxEndThread<br>AfxBeginThread
是MFC提供的线程启动方式，它是个重载函数，有两种调用形式：Worker线程版和UI线程版。MFC对Win32线程做了小心的很好的封装
（CWinThread），虽然其总是调用了_beginthreadex来启动一个线程，但是其额外做的工作使得在MFC环境下，操作线程变得简单明
了，并且不需要太多的关注细节问题。MFC在线程的封装方面主要做了下列事情：<br>1、&nbsp;&nbsp;&nbsp;&nbsp;自动清除CWinThread对象<br>2、&nbsp;&nbsp;&nbsp;&nbsp;关闭线程handle，线程对象自动释放<br>3、&nbsp;&nbsp;&nbsp;&nbsp;存储了线程相关的重要参数，即线程handle和线程ID<br>4、&nbsp;&nbsp;&nbsp;&nbsp;辅之以其它MFC同步对象，方便的实现线程同步<br>5、&nbsp;&nbsp;&nbsp;&nbsp;使用了严格的断言调试语句，使线程调试变得相对简单<br><br>&#8220;（C
Runtime
Library是用标准C开发的实用函数集）如果多线程程序中使用了标准C库函数，并用CreateThread()和ExitThread()，则会导
致内存泄漏。解决这个问题的方法是用C运行库（run-time library）函数来启动和终止线程，而不用WIN32
API定义的CreateThread()和ExitThread()。在C运行库函数中，它们的替代函数分别是_beginthreadex()和
_exitthreadex()，需要的头文件是_process.h。在VC6.0下，还需在
Project-&gt;Settings-&gt;C/C++-&gt;Code Generation中选择Multithreaded
Runtime
Library。当然，也可以通过避免使用C标准库函数的方法来解决上述问题，WIN32提供了一些C标准库函数的替代函数，例如，可用
wsprintf()和lstrlen()来代替sprintf()和strlen()。这样，使用CreateThread()和
ExitThread()不会出现问题。&#8221;<br>六、&nbsp;&nbsp;&nbsp;&nbsp;线程的同步问题（介绍Windows的同步机制）<br>1、&nbsp;&nbsp;&nbsp;&nbsp;怎样等待一个线程结束（忙等（busy loop）和高效的等（WaitForSingleObject））<br>1）&nbsp;&nbsp;&nbsp;&nbsp;忙等（busy loop）<br>hThrd = CreateThread(NULL,0,ThreadFunc,(LPVOID)1,0,&amp;threadId );<br>for (;;)<br>{<br>GetExitCodeThread(hThrd, &amp;exitCode);<br>if ( exitCode != STILL_ACTIVE )<br>break;<br>}<br>CloseHandle(hThrd);<br>缺点：耗费CPU资源，且如果在UI线程中这样等待将导致窗口无法刷新。不推荐使用。<br>2）&nbsp;&nbsp;&nbsp;&nbsp;高效的等待<br>（1）WaitForSingleObject;<br>关于WaitForSingleObject的参数，前者为等待的对象，后者为等待的时间，对某些执行时间较长的线程，可以设置一个合适的值，等待完这个时间后，更新界面，然后继续等待，或者强行终止线程。<br>将以上的等待部分的代码改为：<br>WaitForSingleObject（hThrd,INFINITE）;<br>该函数相当于Sleep函数，当需要等待的对象（句柄）没有被触发时，等待的线程将被自动挂起。该方法解决了耗费CPU时间的问题，但是在UI线程中，仍不能使用该方法来等待某一线程结束。<br>解决方法之一：创建一个Worker管理者线程，在该线程中等待，工作者线程完成，然后由管理者线程发消息通知UI线程更新窗口。<br>（2）WaitForMultipleObject<br>该函数允许在同一时间等待多个对象，函数的原型如下：<br>DWORD WaitForMultipleObject(DWORD nCount，CONST HANDE *lpHandles,BOOL bWaitAll,dwMilliseconds)；<br>第一个参数表示句柄数组的大小；等待的对象不能超过64<br>第二个参数为句柄数组；<br>第三个参数表明是否等待所有对象激发。True表示是。<br>第四个参数为等待时间。<br>关于WaitForMultipleObject的返回值：<br>当bWaitAll为True时，返回值为WAIT_OBJECT_0；<br>当bWaitAll为false时，返回值减去WAIT_OBJECT_0，就是激发对象所在的下标。<br>应用：<br>A）&nbsp;&nbsp;&nbsp;&nbsp;解决多个工人n完成多个任务m（n&lt;m）的问题（bWaitAll设置为false）<br>解决的思路如下：先从m个任务中取出n个任务，对应地用n个工人去完成，然后利用该函数等待其中任意一个工人结束任务，一旦结束则让其做另外一个任务<br>B）&nbsp;&nbsp;&nbsp;&nbsp;解决等待多个资源的问题（bWaitAll设置为true）<br>哲学家就餐问题：5个哲学家在圆桌旁，每个哲学家左手边放着1只筷子，哲学家做两件事情，吃饭和思考，吃饭时同时需要其左右的两只筷子。<br>解决思路：将哲学家模拟为线程，筷子为资源，只有哲学家线程同时获得两个资源时，方可进一步动作（吃饭）。即：<br>WaitForMultipleObjects(2, myChopsticks, TRUE, INFINITE);<br>MyChopsticks是一个大小为5的核心对象数组。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;（3）MsgWaitForMultipleObjects<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;原型：<br>DWORD MsgWaitForMultipleObjects( DWORD nCount,CONST HANDLE pHandles,BOOL fWaitAll,DWORD dwMilliseconds,DWORD dwWakeMask);<br>&nbsp;&nbsp;&nbsp;&nbsp;前
几个参数含义同WaitForMultipleObject，最后一个是消息屏蔽标识，指示接收消息的类型。此外返回值也有额外的意义：当消息到达时，该
函数返回WAIT_OBJECT_0+nCount。以下是常见的使用MsgWaitForMultipleObjects的架构：<br>&nbsp;&nbsp;while (!quit)<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp; // Wait for next message or object being signaled<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;&nbsp; dwWake;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dwWake = MsgWaitForMultipleObjects(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gNumPrinting,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gPrintJobs,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FALSE,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INFINITE,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;QS_ALLEVENTS);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (dwWake &gt;= WAIT_OBJECT_0 &amp;&amp; dwWake &lt; WAIT_OBJECT_0 + gNumPrinting)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//对象被触发<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} // end if<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else if (dwWake == WAIT_OBJECT_0 + gNumPrinting)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//有消息到达<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while (PeekMessage(&amp;msg, NULL, 0, 0, PM_REMOVE))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp; // Get Next message in queue<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (msg.message == WM_QUIT)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; quit = TRUE;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exitCode = msg.wParam;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } // end if<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TranslateMessage(&amp;msg);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DispatchMessage(&amp;msg);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } // end while<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;} // end while<br>2、&nbsp;&nbsp;&nbsp;&nbsp;怎样有效的控制一个线程<br>在任何情况下，切记线程的核心属性为：线程的句柄，线程的ID号。因此控制一个线程也需从这两方面着手。<br>1）&nbsp;&nbsp;&nbsp;&nbsp;使用能返回线程Handle的启动函数来启动线程（除_beginthread外）<br>2）&nbsp;&nbsp;&nbsp;&nbsp;尽量不要使一个工作量较大的线程成为&#8220;闷葫芦&#8221;，从而使该线程能够接收外界通知消息；如下列代码：<br><br><br>MSG msg;<br>&nbsp;&nbsp;&nbsp;&nbsp;while(1)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PeekMessage(&amp;msg,NULL,0,0,PM_REMOVE);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(msg.message==WM_MY)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sleep(100);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>注：GetMessage也是用来得到消息队列中一条消息的函数，它们的区别在于GetMessage是同步的，即如果消息队列中没有消息的话，该线程将自动挂起。使用GetMessage可以使Worker线程成为一个一步一动的线程！<br>&nbsp;&nbsp;&nbsp;&nbsp;MSG msg;<br>&nbsp;&nbsp;&nbsp;&nbsp;while(GetMessage(&amp;msg,NULL,0,0))<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(msg.message==WM_MY)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//Do something here<br>}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>以上的过程也可以通过事件对象予以实现。<br>悬而未决的问题：怎么控制一个正在等待其他事件的线程。如：一个TCP监听线程，在某一Socket上listen，此时该线程处于挂起状态！但是现在主线程又需要关闭该线程，应该怎么操作！<br><br>3、&nbsp;&nbsp;&nbsp;&nbsp;怎样互斥访问一个资源（CMutex和Critical Section）<br>何时需要一个互斥对象？<br>常
见的情形：多个线程需要不定时的操作同一链表（锁链表的头指针）；多个线程需要不定时的进行写文件或是进行屏幕输出（锁文件句柄或屏幕句柄）；多个线程需
要不定时对某个计数器进行操作（锁这个变量）；在多线程环境吓，凡是涉及到对全局变量、静态变量、堆中的内存进行访问时，都应该考虑，是否可能出现一个
race condition（竞争条件）。<br>1）&nbsp;&nbsp;&nbsp;&nbsp;互斥器<br>Win32提供了对互斥资源访问的一整套机制，其中之一就是互斥器，MFC将这些API函数加以封装，形成了CMutex互斥类，使用这两种方法都能够实现对资源的互斥访问。<br>Win32中的API：<br>CreateMutex：<br>原型：<br>HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,&nbsp;&nbsp; BOOL bInitialOwner,&nbsp;&nbsp;LPCTSTR lpName );<br>第一个参数为安全属性；<br>第二个参数用来指示互斥器的拥有者是否为当前线程；<br>第三个参数为互斥器的名称；<br>当不再需要互斥器时，应当调用CloseHandle关闭。<br>约
定：互斥器产生之后，由某一线程完成锁定工作（即调用Wait&#8230;函数），此时系统将该mutex的拥有权交于该线程，然后短暂地将该对象设置为激发态，于
是Wait&#8230;函数返回，做完相应的工作之后（如：修改链表指针、修改计数器、写文件等），调用ReleaseMutex释放拥有权。周而复始。<br>MFC中的互斥器CMutex对象：<br>A、&nbsp;&nbsp;&nbsp;&nbsp;利用其构造函数产生一个互斥器对象<br>HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner, LPCTSTR lpName);<br>B、&nbsp;&nbsp;&nbsp;&nbsp;配合CSingleLock或者CmutipleLock产生一个临时对象，对产生的互斥器进行加锁和释放的动作；<br>2）&nbsp;&nbsp;&nbsp;&nbsp;临界区<br>另一个提供互斥访问的机制是Critical Section，该机制较前一种方法廉价，因为它不属于不是系统的核心对象；临界区可以反复进入，这一点与Mutex有所区别，这需要我们在使用临界区时，保证进入的次数要等于离开的次数。<br>相关函数为InitializeCriticalSection、DeleteCriticalSection、EnterCriticalSection、LeaveCriticalSection。<br>4、&nbsp;&nbsp;&nbsp;&nbsp;怎样等待多个不同（或者相同）资源（WaitForMultiObject）<br>等待多个不同资源在多线程程序设计中时常遇到，如：等待某一线程结束和某一个资源被释放，等待缓冲区和设备准备好两个资源；这种现实情况，可以分别为不同的资源设置系统对象，然后利用WaitForMultiObject进行等待。<br>5、&nbsp;&nbsp;&nbsp;&nbsp;怎样等待多个资源中的一个（使用CSemaphore）<br>现实中还可能出现如下情形：客人租相机的问题：有若干客人需要，租相机，总相机数为n，相机租完后，客人必须等待，只要有一个相机，则某客人就可以等到租借。还有许多问题可以用这种Producer/consumer模型加以概括。<br>这种情形即是等待多个资源中的一个的情况，在Win32程序设计中则经常使用信号量（Semaphore）来解决此问题。<br>Win32系统中，信号量具有以下特性：<br>一
个信号量可以被锁定N次，N一般代表可用资源的个数，上例中即可代表相机的个数，信号量初始化后，在Win32环境下调用一次Wait&#8230;操作即表示对其的
一次锁定，信号量的值相应加1，操作完后，调用ReleaseSemaphore操作，即代表资源释放（上述例子中就是归还相机）。MFC对Win32信
号量的相关API函数进行了封装（CSemaphore），配合CMultiLock 或者 CSingleLock即可实现锁定和资源释放的动作。<br>七、&nbsp;&nbsp;&nbsp;&nbsp;线程间的通信<br>线程间的通信有许多方法可以实现，视场合不同也有不同的应用，大致可以分为两类：进程内的线程通信和进程间的通信。关于进程内线程的通信，前面所述的各种同步互斥等待机制也可归属线程间通信的范畴，<br>1、&nbsp;&nbsp;&nbsp;&nbsp;使用线程消息实现线程通信<br>2、&nbsp;&nbsp;&nbsp;&nbsp;使用事件对象实现线程通信<br>Win32还提供了一种比较灵活的核心对象，该对象完全受控于程序（只是清除的时候由系统回收），这就是Event（事件）对象。事件对象一般用于线程间的通知。下面先看事件对象的一些属性：<br>创建一个事件对象可以调用Win32 API函数完成，也可以使用MFC封装的事件对象。其API原型为：<br>HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,BOOL bManualReset,BOOL bInitialState, LPCTSTR lpName );<br>第二个参数指示事件对象是否为手动修改状态（手动修改需要显式调用ResEvent函数）；第三个参数设置事件对象的初态，true为激发态，false为非激发态。第四个参数为事件的名字。<br>事件对象自从创建后即在程序的控制下处于激发态和非激发态之间翻转。<br>八、&nbsp;&nbsp;&nbsp;&nbsp;线程代码的调试<br>九、&nbsp;&nbsp;&nbsp;&nbsp;什么是线程安全的代码<br>十、&nbsp;&nbsp;&nbsp;&nbsp;多线程程序设计的几个原则</font></span><img src ="http://www.cppblog.com/richardhe/aggbug/64465.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-10-20 10:09 <a href="http://www.cppblog.com/richardhe/articles/64465.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>网易笔试</title><link>http://www.cppblog.com/richardhe/articles/63305.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Mon, 06 Oct 2008 03:41:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/63305.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/63305.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/63305.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/63305.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/63305.html</trackback:ping><description><![CDATA[第一部分，计算机基础：<br>
（1）模块划分的原则：选择题，高/低内聚 高/低耦合<br>
（2）下面排序算法最坏情况下时间复杂度不是n(n-1)/2的是：堆排序，冒泡，直接插入排序，快速排序<br>
（3）Hash技术中的open addressing 和 chianning。<br>
（4）设计一个新的链表结构以改进定位第n个结点的时间复杂度并给出复杂度。<br>
（5）什么是NP问题，举例常见的NP问题。你如何判定一个问题是否是NP问题（ICPCer多多少少都想得到点吧，，嘿嘿）。<br>
（6）给了一棵树和一个简单的遍历函数（这种遍历方式在数据结构书中没出现过），输出遍历序列。（很简单。。是个选择题）<br>
忘了1题了好像。<br>
<br>
第二部分，C/C++：<br>
（1）输出std::list&lt;int&gt; &amp;l中的元素，每个一行。<br>
（2）关于重载，虚函数，覆盖，类静态成员，sizeof(class) 等。（我都不会，平时没用过）<br>
（3）有什么办法可以让new操作符只调用构造函数而不分配空间。这样做有什么作用。（完全不会做）<br>
（4）C++ Traits 是什么？（我不知道，拼错没？）<br>
<br>
第三部分，JAVA：<br>
（1）多线程的实现的方式以及什么情况下那种情况下那种比较合适。ThreadLocal相关。<br>
（2）给了一个JAVA程序让你找错。<br>
（3）JAVA Class Loader的层次以及各个Loader 的作用。<br>
（4）虚构造函数的覆盖等。<br>
（5）interface 和 抽象类，什么情况下用哪个。<br>
（6）Map的几种实现。<br>
（7）<br>
public static void main(String argvs[]){<br>
&nbsp;&nbsp;&nbsp;         Integer var1 = new Integer(1);<br>
Integer var2 = var1;<br>
&nbsp;&nbsp;&nbsp;         doSomeThing(var2);<br>
&nbsp;&nbsp;&nbsp;         System.out.println(var1+var1==var2);<br>
}<br>
<br>
doSomeThing(Integer var){<br>
&nbsp;&nbsp;&nbsp;         var = new Integer(1);<br>
}<br>
求此程序的输出。<br>
<br>
第四部分，数据库：<br>
（1）哈希索引和树索引的区别。<br>
（2）基本的跨表SQL查询。<br>
（3）连接池技术，如何提高一个中心数据库服务器的（连接池）性能。<br>
我没做这部分，记得的不多，好像一共四题吧。<br>
<br>
第五部分，linux 开发：<br>
（1）基本的文件查找替换命令。用一个命令建立 aa bb cc 三个目录。<br>
（2）pthread。<br>
（3）gdb<br>
（4）什么位置的bash..和 bash_profile 的区别。<br>
这些东西我都是久仰他们的大名，但从来就没用过。（建议各位尽早开始使用linux）<br>
<br>
第六部分，windows程序开发：<br>
（1）碰撞检测，怎么判断点在多变形内部，两个多变形的重合面积等。<br>
（2）一个程序非MFC，CRT进程什么的。<br>
<br>
第七部分，Flash和JAVAscript：<br>
（1）下面错误的是<br>
object var={ };<br>
object var=[ ];<br>
object var=( );<br>
object var=/ /;<br>
（2）flash如何与javascript交互。<br>
<br>
第八部分，web开发：<br>
（1）给出了一个html代码，求其中一张图片距离什么div的距离，按照css计算。<br>
（2）HTTP头相关，keep-alive的问题。<br>
（3）说你常用的web服务器的什么的。<br>
<br>
第九部分，测试：<br>
（1）说说你知道的测试过程，工具，流程等。<br>
（2）如果你某天早上上班，发现不能上网了，你怎么办。<br>
（3）描述了一个多人聊天系统，让你设计测试用例。<br>
（4）和（3）差不多的一题吧。<img src ="http://www.cppblog.com/richardhe/aggbug/63305.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-10-06 11:41 <a href="http://www.cppblog.com/richardhe/articles/63305.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>buffer和cache的区别</title><link>http://www.cppblog.com/richardhe/articles/62736.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Thu, 25 Sep 2008 01:45:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/62736.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/62736.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/62736.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/62736.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/62736.html</trackback:ping><description><![CDATA[A buffer is something that has
yet to be "written" to disk. A cache is something that has been "read"
from the disk and stored for later use.&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 缓存（cached）是把读取过的数据保存起来，重新读取时若命中（找到需要的数据）就不要去读硬盘了，若没有命中就读硬盘。其中的数据会根据读取频率进行组织，把最频繁读取的内容放在最容易找到的位置，把不再读的内容不断往后排，直至从中删除。 <br>缓冲（buffers）是根据磁盘的读写设计的，把分散的写操作集中进行，减少磁盘碎片和硬盘的反复寻道，从而提高系统性能。<br>两者都是RAM中的数据。简单来说，buffer是即将要被写入磁盘的，而cache是被从磁盘中读出来的。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buffer是由各种进程分配的，被用在如输入队列等方面，一个简单的例子如某个进程要求有多个字段读入，在所有字段被读入完整之前，进程把先前读入的字段放在buffer中保存。 <br>cache经常被用在磁盘的I/O请求上，如果有多个进程都要访问某个文件，于是该文件便被做成cache以方便下次被访问，这样可提供系统性能。
<p style="font-size: 12pt;" align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cache 和 buffer的区别:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache：
高速缓存,是位于CPU与主内存间的一种容量较小但速度很高的存储器。由于CPU的速度远高于主内存，CPU直接从内存中存取数据要等待一定时间周期，
Cache中保存着CPU刚用过或循环使用的一部分数据，当CPU再次使用该部分数据时可从Cache中直接调用,这样就减少了CPU的等待时间,提高了
系统的效率。Cache又分为一级Cache(L1 Cache)和二级Cache(L2 Cache)，L1 Cache集成在CPU内部，L2
Cache早期一般是焊在主板上,现在也都集成在CPU内部，常见的容量有256KB或512KB L2 Cache。<br>&nbsp;　Buffer：缓冲区，一个用于存储速度不同步的设备或优先级不同的设备之间传输数据的区域。通过缓冲区，可以使进程之间的相互等待变少，从而使从速度慢的设备读入数据时，速度快的设备的操作进程不发生间断。</p><img src ="http://www.cppblog.com/richardhe/aggbug/62736.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-09-25 09:45 <a href="http://www.cppblog.com/richardhe/articles/62736.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++位运算</title><link>http://www.cppblog.com/richardhe/articles/62198.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Thu, 18 Sep 2008 09:39:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/62198.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/62198.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/62198.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/62198.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/62198.html</trackback:ping><description><![CDATA[<font face="Verdana">前言&nbsp;&nbsp; <br>
&nbsp; 看到有些人对位运算还存在问题，于是决定写这篇文章作个简要说明。&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 什么是位(bit)？&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;很简单，位(bit)就是单个的0或1，位是我们在计算机上所作一切的基础。计算机上的所有数据都是用位来存储的。一个字节(BYTE)由八个位组成，一个字(WORD)是二个字节或十六位，一个双字(DWORD)是二个字(WORDS)或三十二位。如下所示：&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp; 1&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;&nbsp;
0&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;&nbsp; 0&nbsp;&nbsp; 1&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; <br>
&nbsp; |&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; |&nbsp;&nbsp; <br>
&nbsp; |&nbsp;&nbsp; +-&nbsp;&nbsp; bit&nbsp;&nbsp; 31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bit&nbsp;&nbsp; 0&nbsp;&nbsp; -+&nbsp;&nbsp; |&nbsp;&nbsp; <br>
&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; <br>
&nbsp; +--&nbsp;&nbsp; BYTE&nbsp;&nbsp; 3&nbsp;&nbsp; ----&nbsp;&nbsp; -+----&nbsp;&nbsp; BYTE&nbsp;&nbsp; 2&nbsp;&nbsp; ---+----&nbsp;&nbsp; BYTE&nbsp;&nbsp; 1&nbsp;&nbsp; ---+---&nbsp;&nbsp; BYTE&nbsp;&nbsp; 0&nbsp;&nbsp; -----+&nbsp;&nbsp; <br>
&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; <br>
&nbsp; +------------&nbsp;&nbsp; WORD&nbsp;&nbsp; 1&nbsp;&nbsp; ------------+-----------&nbsp;&nbsp; WORD&nbsp;&nbsp; 0&nbsp;&nbsp; -------------+&nbsp;&nbsp; <br>
&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp; <br>
&nbsp; +-----------------------------&nbsp;&nbsp; DWORD&nbsp;&nbsp; -----------------------------+&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;使用位运算的好处是可以将BYTE,&nbsp;&nbsp; WORD&nbsp;&nbsp; 或&nbsp;&nbsp; DWORD&nbsp;&nbsp; 作为小数组或结构使用。通过位运算可以检查位的值或赋值，也可以对整组的位进行运算。&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 16进制数及其与位的关系&nbsp;&nbsp; <br>
&nbsp; 用0或1表示的数值就是二进制数，很难理解。因此用到16进制数。&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 16进制数用4个位表示0&nbsp;&nbsp; -&nbsp;&nbsp; 15的值，4个位组成一个16进制数。也把4位成为半字节(nibble)。一个BYTE有二个nibble，因此可以用二个16进制数表示一个BYTE。如下所示：&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; NIBBLE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HEX&nbsp;&nbsp; VALUE&nbsp;&nbsp; <br>
&nbsp; ======&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =========&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 0000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 0001&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 0010&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 0011&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 0100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 0101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 0110&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 0111&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 1000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 1001&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 9&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 1010&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 1011&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 1100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 1101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 1110&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; E&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 1111&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; F&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 如果用一个字节存放字母"r"(ASCII码114)，结果是：&nbsp;&nbsp; <br>
&nbsp; 0111&nbsp;&nbsp; 0010&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 二进制&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 16进制&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 可以表达为：'0x72'&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 有6种位运算：&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 与运算&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 或运算&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ^&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 异或运算&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ~&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 非运算(求补)&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &gt;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 右移运算&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 左移运算&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 与运算(&amp;)&nbsp;&nbsp; <br>
&nbsp; 双目运算。二个位都置位(等于1)时，结果等于1，其它的结果都等于0。&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ==&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ==&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ==&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ==&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 与运算的一个用途是检查指定位是否置位(等于1)。例如一个BYTE里有标识位，要检查第4位是否置位，代码如下：&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; BYTE&nbsp;&nbsp; b&nbsp;&nbsp; =&nbsp;&nbsp; 50;&nbsp;&nbsp; <br>
&nbsp; if&nbsp;&nbsp; (&nbsp;&nbsp; b&nbsp;&nbsp; &amp;&nbsp;&nbsp; 0x10&nbsp;&nbsp; )&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; "Bit&nbsp;&nbsp; four&nbsp;&nbsp; is&nbsp;&nbsp; set"&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; endl;&nbsp;&nbsp; <br>
&nbsp; else&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; "Bit&nbsp;&nbsp; four&nbsp;&nbsp; is&nbsp;&nbsp; clear"&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; endl;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 上述代码可表示为：&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00110010&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; b&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&nbsp;&nbsp; 00010000&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; &amp;&nbsp;&nbsp; 0x10&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; ----------------------------&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00010000&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; result&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 可以看到第4位是置位了。&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 或运算(&nbsp;&nbsp; |&nbsp;&nbsp; )&nbsp;&nbsp; <br>
&nbsp; 双目运算。二个位只要有一个位置位，结果就等于1。二个位都为0时，结果为0。&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ==&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ==&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ==&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ==&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 与运算也可以用来检查置位。例如要检查某个值的第3位是否置位：&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; BYTE&nbsp;&nbsp; b&nbsp;&nbsp; =&nbsp;&nbsp; 50;&nbsp;&nbsp; <br>
&nbsp; BYTE&nbsp;&nbsp; c&nbsp;&nbsp; =&nbsp;&nbsp; b&nbsp;&nbsp; |&nbsp;&nbsp; 0x04;&nbsp;&nbsp; <br>
&nbsp; cout&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; "c&nbsp;&nbsp; =&nbsp;&nbsp; "&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; c&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; endl;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 可表达为：&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00110010&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; b&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; 00000100&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; |&nbsp;&nbsp; 0x04&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----------&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00110110&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; result&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 异或运算(^)&nbsp;&nbsp; <br>
&nbsp; 双目运算。二个位不相等时，结果为1，否则为0。&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ^&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ==&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ^&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ==&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ^&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ==&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ^&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ==&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 异或运算可用于位值翻转。例如将第3位与第4位的值翻转：&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; BYTE&nbsp;&nbsp; b&nbsp;&nbsp; =&nbsp;&nbsp; 50;&nbsp;&nbsp; <br>
&nbsp; cout&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; "b&nbsp;&nbsp; =&nbsp;&nbsp; "&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; b&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; endl;&nbsp;&nbsp; <br>
&nbsp; b&nbsp;&nbsp; =&nbsp;&nbsp; b&nbsp;&nbsp; ^&nbsp;&nbsp; 0x18;&nbsp;&nbsp; <br>
&nbsp; cout&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; "b&nbsp;&nbsp; =&nbsp;&nbsp; "&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; b&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; endl;&nbsp;&nbsp; <br>
&nbsp; b&nbsp;&nbsp; =&nbsp;&nbsp; b&nbsp;&nbsp; ^&nbsp;&nbsp; 0x18;&nbsp;&nbsp; <br>
&nbsp; cout&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; "b&nbsp;&nbsp; =&nbsp;&nbsp; "&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; b&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; endl;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 可表达为：&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00110010&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; b&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ^&nbsp;&nbsp; 00011000&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; ^0x18&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----------&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00101010&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; result&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00101010&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; b&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ^&nbsp;&nbsp; 00011000&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; ^0x18&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----------&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00110010&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; result&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 非运算(~)&nbsp;&nbsp; <br>
&nbsp; 单目运算。位值取反，置0为1，或置1为0。非运算的用途是将指定位清0，其余位置1。非运算与数值大小无关。例如将第1位和第2位清0，其余位置1：&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; BYTE&nbsp;&nbsp; b&nbsp;&nbsp; =&nbsp;&nbsp; ~0x03;&nbsp;&nbsp; <br>
&nbsp; cout&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; "b&nbsp;&nbsp; =&nbsp;&nbsp; "&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; b&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; endl;&nbsp;&nbsp; <br>
&nbsp; WORD&nbsp;&nbsp; w&nbsp;&nbsp; =&nbsp;&nbsp; ~0x03;&nbsp;&nbsp; <br>
&nbsp; cout&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; "w&nbsp;&nbsp; =&nbsp;&nbsp; "&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; w&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; endl;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 可表达为：&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00000011&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; 0x03&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 11111100&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; ~0x03&nbsp;&nbsp;&nbsp;&nbsp; b&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0000000000000011&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; 0x03&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1111111111111100&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; ~0x03&nbsp;&nbsp;&nbsp;&nbsp; w&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 非运算和与运算结合，可以确保将指定为清0。如将第4位清0：&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; BYTE&nbsp;&nbsp; b&nbsp;&nbsp; =&nbsp;&nbsp; 50;&nbsp;&nbsp; <br>
&nbsp; cout&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; "b&nbsp;&nbsp; =&nbsp;&nbsp; "&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; b&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; endl;&nbsp;&nbsp; <br>
&nbsp; BYTE&nbsp;&nbsp; c&nbsp;&nbsp; =&nbsp;&nbsp; b&nbsp;&nbsp; &amp;&nbsp;&nbsp; ~0x10;&nbsp;&nbsp; <br>
&nbsp; cout&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; "c&nbsp;&nbsp; =&nbsp;&nbsp; "&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; c&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; endl;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 可表达为：&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00110010&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; b&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&nbsp;&nbsp; 11101111&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; ~0x10&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ----------&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00100010&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; result&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 移位运算(&gt;&gt;&nbsp;&nbsp; 与&nbsp;&nbsp; &lt;&lt;)&nbsp;&nbsp; <br>
&nbsp; 将位值向一个方向移动指定的位数。右移&nbsp;&nbsp; &gt;&gt;&nbsp;&nbsp; 算子从高位向低位移动，左移&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; 算子从低位向高位移动。往往用位移来对齐位的排列(如MAKEWPARAM,&nbsp;&nbsp; HIWORD,&nbsp;&nbsp; LOWORD&nbsp;&nbsp; 宏的功能)。&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; BYTE&nbsp;&nbsp; b&nbsp;&nbsp; =&nbsp;&nbsp; 12;&nbsp;&nbsp; <br>
&nbsp; cout&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; "b&nbsp;&nbsp; =&nbsp;&nbsp; "&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; b&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; endl;&nbsp;&nbsp; <br>
&nbsp; BYTE&nbsp;&nbsp; c&nbsp;&nbsp; =&nbsp;&nbsp; b&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; 2;&nbsp;&nbsp; <br>
&nbsp; cout&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; "c&nbsp;&nbsp; =&nbsp;&nbsp; "&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; c&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; endl;&nbsp;&nbsp; <br>
&nbsp; c&nbsp;&nbsp; =&nbsp;&nbsp; b&nbsp;&nbsp; &gt;&gt;&nbsp;&nbsp; 2;&nbsp;&nbsp; <br>
&nbsp; cout&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; "c&nbsp;&nbsp; =&nbsp;&nbsp; "&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; c&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; endl;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 可表达为：&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00001100&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; b&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00110000&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; b&nbsp;&nbsp; &lt;&lt;&nbsp;&nbsp; 2&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00000011&nbsp;&nbsp;&nbsp;&nbsp; -&nbsp;&nbsp; b&nbsp;&nbsp; &gt;&gt;&nbsp;&nbsp; 2&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 译注：以上示例都对，但举例用法未必恰当。请阅文末链接的文章，解释得较为清楚。&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 位域(Bit&nbsp;&nbsp; Field)&nbsp;&nbsp; <br>
&nbsp;位操作中的一件有意义的事是位域。利用位域可以用BYTE,&nbsp;&nbsp; WORD或DWORD来创建最小化的数据结构。例如要保存日期数据，并尽可能减少内存占用，就可以声明这样的结构：&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; struct&nbsp;&nbsp; date_struct&nbsp;&nbsp; {&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BYTE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; day&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp; 5,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; 1&nbsp;&nbsp; to&nbsp;&nbsp; 31&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; month&nbsp;&nbsp; :&nbsp;&nbsp; 4,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; 1&nbsp;&nbsp; to&nbsp;&nbsp; 12&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; year&nbsp;&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp; 14;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; 0&nbsp;&nbsp; to&nbsp;&nbsp; 9999&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }date;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
&nbsp; 在结构中，日期数据占用最低5位，月份占用4位，年占用14位。这样整个日期数据只需占用23位，即3个字节。忽略第24位。如果用整数来表达各个域，整个结构要占用12个字节。&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; |&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; |&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; |&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp; |&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +-------------&nbsp;&nbsp; year&nbsp;&nbsp; --------------+&nbsp;&nbsp; month+--&nbsp;&nbsp; day&nbsp;&nbsp; --+&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 现在分别看看在这个结构声明中发生了什么&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;
首先看一下位域结构使用的数据类型。这里用的是BYTE。1个BYTE有8个位，编译器将分配1个BYTE的内存。如果结构内的数据超过8位，编译器就再
分配1个BYTE，直到满足数据要求。如果用WORD或DWORD作结构的数据类型，编译器就分配一个完整的32位内存给结构。&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 其次看一下域声明。变量(day,&nbsp;&nbsp; month,&nbsp;&nbsp; year)名跟随一个冒号，冒号后是变量占用的位数。位域之间用逗号分隔，用分号结束。&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; 使用了位域结构，就可以方便地象处理普通结构数据那样处理成员数据。尽管我们无法得到位域的地址，却可以使用结构地址。例如：&nbsp;&nbsp; <br>
&nbsp; date.day&nbsp;&nbsp; =&nbsp;&nbsp; 12;&nbsp;&nbsp; <br>
&nbsp; dateptr&nbsp;&nbsp; =&nbsp;&nbsp; &amp;date;&nbsp;&nbsp; <br>
&nbsp; dateptr-&gt;year&nbsp;&nbsp; =&nbsp;&nbsp; 1852;</font><img src ="http://www.cppblog.com/richardhe/aggbug/62198.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-09-18 17:39 <a href="http://www.cppblog.com/richardhe/articles/62198.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>论百万人同时在线棋牌类网络游戏服务器设计</title><link>http://www.cppblog.com/richardhe/articles/61615.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Thu, 11 Sep 2008 11:10:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/61615.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/61615.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/61615.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/61615.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/61615.html</trackback:ping><description><![CDATA[<span  style="font-family: Verdana; font-size: 13px; "><div class="post" style="line-height: 150%; font-size: 13px; ">本文主要探讨如何设计一款百万人同时在线的棋牌类网络游戏服务器系统，如果您发现本文的设计上存在漏洞或不对的地方欢迎提出共同探讨。<br><h1 style="margin-top: 17pt; margin-right: 0cm; margin-bottom: 16.5pt; margin-left: 0cm; "><font size="6"><font color="#000000"><span lang="EN-US"><font face="Calibri">1.</font></span><span style="font-family: 宋体; ">总体架构图<br><br></span></font></font></h1><img height="507" alt="" src="http://www.cppblog.com/images/cppblog_com/beifangying/1.JPG" width="487" border="0"><br>&#160;<p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; line-height: 150%; font-size: 13px; "><span>注</span><span>: CMS(control and manage server) :&#160;</span><span>控制管理服务器</span><span>. GateServer :&#160;</span><span>门服务器<br></span></p><h1 style="margin-top: 17pt; margin-right: 0cm; margin-bottom: 16.5pt; margin-left: 0cm; "><font size="6"><font color="#000000"><span lang="EN-US"><font face="Calibri">2.</font></span><span style="font-family: 宋体; ">相关服务器介绍<br></span></font></font></h1><span style="font-size: 10.5pt; font-family: 宋体; ">注：除</span><span lang="EN-US" style="font-size: 10.5pt; font-family: Calibri, sans-serif; ">CMS</span><span style="font-size: 10.5pt; font-family: 宋体; ">外每台服务器都由两个程序实例构成，服务器管理客户端和服务器程序。<br><h2 style="margin-right: 0cm; margin-bottom: 13pt; margin-left: 0cm; margin-top: 10px; font-size: 13px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(102, 102, 102); "><font size="5"><font color="#000000"><span lang="EN-US"><font face="Cambria">2.1&#160;</font></span><span style="font-family: 宋体; ">控制管理服务器（</span><span lang="EN-US"><font face="Cambria">CMS</font></span><span style="font-family: 宋体; ">）</span></font></font></h2><p class="MsoNormal" style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; line-height: 150%; font-size: 13px; "><span lang="EN-US"><font face="Calibri">CMS</font></span><span style="font-family: 宋体; ">的作用是管理和配置所有的服务器。主备账号服务器、主备</span><span lang="EN-US"><font face="Calibri">GATE</font></span><span style="font-family: 宋体; ">服务器的切换也是由</span><span lang="EN-US"><font face="Calibri">CMS</font></span><span style="font-family: 宋体; ">决定的，服务器管理员通过</span><span lang="EN-US"><font face="Calibri">CMS</font></span><span style="font-family: 宋体; ">来管理所有的服务器。</span></p><h2 style="margin-right: 0cm; margin-bottom: 13pt; margin-left: 0cm; margin-top: 10px; font-size: 13px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(102, 102, 102); "><font size="5"><font color="#000000"><span lang="EN-US"><font face="Cambria">2.2&#160;</font></span><span style="font-family: 宋体; ">账号服务器</span></font></font></h2><p class="MsoNormal" style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; line-height: 150%; font-size: 13px; "><span style="font-family: 宋体; ">账号服务器的主要用于处理用户注册和登录游戏系统。用户是否重复登录游戏也将在账号服务器上处理。账号服务器由主备构成，任何时候只有主账号服务器负责和客户端及</span><span lang="EN-US"><font face="Calibri">GATE</font></span><span style="font-family: 宋体; ">服务器交互；备用账号服务器主要处理</span><span lang="EN-US"><font face="Calibri">CMS</font></span><span style="font-family: 宋体; ">发来的控制消息及主账号服务器发来的实时数据备份消息，及其他服务器发来的心跳消息。</span></p><h2 style="margin-right: 0cm; margin-bottom: 13pt; margin-left: 0cm; margin-top: 10px; font-size: 13px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(102, 102, 102); "><font size="5"><font color="#000000"><span lang="EN-US"><font face="Cambria">2.3&#160;</font></span><span style="font-family: 宋体; ">门服务器（</span><span lang="EN-US"><font face="Cambria">GateServer</font></span><span style="font-family: 宋体; ">）</span></font></font></h2><p class="MsoNormal" style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; line-height: 150%; font-size: 13px; "><span style="font-family: 宋体; ">门服务器的作用是负责各服务器之间的消息转发，确定用户的资料在哪台数据库服务器上。门服务器也分为主用和备用两台，除</span><span lang="EN-US"><font face="Calibri">CMS</font></span><span style="font-family: 宋体; ">外的其他服务器只和主用的门服务器交互。当</span><span lang="EN-US"><font face="Calibri">CMS</font></span><span style="font-family: 宋体; ">发现主用门服务器故障时将通知其他服务器进行主备切换。</span></p><h2 style="margin-right: 0cm; margin-bottom: 13pt; margin-left: 0cm; margin-top: 10px; font-size: 13px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(102, 102, 102); "><font size="5"><font color="#000000"><span lang="EN-US"><font face="Cambria">2.4&#160;</font></span><span style="font-family: 宋体; ">大厅服务器</span></font></font></h2><p class="MsoNormal" style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; line-height: 150%; font-size: 13px; "><span style="font-family: 宋体; ">当用户登录成功后将和大厅服务器保持长连接以实时获取游戏系统的信息。</span></p><h2 style="margin-right: 0cm; margin-bottom: 13pt; margin-left: 0cm; margin-top: 10px; font-size: 13px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(102, 102, 102); "><font size="5"><font color="#000000"><span lang="EN-US"><font face="Cambria">2.5&#160;</font></span><span style="font-family: 宋体; ">游戏服务器</span></font></font></h2><p class="MsoNormal" style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; line-height: 150%; font-size: 13px; "><span style="font-family: 宋体; ">当用户在大厅中点击进入某个游戏时，用户将登录相应的游戏服务器进行游戏。</span></p><h2 style="margin-right: 0cm; margin-bottom: 13pt; margin-left: 0cm; margin-top: 10px; font-size: 13px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(102, 102, 102); "><font size="5"><font color="#000000"><span lang="EN-US"><font face="Cambria">2.6&#160;</font></span><span style="font-family: 宋体; ">数据库服务器</span></font></font></h2><p class="MsoNormal" style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; line-height: 150%; font-size: 13px; "><span style="font-family: 宋体; ">数据库服务器主要保存用户的资料和用户的游戏数据。</span></p><h2 style="margin-right: 0cm; margin-bottom: 13pt; margin-left: 0cm; margin-top: 10px; font-size: 13px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(102, 102, 102); "><font size="5"><font color="#000000"><span lang="EN-US"><font face="Cambria">2.7&#160;</font></span><span style="font-family: 宋体; ">消息服务器</span></font></font></h2><p class="MsoNormal" style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; line-height: 150%; font-size: 13px; "><span style="font-family: 宋体; ">主要负责用户聊天消息的处理。</span></p><h1 style="margin-top: 17pt; margin-right: 0cm; margin-bottom: 16.5pt; margin-left: 0cm; "><font size="6"><font color="#000000"><span lang="EN-US"><font face="Calibri">3.</font></span><span style="font-family: 宋体; ">流程介绍<br></span></font></font></h1></span><h2 style="margin-right: 0cm; margin-bottom: 13pt; margin-left: 0cm; margin-top: 10px; font-size: 13px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(102, 102, 102); "><font size="5"><font color="#000000"><span lang="EN-US"><font face="Cambria">3.1&#160;</font></span><span style="font-family: 宋体; ">系统启动流程</span></font></font></h2><img height="88" alt="" src="http://www.cppblog.com/images/cppblog_com/beifangying/2.JPG" width="563" border="0"><br><p class="MsoNormal" style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; line-height: 150%; font-size: 13px; "><span style="font-family: 宋体; ">如图所示，系统最先启动的是</span><span lang="EN-US"><font face="Calibri">CMS</font></span><span style="font-family: 宋体; ">，当</span><span lang="EN-US"><font face="Calibri">CMS</font></span><span style="font-family: 宋体; ">启动之后将从本地数据库读取相关服务器配置信息，只有本地配置中存在的服务器才可以连接本系统正常工作；这样就可以保证只有合法的服务器才能连接到本系统以防止非法服务器的接入。当门服务器启动并连接</span><span lang="EN-US"><font face="Calibri">CMS</font></span><span style="font-family: 宋体; ">后</span><span lang="EN-US"><font face="Calibri">CMS</font></span><span style="font-family: 宋体; ">将选择其中一个作为主用门服务器。接下来依次启动的是数据库服务器，大厅服务器，游戏服务器，消息服务器。最后启动的是账号服务器。</span></p><h2 style="margin-right: 0cm; margin-bottom: 13pt; margin-left: 0cm; margin-top: 10px; font-size: 13px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(102, 102, 102); "><font size="5"><font color="#000000"><span lang="EN-US"><font face="Cambria">3.2&#160;</font></span><span style="font-family: 宋体; ">添加一台新服务器流程</span></font></font></h2><img height="549" alt="" src="http://www.cppblog.com/images/cppblog_com/beifangying/3.JPG" width="498" border="0"><br><br><h2 style="margin-right: 0cm; margin-bottom: 13pt; margin-left: 0cm; margin-top: 10px; font-size: 13px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(102, 102, 102); "><font size="5"><font color="#000000"><span lang="EN-US"><font face="Cambria">3.3&#160;</font></span><span style="font-family: 宋体; ">用户登录流程</span></font></font></h2><img height="700" alt="" src="http://www.cppblog.com/images/cppblog_com/beifangying/4.JPG" width="533" border="0"><br><br><br><p class="postfoot" style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; line-height: 150%; font-size: 11px; ">posted on 2008-09-11 17:15&#160;<a href="http://www.cppblog.com/beifangying/" style="text-decoration: none; color: rgb(102, 102, 102); background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; ">司强</a>&#160;阅读(78)&#160;<a href="http://www.cppblog.com/beifangying/archive/2008/09/11/61600.html#Post" style="text-decoration: none; color: rgb(102, 102, 102); background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; ">评论(2)</a>&#160;&#160;<a href="http://www.cppblog.com/beifangying/admin/EditPosts.aspx?postid=61600" style="text-decoration: none; color: rgb(102, 102, 102); background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; ">编辑</a>&#160;<a href="http://www.cppblog.com/beifangying/AddToFavorite.aspx?id=61600" style="text-decoration: none; color: rgb(102, 102, 102); background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; ">收藏</a>&#160;<a href="http://www.cppblog.com/beifangying/services/trackbacks/61600.aspx" style="text-decoration: none; color: rgb(102, 102, 102); background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; ">引用</a></p></div><img src="http://www.cppblog.com/beifangying/aggbug/61600.html?webview=1" width="1" height="1"><div id="AjaxHolder_UpdatePanel1"><a name="pagedcomment" style="color: rgb(102, 102, 102); text-decoration: none; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; "></a><a name="评论" style="color: rgb(102, 102, 102); text-decoration: none; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; "></a><div id="comments"><a name="评论" style="color: rgb(102, 102, 102); text-decoration: none; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; "><h3 style="font-size: 15px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(170, 170, 170); ">评论</h3></a><h4 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 13px; "><a name="评论" style="color: rgb(102, 102, 102); text-decoration: none; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; "></a><a title="permalink: re: 论百万人同时在线棋牌类网络游戏服务器设计" href="http://www.cppblog.com/beifangying/archive/2008/09/11/61600.html#61608" style="text-decoration: none; color: rgb(102, 102, 102); background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; ">#</a>&#160;<a name="61608" style="color: rgb(102, 102, 102); text-decoration: none; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; "></a>re: 论百万人同时在线棋牌类网络游戏服务器设计&#160;<span style="color: rgb(153, 153, 153); ">2008-09-11 18:14&#160;</span><a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" href="http://www.cppblog.com/aurain/" target="_blank" style="text-decoration: none; color: rgb(102, 102, 102); background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; ">水</a></h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; line-height: 150%; font-size: 13px; ">帐号服务器的用户数据如何与数据库服务器同步？定期吗？当用户登录游戏服务器后，应该同大厅服务器断开连接吧？所有用户均向一台帐号服务器登录吗？&#160;&#160;<a onclick="return SetReplyAuhor(&quot;水&quot;)" href="http://www.cppblog.com/beifangying/archive/2008/09/11/61600.html#post" style="text-decoration: none; color: rgb(102, 102, 102); background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; ">回复</a>&#160;&#160;<a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=%e6%b0%b4" target="_blank" style="text-decoration: none; color: rgb(102, 102, 102); background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; ">更多评论</a>&#160;<a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink" href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl00$DeleteLink','')" style="text-decoration: none; color: rgb(102, 102, 102); background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; "></a>&#160;&#160;<a id="AjaxHolder_Comments_CommentList_ctl00_EditLink" style="color: rgb(102, 102, 102); text-decoration: none; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; "></a></p><h4 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 13px; "><a title="permalink: re: 论百万人同时在线棋牌类网络游戏服务器设计" href="http://www.cppblog.com/beifangying/archive/2008/09/11/61600.html#61611" style="text-decoration: none; color: rgb(102, 102, 102); background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; ">#</a>&#160;<a name="61611" style="color: rgb(102, 102, 102); text-decoration: none; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; "></a>re: 论百万人同时在线棋牌类网络游戏服务器设计<a name="Post" style="color: rgb(102, 102, 102); text-decoration: none; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; "></a>&#160;<span style="color: rgb(153, 153, 153); ">2008-09-11 18:28&#160;</span><a id="AjaxHolder_Comments_CommentList_ctl01_NameLink" href="http://www.cppblog.com/hideto/" target="_blank" style="text-decoration: none; color: rgb(102, 102, 102); background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; ">Hideto</a></h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; line-height: 150%; font-size: 13px; ">用户流程简化来看：<br>前端LoadBalance -> 用户认证服务器组 -> LoadBalance -> 大厅服务器组 -> LoadBalance -> 游戏服务器组<br><br>1，访问前端LoadBalance，负载均衡，建立到一个用户认证服务器的新连接<br>2，访问用户认证服务器，用户输入登录id和密码进行认证，通过后断开连接，负载均衡，建立到一个大厅服务器的新连接<br>3，访问大厅服务器，用户选择一款游戏，断开连接，LoadBalance，建立到一个游戏服务器的新连接<br>4，开始游戏&#160;&#160;<a onclick="return SetReplyAuhor(&quot;Hideto&quot;)" href="http://www.cppblog.com/beifangying/archive/2008/09/11/61600.html#post" style="text-decoration: none; color: rgb(102, 102, 102); background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; ">回复</a>&#160;&#160;<a title="查看该作者发表过的评论" href="http://www.cppblog.com/comment?author=Hideto" target="_blank" style="text-decoration: none; color: rgb(102, 102, 102); background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; ">更多评论</a>&#160;<a id="AjaxHolder_Comments_CommentList_ctl01_DeleteLink" href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl01$DeleteLink','')" style="text-decoration: none; color: rgb(102, 102, 102); background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; "></a>&#160;&#160;<a id="AjaxHolder_Comments_CommentList_ctl01_EditLink" style="color: rgb(102, 102, 102); text-decoration: none; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; background-position: initial initial; "></a></p><div><span  style="line-height: 19px;"><br></span></div></div></div></span><img src ="http://www.cppblog.com/richardhe/aggbug/61615.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-09-11 19:10 <a href="http://www.cppblog.com/richardhe/articles/61615.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ansi、Unicode、UTF8字符串之间的转换和写入文本文件</title><link>http://www.cppblog.com/richardhe/articles/60564.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Mon, 01 Sep 2008 01:37:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/60564.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/60564.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/60564.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/60564.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/60564.html</trackback:ping><description><![CDATA[<p>转载请注明出处<a  href="http://www.cppblog.com/greatws/archive/2008/08/31/60546.html">http://www.cppblog.com/greatws/archive/2008/08/31/60546.html</a><br><br>最近有人问我关于这个的问题，就此写一篇blog<br><br>Ansi字符串我们最熟悉，英文占一个字节，汉字2个字节，以一个\0结尾，常用于txt文本文件<br>Unicode
字符串，每个字符(汉字、英文字母)都占2个字节，以2个连续的\0结尾，NT操作系统内核用的是这种字符串，常被定义为typedef
unsigned short wchar_t;所以我们有时常会见到什么char*无法转换为unsigned
short*之类的错误，其实就是unicode<br>UTF8是Unicode一种压缩形式，英文A在unicode中表示为0x0041，老外觉得
这种存储方式太浪费，因为浪费了50%的空间，于是就把英文压缩成1个字节，成了utf8编码，但是汉字在utf8中占3个字节，显然用做中文不如
ansi合算，这就是中国的网页用作ansi编码而老外的网页常用utf8的原因。<br>UTF8在还游戏里运用的很广泛，比如WOW的lua脚本等<br><br>下面来说一下转换，主要用代码来说明吧<br>写文件我用了CFile类，其实用FILE*之类的也是一样，写文件和字符串什么类别没有关系，硬件只关心数据和长度<br><br>Ansi转Unicode<br>介绍2种方法<br></p>
<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><img  src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;CConvertDlg::OnBnClickedButtonAnsiToUnicode()<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" id="Codehighlighter1_51_1122_Open_Image" onclick="this.style.display='none'; codehighlighter1_51_1122_open_text.style.display="'none';" codehighlighter1_51_1122_closed_image.style.display="'inline';" codehighlighter1_51_1122_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" id="Codehighlighter1_51_1122_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_51_1122_closed_text.style.display="'none';" codehighlighter1_51_1122_open_image.style.display="'inline';" codehighlighter1_51_1122_open_text.style.display="'inline';"" align="top"></span><span id="Codehighlighter1_51_1122_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;"><img  src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_51_1122_Open_Text"><span style="color: #000000;">{<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;ansi&nbsp;to&nbsp;unicode</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;szAnsi&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">abcd1234你我他</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">预转换，得到所需空间的大小</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;wcsLen&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;::MultiByteToWideChar(CP_ACP,&nbsp;NULL,&nbsp;szAnsi,&nbsp;strlen(szAnsi),&nbsp;NULL,&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">分配空间要给'\0'留个空间，MultiByteToWideChar不会给'\0'空间</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;wchar_t</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;wszString&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[wcsLen&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">];<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">转换</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;::MultiByteToWideChar(CP_ACP,&nbsp;NULL,&nbsp;szAnsi,&nbsp;strlen(szAnsi),&nbsp;wszString,&nbsp;wcsLen);<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">最后加上'\0'</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;wszString[wcsLen]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">\0</span><span style="color: #000000;">'</span><span style="color: #000000;">;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">unicode版的MessageBox&nbsp;API</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;::MessageBoxW(GetSafeHwnd(),&nbsp;wszString,&nbsp;wszString,&nbsp;MB_OK);<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">接下来写入文本<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">写文本文件，头2个字节0xfeff，低位0xff写在前</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;CFile&nbsp;cFile;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;cFile.Open(_T(</span><span style="color: #000000;">"</span><span style="color: #000000;">1.txt</span><span style="color: #000000;">")</span><span style="color: #000000;">,&nbsp;CFile::modeWrite&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;CFile::modeCreate);<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">文件开头</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;cFile.SeekToBegin();<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;cFile.Write(</span><span style="color: #000000;">"</span><span style="color: #000000;">\xff\xfe</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">);<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">写入内容</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;cFile.Write(wszString,&nbsp;wcsLen&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><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;cFile.Flush();<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;cFile.Close();<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;delete[]&nbsp;wszString;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;wszString&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">NULL;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">方法2<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">设置当前地域信息，不设置的话，使用这种方法，中文不会正确显示<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">需要#include&lt;locale.h&gt;</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;setlocale(LC_CTYPE,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">chs</span><span style="color: #000000;">"</span><span style="color: #000000;">);&nbsp;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;wchar_t&nbsp;wcsStr[</span><span style="color: #000000;">100</span><span style="color: #000000;">];<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">注意下面是大写S，在unicode中，代表后面是ansi字符串<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">swprintf是sprintf的unicode版本<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">格式的前面要加大写L，代表是unicode</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;swprintf(wcsStr,&nbsp;L</span><span style="color: #000000;">"</span><span style="color: #000000;">%S</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;szAnsi);<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;::MessageBoxW(GetSafeHwnd(),&nbsp;wcsStr,&nbsp;wcsStr,&nbsp;MB_OK);<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span></div>
<br><br>Unicode转Ansi<br>也是2种方法<br><br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><img  src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;CConvertDlg::OnBnClickedButtonUnicodeToAnsi()<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" id="Codehighlighter1_51_1013_Open_Image" onclick="this.style.display='none'; codehighlighter1_51_1013_open_text.style.display="'none';" codehighlighter1_51_1013_closed_image.style.display="'inline';" codehighlighter1_51_1013_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" id="Codehighlighter1_51_1013_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_51_1013_closed_text.style.display="'none';" codehighlighter1_51_1013_open_image.style.display="'inline';" codehighlighter1_51_1013_open_text.style.display="'inline';"" align="top"></span><span id="Codehighlighter1_51_1013_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;"><img  src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_51_1013_Open_Text"><span style="color: #000000;">{<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;unicode&nbsp;t