<?xml version="1.0" encoding="utf-8"?><rss version="2.0">
<channel>
<title><![CDATA[挑逗C/C++]]></title>
<link>http://blog.pfan.cn/manbuyuduan</link>
<description>编程爱好者博客</description>
<language>zh-cn</language>
			<item>
		<title><![CDATA[安装SQL2000指定的服务并未以已安装的服务存在]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/52315.html</link>
		<description><![CDATA[一、将计算机名改成大写。

二、将sql server的安装文件夹和数据文件夹全部删除

三、用如下方法对付安装挂起问题：

1、在开始-&gt;运行中输入regedit

2、到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager 位置

3、选择文件-&gt;导出,保存（安全起见）

4、在右边窗口右击PendingFileRenameOperations，选择删除，然后确认
四、用删除注册表中相关项解决多实例问题：

1、删除HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server

2、删除HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer

3、删除HKEY_LOCAL_USER\SOFTWARE\Microsoft\Microsoft SQL Server

4、 + HKEY_LOCAL_MACHINE

+ SOFTWART

+ Microsoft

+ Windows

+ CurrentVersion

+ Setup

+ ExceptionComponents

将 ExceptionComponents 下面的文件夹全部删除!

如 {60BFF50D-FB2C-4498-A577-C9548C390BB9}

{60BFF50D-FB2C-4498-A577-C9548C390BB9}

{60BFF50D-FB2C-4498-A577-C9548C390BB9}

{60BFF50D-FB2C-4498-A577-C9548C390BB9}

.......


五、重新启动:


六、重新安装 SQL Server 2000
&nbsp;&nbsp; ======================
以上方法本人已经过验证,确实可行!~~~~~]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2011-03-14 14:40:00</pubDate>
		</item>
				<item>
		<title><![CDATA[C++&nbsp;运算符优先级列表]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51829.html</link>
		<description><![CDATA[Precedence
Operator
Description
Example
Associativity


1
()
[]
-&gt;
.
::
++
--
Grouping operator
Array access
Member access from a pointer
Member access from an object
Scoping operator
Post-increment
Post-decrement
(a + b) / 4;
array[4] = 2;
ptr-&gt;age = 34;
obj.age = 34;
Class::age = 2;
for( i = 0; i &lt; 10; i++ ) ...
for( i = 10; i &gt; 0; i-- ) ...
left to right


2
!
~
++
--
-
+
*
&amp;
(type)
sizeof
Logical negation
Bitwise complement
Pre-increment
Pre-decrement
Unary minus
Unary plus
Dereference
Address of
Cast to a given type
Return size in bytes
if( !done ) ...
flags = ~flags;
for( i = 0; i &lt; 10; ++i ) ...
for( i = 10; i &gt; 0; --i ) ...
int i = -1;
int i = +1;
data = *ptr;
address = &amp;obj;
int i = (int) floatNum;
int size = sizeof(floatNum);
right to left


3
-&gt;*
.*
Member pointer selector
Member pointer selector
ptr-&gt;*var = 24;
obj.*var = 24;
left to right


4
*
/
%
Multipli]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-09-29 13:56:00</pubDate>
		</item>
				<item>
		<title><![CDATA[CString&nbsp;与folat&nbsp;int&nbsp;char*&nbsp;CTime&nbsp;string转换]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51804.html</link>
		<description><![CDATA[CString 与folat int char * CTime string等的互相转变 
本文 总结了如何实现CString 与folat&nbsp;&nbsp; int&nbsp;&nbsp; char *&nbsp;&nbsp; CTime&nbsp; string等的互相转变方法。
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CString 是一种很特殊的 C++ 对象，它里面包含了三个值：一个指向某个数据缓冲区的指针、一个是该缓冲中有效的字符记数(它是不可存取的，是位于 CString 地址之下的一个隐藏区域)以及一个缓冲区长度。 有效字符数的大小可以是从0到该缓冲最大长度值减1之间的任何数（因为字符串结尾有一个NULL字符）。字符记数和缓冲区长度被巧妙隐藏。
1. CString 与 float 的转变
1) CString 转变为float 
&nbsp;&nbsp;&nbsp; CString strContent;
&nbsp;&nbsp;&nbsp; float fNum;
&nbsp;&nbsp; fNum=atof(strContent);
2)float 转变为CString
&nbsp;&nbsp;&nbsp;&nbsp; CString&nbsp;&nbsp; strContent;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp; float&nbsp;&nbsp; fNum;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp; strContent.format("%f",fNum);
2. CString 与int 的转变
1)CString转变为int
&nbsp;&nbsp; CString strContent;
&nbsp;&nbsp;&nbsp; int nNum;
&nbsp;&nbsp; nNum=atoi(strContent);
2) int 转变为CSting
&nbsp;&nbsp;&nbsp; CString&nbsp;&nbsp; strContent;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp; int nNum;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-09-20 22:24:00</pubDate>
		</item>
				<item>
		<title><![CDATA[c++&nbsp;结构体字节对齐[转]]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51790.html</link>
		<description><![CDATA[结构体(struct)的sizeof值，并不是简单的将其中各元素所占字节相加，而是要考虑到存储空间的字节对齐问题。先看下面定义的两个结构体.
struct
{
char a;
short b;
char c;
}S1;
struct
{
char a;
char b;
short c;
}S2;
分别用程序测试得出sizeof(S1)=6 , sizeof(S2)=4
可见，虽然两个结构体所含的元素相同，但因为其中存放的元素类型顺序不一样，所占字节也出现差异。这就是字节对齐原因。通过字节对齐，有助于加快计算机的取数速度，否则就得多花指令周期。

字节对齐原则
结构体默认的字节对齐一般满足三个准则：
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除；
2) 结构体每个成员相对于结构体首地址的偏移量（offset）都是成员自身大小的整数倍，如有需要编译器会在成员之间加上填充字节（internal adding）；
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍，如有需要编译器会在最末一个成员之后加上填充字节（trailing padding）。

通过这三个原则，就不难理解上面两个struct的差异了.
对于struct S1, 为了使short变量满足字节对其准则(2), 即其存储位置相对于结构体首地址的offset是自身大小(short占2个字节)的整数倍，必须在字节a后面填充一个字节以对齐；再由准则(3),为了 满足结构体总大小为short大小的整数倍，必须再在c后面填充一个字节。

对于struct S2, 却不必如上所述的填充字节，因为其直接顺序存储已经满足了对齐准则。

如果将上面两个结构体中的short都改为int(占4个字节), 那么会怎么样呢？ 程序得出sizeof(S1)=12, sizeof(S2)=8 
利用上面的准则，也不难计算得出这样的结果。S1中在a后面填充3个字节、在c后面填充3个字节，这样一共12个字节；S2中在a、b顺序存储之后填充两个字节用以对其，这样一共就8个字节。

当然，在某些时候也可以设置字节对齐方式。这就需要使用 #pragma pack 。
#pragma pack(push) //压栈保存
#pragma pack(1)// 设置1字]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-09-17 10:08:00</pubDate>
		</item>
				<item>
		<title><![CDATA[深入浅出Win32多线程程序设计之线程通信]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51762.html</link>
		<description><![CDATA[简介

　　线程之间通信的两个基本问题是互斥和同步。

　　线程同步是指线程之间所具有的一种制约关系，一个线程的执行依赖另一个线程的消息，当它没有得到另一个线程的消息时应等待，直到消息到达时才被唤醒。

　　线程互斥是指对于共享的操作系统资源（指的是广义的"资源"，而不是Windows的.res文件，譬如全局变量就是一种共享资源），在各线程访问时的排它性。当有若干个线程都要使用某一共享资源时，任何时刻最多只允许一个线程去使用，其它要使用该资源的线程必须等待，直到占用资源者释放该资源。

　　线程互斥是一种特殊的线程同步。

　　实际上，互斥和同步对应着线程间通信发生的两种情况：

　　（1）当有多个线程访问共享资源而不使资源被破坏时；

　　（2）当一个线程需要将某个任务已经完成的情况通知另外一个或多个线程时。

　　在WIN32中，同步机制主要有以下几种：

　　（1）事件(Event);

　　（2）信号量(semaphore);

　　（3）互斥量(mutex);

　　（4）临界区(Critical section)。

　　全局变量

　　因为进程中的所有线程均可以访问所有的全局变量，因而全局变量成为Win32多线程通信的最简单方式。例如：




int var; //全局变量
UINT ThreadFunction(LPVOIDpParam)
{
　var = 0;
　while (var &lt; MaxValue)
　{
　　//线程处理
　　::InterlockedIncrement(long*) &amp;var);
　}
　return 0;
}
请看下列程序：
int globalFlag = false; 
DWORD WINAPI ThreadFunc(LPVOID n)
{
　Sleep(2000);
　globalFlag = true;

　return 0;
}

int main()
{
　HANDLE hThrd;
　DWORD threadId;

　hThrd = CreateThread(NULL, 0, ThreadFunc, NULL, 0, &amp;threadId);
　if (hThrd]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-09-11 21:31:00</pubDate>
		</item>
				<item>
		<title><![CDATA[Windows进程间通信的各种方法]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51761.html</link>
		<description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 进程是装入内存并准备执行的程序，每个进程都有私有的虚拟地址空间，由代码、数据以及它可利用的系统资源(如文件、管道等)组成。多进程/多线程是Windows操作系统的一个基本特征。Microsoft Win32应用编程接口(Application Programming Interface, API)提供了大量支持应用程序间数据共享和交换的机制，这些机制行使的活动称为进程间通信(InterProcess Communication, IPC)，进程通信就是指不同进程间进行数据共享和数据交换。
　　正因为使用Win32 API进行进程通信方式有多种，如何选择恰当的通信方式就成为应用开发中的一个重要问题，下面本文将对Win32中进程通信的几种方法加以分析和比较。
2 进程通信方法
2.1 文件映射
文件映射(Memory-Mapped Files)能使进程把文件内容当作进程地址区间一块内存那样来对待。因此，进程不必使用文件I/O操作，只需简单的指针操作就可读取和修改文件的内容。
Win32 API允许多个进程访问同一文件映射对象，各个进程在它自己的地址空间里接收内存的指针。通过使用这些指针，不同进程就可以读或修改文件的内容，实现了对文件中数据的共享。
应用程序有三种方法来使多个进程共享一个文件映射对象。
(1)继承：第一个进程建立文件映射对象，它的子进程继承该对象的句柄。
(2)命名文件映射：第一个进程在建立文件映射对象时可以给该对象指定一个名字(可与文件名不同)。第二个进程可通过这个名字打开此文件映射对象。另外，第一个进程也可以通过一些其它IPC机制(有名管道、邮件槽等)把名字传给第二个进程。
(3)句柄复制：第一个进程建立文件映射对象，然后通过其它IPC机制(有名管道、邮件槽等)把对象句柄传递给第二个进程。第二个进程复制该句柄就取得对该文件映射对象的访问权限。
文件映射是在多个进程间共享数据的非常有效方法，有较好的安全性。但文件映射只能用于本地机器的进程之间，不能用于网络中，而开发者还必须控制进程间的同步。
2.2 共享内存
Win32 API中共享内存(Shared Memory)实际就是文件映射的一种特殊情况。进程在创建文件映射对象时用0xFFFFFFFF来代替 文件句柄(HAND]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-09-11 16:41:00</pubDate>
		</item>
				<item>
		<title><![CDATA[阶乘末尾0的个数]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51758.html</link>
		<description><![CDATA[求阶乘末尾0的个数，对于较小的数的话可以计算出来后在算末尾0的个数，但是数字较大的时候则比较麻烦，可以通过如下原理反复的除以5得到最后的结果：
原理是：&nbsp;&nbsp;
&nbsp;&nbsp; &nbsp;假如你把1×2×3×4×……×N中每一个因数分解质因数，结果就像：&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; 1&nbsp;×&nbsp;2&nbsp;× 3&nbsp;×&nbsp;(2&nbsp;× 2) × 5&nbsp;×&nbsp;(2 × 3) ×&nbsp;7&nbsp;×&nbsp;(2&nbsp;× 2&nbsp;×2) ×……&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; 10进制数结尾的每一个0都表示有一个因数10存在——任何进制都一样，对于一个M进制的数，让结尾多一个0就等价于乘以M。&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; 10可以分解为2&nbsp;× 5——因此只有质数2和5相乘能产生0，别的任何两个质数相乘都不能产生0，而且2，5相乘只产生一个0。&nbsp;&nbsp;
&nbsp;&nbsp; &nbsp;所以，分解后的整个因数式中有多少对(2,&nbsp;&nbsp; 5)，结果中就有多少个0，而分解的结果中，2的个数显然是多于5的，因此，有多少个5，就有多少个(2,&nbsp;&nbsp; 5)对。&nbsp;&nbsp;
&nbsp;&nbsp; &nbsp;所以，讨论1000的阶乘结尾有几个0的问题，就被转换成了1到1000所有这些数的质因数分解式有多少个5的问题。&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; 5的个数可以用上面那个式子算出（道理很简单，自己想想吧^_^），所以1000的阶乘结尾有249个0。
以下为代码：
#include &lt;iostream&gt;
using namespace std;
int main()
{
&nbsp;&nbsp;&nbsp; long total;
&nbsp;&nbsp;&nbsp; long Integer;
&nbsp;&nbsp;&nbsp; long i;
&nbsp;&nbsp;&nbsp; scanf("%ld", &amp;total]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-09-10 16:51:00</pubDate>
		</item>
				<item>
		<title><![CDATA[4种流行的进程线程同步互斥的控制机制]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51757.html</link>
		<description><![CDATA[现在流行的进程线程同步互斥的控制机制，其实是由最原始最基本的4种方法实现的。由这4种方法组合优化就有了.Net和Java下灵活多变的，编程简便的线程进程控制手段。 
　　这4种方法具体定义如下 在《操作系统教程》ISBN 7-5053-6193-7 一书中可以找到更加详细的解释 
　　1、临界区:通过对多线程的串行化来访问公共资源或一段代码，速度快，适合控制数据访问。 
　　2、互斥量:为协调共同对一个共享资源的单独访问而设计的。 
　　3、信号量:为控制一个具有有限数量用户资源而设计。 
　　4、事 件:用来通知线程有一些事件已发生，从而启动后继任务的开始。&nbsp;
&nbsp;&nbsp;　　
临界区（Critical Section） 
　　保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区，那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起，并一直持续到进入临界区的线程离开。临界区在被释放后，其他线程可以继续抢占，并以此达到用原子方式操作共享资源的目的。 
　　临界区包含两个操作原语： 
　　EnterCriticalSection（） 进入临界区 
　　LeaveCriticalSection（） 离开临界区 
　　EnterCriticalSection（）语句执行后代码将进入临界区以后无论发生什么，必须确保与之匹配的LeaveCriticalSection（）都能够被执行到。否则临界区保护的共享资源将永远不会被释放。虽然临界区同步速度很快，但却只能用来同步本进程内的线程，而不可用来同步多个进程中的线程。 
　　MFC提供了很多功能完备的类，我用MFC实现了临界区。MFC为临界区提供有一个CCriticalSection类，使用该类进行线程同步处理是非常简单的。只需在线程函数中用CCriticalSection类成员函数Lock（）和UnLock（）标定出被保护代码片段即可。Lock（）后代码用到的资源自动被视为临界区内的资源被保护。UnLock后别的线程才能访问这些资源。 
&nbsp;&nbsp; 
&nbsp;&nbsp;//CriticalSection 
&nbsp;&nbsp;CCriticalSection global_]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-09-10 13:51:00</pubDate>
		</item>
				<item>
		<title><![CDATA[Visio如何反向导出数据库设计文档]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51721.html</link>
		<description><![CDATA[1支持的数据库 &nbsp;

为了拥有最大弹性，Visio支持相当多数据库，包括主从模式的数据库（比如 IBM、Informix、Microsoft、Oracle 和 Sybase）、桌面数据库（比如 Microsoft Access 和 Corel Paradox）。 &nbsp;
 
2以商业规则为基础的数据库设计 &nbsp;

如果信息专业人员和一般用户都会说共通的语言，则数据库设计的需求便比较容易被达成。有了 Visio，我们可以使用对一般用户和开发者都具备意义的语言描述商业规则，完全不必担心实现问题。 &nbsp;
 
3数据库工程再造 &nbsp;

当我们规划数据库以进行今日的IT项目时（比如电子商务或顾客管理系统），我们需要以现有的 DBMS为基础，但不要被它们的限制所阻碍，而Visio具备我们所需的数据库工程再造威力。  &nbsp;
 
4工作组的协同作业 &nbsp;

大型数据库设计项目可轻易分散给开发者团队成员，利用 Visio产生项目的子模型，每一位开发者都能处理数据库上的一个子区段，而中心化的项目文件可合并来源模型而显示完整状态、将资料表与字段名称的改变对映到来源模型，然后产生数据库纲要，团队工作比以往更为容易。 &nbsp;
 
接着，我们便一同来瞧瞧“反向工程”怎么使用。 &nbsp;
 
 




1打开Microsoft Visio 专业版。此时便会出现“选择绘图类型” 对话框，由类别中选择“数据库”|“数据库模型图”。如果您已经打开Visio，则由菜单中选择“文件”|“新建”|“选择绘图类型”|“数据库”|“数据库模型图”。 






2接着，我们会在菜单中发觉多了一个“数据库”菜单，选择“数据库”|“反向工程”。 
 
 




3此时便会打开“反向工程向导”对话框。 






 
 




4在此对话框中我们可以选择其数据源，并选择适当的驱动程序。 





 





5接着出现“连接数据源”对话框，由于笔者所建立的数据库并没有设置管理员以及密码，因此直接单击“确定”即可。 





6请选择 “数据源”为“Microsoft Access Database”，单]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-08-27 14:46:00</pubDate>
		</item>
				<item>
		<title><![CDATA[Attach函数与Detach函数]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51710.html</link>
		<description><![CDATA[&nbsp;




&nbsp;&nbsp;&nbsp;&nbsp; 首先，你要明白Windows对象和MFC对象的区别。MFC对象实际上并没有把整个Windows对象都包装在其中，它只是有一个窗口句柄而已，这个窗 口句柄如果指向一个实际存在的窗口对象，那么这个MFC对象就是有效的，否则这个MFC对象是空的。如果你还不明白，请回忆一下，当我们使用MFC创建一 个窗口时，是分两步进行的，第一步，new一个CWnd对象，这一步是创建MFC对象，但是其中的HWND还是非法的，因为对应的Windows对象还没 有被创建出来；第二步，调用CWnd的成员函数Create创建真正的Windows对象，同时，把先前创建的MFC的CWnd对象的HWND成员指向该 窗口，这样才算创建完毕一个窗口。而如果你是用SDK方式，那么只要创建一个WNDCLASS结构，然后调用Create或者CreateEx就创建了一 个窗口。 
&nbsp;&nbsp;&nbsp;&nbsp; 好，现在回答你的问题，你可以假设，现在你已经有了一个有效窗口句柄，那么你想把这个窗口和一个CWnd对象关联起来怎么办？很简单，用Attach，其实就是让一个CWnd对象的HWND成员指向这个窗口句柄。这就是Attach主要完成的任务。 
&nbsp;&nbsp;&nbsp;&nbsp; 第二个，关于Detach。如前所述，WNDCLASS其实和CWnd根本没有什么关系。它们之间只是通过CWnd的成员HWND联系起来的。如果把 Attach看做“联姻”的话，那么Detach就是“离婚”了，通俗地说，就是切断一个CWnd对象和一个有效窗口的脐带。为什么要切断呢？因为 CWnd是C++的对象，C++的对象有一个生存期的概念，脱离了该对象的作用域，这个对象就要被销毁，但是Windows对象没有这个特点，当销毁 CWnd对象的时候，我们不一定希望WNDCLASS一起被销毁，那么在此之前，我们就先要把这个“脐带”剪断，以免“城门失火，殃及池鱼”。




转：http://hi.baidu.com/lrg319/blog/item/ab0d77ee926e81f1b2fb95cd.html]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-08-26 19:58:00</pubDate>
		</item>
				<item>
		<title><![CDATA[(好)(转：五种网络IO模型)winsock&nbsp;IO模型]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51699.html</link>
		<description><![CDATA[winsock IO模型



如果你想在Windows平台上构建服务器应用，那么I/O模型是你必须考虑的Windows操作系统提供了选择（Select）异步选择（WSAAsyncSelect）事件选择（WSAEventSelect）重叠I/O（Overlapped I/O）和完成端口（Completion Port)共五种I/O模型每一种模型均适用于一种特定的应用场景程序员应该对自己的应用需求非常明确，而且综合考虑到程序的扩展性和可移植性等因素，作出自己的选择
我会以一个回应反射式服务器（与Windows网络编程第八章一样）来介绍这五种I/O模型
我们假设客户端的代码如下（为代码直观，省去所有错误检查，以下同）：
#include &lt;WINSOCK2.H&gt;
#include &lt;stdio.h&gt;
#define SERVER_ADDRESS "137.117.2.148"
#define PORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5150
#define MSGSIZE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1024
#pragma comment(lib, "ws2_32.lib")
int main()
{
&nbsp; WSADATA&nbsp;&nbsp;&nbsp;&nbsp; wsaData;
&nbsp; SOCKET&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sClient;
&nbsp; SOCKADDR_IN server;
&nbsp; char&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; szMessage[MSGSIZE];
&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret;
&nbsp; 
&nbsp; // Initialize Windows socket library
&nbsp; WSAStartup(0x0202, &amp;wsaData);
&nbsp; // Create client s]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-08-23 15:41:00</pubDate>
		</item>
				<item>
		<title><![CDATA[ASSERT(afxCurrentInstanceHandle!=NULL)]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51620.html</link>
		<description><![CDATA[afxwin1.inl assert at line:23

好久没更新了，奉献一篇技术贴。
最近使用ATL 7.0 写windows服务,因为以前的程序是用MFC编写的,遇到一些麻烦,解决问题花了些时间.
拿出来共享一下.
其实就是一个经常出现的错误:
afxwin1.inl assert at line:23
现象:打开afxwin1.inl 发现assert(afxCurrentInstanceHandle != NULL)出错
我心想MFC这个垃圾不会要我手动赋吧,所以研究了很久,看看自己初始化是不是缺少什么不骤,还是哪里修改了这个值. 后来发现,手动赋才是王道,因为如果是MFC程序,这个赋值在CWinAPP的里就作了,不过因为嫌太麻烦就懒得找了,呵呵.
另外一个问题,ATL程序如何获得这个句柄呢,其实每个ATL程序都会有一个全局成员 _AtlBaserModule保存这重要的句柄.
&nbsp;
ok 
solution:
在ATL程序初始化阶段手动赋值
afxCurrentInstanceHandle = _AtlBaseModule.GetModuleInstance();
afxCurrentResourceHandle = _AtlBaseModule.GetResourceInstance(); (这个也要赋一下,呵呵)
&nbsp;
引用http://lavadiablo.spaces.live.com/blog/cns!edb786de4aef809a!246.entry
&nbsp;]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-08-11 14:58:00</pubDate>
		</item>
				<item>
		<title><![CDATA[C++中头文件相互包含的几点问题[转]]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51584.html</link>
		<description><![CDATA[一、类嵌套的疑问
C++头文件重复包含实在是一个令人头痛的问题，前一段时间在做一个简单的数据结构演示程序的时候，不只一次的遇到这种问题。假设我们有两个类A和B，分别定义在各自的有文件A.h和B.h中，但是在A中要用到B，B中也要用到A，但是这样的写法当然是错误的：
class B;
class A
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B b;
};
class B
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A a;
};
因为在A对象中要开辟一块属于B的空间，而B中又有A的空间，是一个逻辑错误，无法实现的。在这里我们只需要把其中的一个A类中的B类型成员改成指针形式就可以避免这个无限延伸的怪圈了。为什么要更改A而不是B？因为就算你在B中做了类似的动作，也仍然会编译错误，表面上这仅仅上一个先后顺序的问题。
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为什么会这样呢？因为C++编译器自上而下编译源文件的时候，对每一个数据的定义，总是需要知道定义的数据的类型的大小。在预先声明语句class B;之后，编译器已经知道B是一个类，但是其中的数据却是未知的，因此B类型的大小也不知道。这样就造成了编译失败，VC++6.0下会得到如下编译错误：
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; error C2079: 'b' uses undefined class 'B'
将A中的b更改为B指针类型之后，由于在特定的平台上，指针所占的空间是一定的（在Win32平台上是4字节），这样可以通过编译。
二、不同头文件中的类的嵌套
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在实际编程中，不同的类一般是放在不同的相互独立的头文件中的，这样两个类在相互引用时又会有不一样的问题。重复编译是问题出现的根本原因。为了保证头文件仅被编译一次，在C++中常用的办法是使用条件编译命令。在头文件中我们常常会看到以下语句段]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-08-06 13:59:00</pubDate>
		</item>
				<item>
		<title><![CDATA[醴陵瓷器]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51536.html</link>
		<description><![CDATA[　醴陵瓷器
醴陵是一座古老而充满现代气息的江南城市，享有“瓷城”美誉，是举世闻名的釉下五彩瓷原产地。瓷器是中 

国独创的发明之一，至今英文仍把瓷器称之为“ｃｈｉｎａ”。醴陵陶瓷生产已有近两千年的历史，远在东汉时期，醴陵就有较大规模的作坊，专门从事陶器制作。清朝雍正七年（1729年）醴陵开始烧制粗瓷。清朝末年至民国初年，醴陵瓷业进入到一个新的发展时期。 
　　漫长的历史长河中，有许多仁人志士和能工巧匠，为醴陵瓷业的发展呕心沥血，作出了重大贡献。1904年，湖南凤凰人熊希龄（辛亥革命后担任北洋政府总理）与曾参与“公车上书”的醴陵举人文俊铎，本着实业救国的思想赴日本考察。在日本期间，他们发现日本瓷业技术先进，产品精良。第二年回国后，熊希龄在文俊铎陪同下，前往醴陵的主要粗瓷产地进行调查，找出了醴陵瓷业生产落后的主要原因，同时又看到了醴陵进一步发展瓷业生产的有利条件：消费市场广阔，瓷土资源丰富，劳动力价格低廉。随即提出了“立学堂、设公司”等主张，得到了湖南官府的大力支持。当年，湖南官立瓷业学堂在醴陵正式开办，次年，湖南瓷业制造公司在醴陵成立，熊希龄任公司总经理，文俊铎任学堂监督。公司聘请日本技师和景德镇技术工人，引进了当时日本最先进的生产工艺和设备，开启了醴陵由粗瓷生产到细瓷开发的新纪元。独具特色的醴陵釉下五彩瓷就是在这样的背景下研制出来的。 
　　此前，醴陵瓷器用单一的氧化钴（俗称土墨）作彩饰原料，手工描绘粗犷花草图案后，施釉覆盖，烧成釉下青花瓷。1907年至1908年，湖南瓷业学堂研制出草青、海碧、艳黑、赭色和玛瑙红等多种釉下颜料。湖南瓷业制造公司的绘画名师和瓷业学堂陶画班的毕业生，经过反复研制，采用自制釉下色料，运用国画双勾分水填色和“三烧制”法，生产出令人耳目一新的釉下五彩瓷器。釉下五彩瓷器瓷质细腻，画工精美，清新雅丽，别具一格，釉层下五彩缤纷，呈现出栩栩如生的画面，具有较高的艺术价值和使用价值。它的问世，立即得到业内人士和国内外舆论的极大关注和好评。1909年到1911年，醴陵釉下五彩瓷分别参展武汉劝业会、南洋劝业会和意大利都朗国际赛会，连续获得金牌奖，醴陵瓷器开始名扬华夏，走向世界。“白如玉、明如镜、薄如纸、声如磬”，就是醴陵瓷在当时赢得的良好评价。 
　　1915年，醴陵瓷器远涉重洋，参加了在美国旧金山举行的巴拿马太平洋万国博览会，参展的釉下五彩扁]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-07-27 13:49:00</pubDate>
		</item>
				<item>
		<title><![CDATA[线程中CreateEvent和SetEvent及WaitForSingleObj]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51522.html</link>
		<description><![CDATA[首先介绍CreateEvent是创建windows事件的意思，作用主要用在判断线程退出，程锁定方面.
CreateEvent 
函功能描述：创建或打开一个命名的或无名的事件对象.
EVENT有两种状态：发信号，不发信号。 
SetEvent/ResetEvent分别将EVENT置为这两种状态分别是发信号与不发信号。 
WaitForSingleObject()等待，直到参数所指定的OBJECT成为发信号状态时才返回，OBJECT可以是EVENT，也可以是其它内核对象。 
当你创建一个线程时，其实那个线程是一个循环，不像上面那样只运行一次的。这样就带来了一个问题，在那个死循环里要找到合适的条件退出那个死循环，那么是怎么样实现它的呢？在Windows里往往是采用事件的方式，当然还可以采用其它的方式。在这里先介绍采用事件的方式来通知从线程运行函数退出来，它的实现原理是这样，在那个死循环里不断地使用 WaitForSingleObject函数来检查事件是否满足，如果满足就退出线程，不满足就继续运行。当在线程里运行阻塞的函数时，就需要在退出线程时，先要把阻塞状态变成非阻塞状态，比如使用一个线程去接收网络数据，同时使用阻塞的SOCKET时，那么要先关闭SOCKET，再发送事件信号，才可以退出线程的。
当然我感觉重要应用方面还是用来锁定，实现所谓的pv功能。
下面介绍函数功能，参数等
1.CreateEvent 




函数功能描述：创建或打开一个命名的或无名的事件对象
函数原型：
HANDLE CreateEvent(
&nbsp;&nbsp;LPSECURITY_ATTRIBUTES lpEventAttributes,&nbsp; &nbsp;// 安全属性
&nbsp;&nbsp;BOOL bManualReset,&nbsp; &nbsp;// 复位方式
&nbsp;&nbsp;BOOL bInitialState,&nbsp; &nbsp;// 初始状态
&nbsp;&nbsp;LPCTSTR lpName&nbsp; &nbsp;// 对象名称
);
参数：
lpEventAttributes：
&nbsp; &nbsp;&nbsp; &nbsp;[输入]一个指向SECURITY_ATTRIBUTES结构的指针，]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-07-21 17:24:00</pubDate>
		</item>
				<item>
		<title><![CDATA[函数的调用规则(__cdecl,__stdcall,__fastcall,__p]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51521.html</link>
		<description><![CDATA[关于函数的调用规则（调用约定），大多数时候是不需要了解的，但是如果需要跨语言的编程，比如VC写的dll要delphi调用，则需要了解。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; microsoft的vc默认的是__cdecl方式，而windows API则是__stdcall，如果用vc开发dll给其他语言用，则应该指定__stdcall方式。堆栈由谁清除这个很重要，如果是要写汇编函数给C调用，一定要小心堆栈的清除工作，如果是__cdecl方式的函数，则函数本身（如果不用汇编写）则不需要关心保存参数的堆栈的清除，但是如果是__stdcall的规则，一定要在函数退出(ret)前恢复堆栈。
1.__cdecl
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所谓的C调用规则。按从右至左的顺序压参数入栈，由调用者把参数弹出栈。切记：对于传送参数的内存栈是由调用者来维护的。返回值在EAX中因此，对于象printf这样变参数的函数必须用这种规则。编译器在编译的时候对这种调用规则的函数生成修饰名的饿时候，仅在输出函数名前加上一个下划线前缀，格式为_functionname。 
2.__stdcall 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 按从右至左的顺序压参数入栈，由被调用者把参数弹出栈。_stdcall是Pascal程序的缺省调用方式，通常用于Win32 Api中，切记：函数自己在退出时清空堆栈，返回值在EAX中。　　__stdcall调用约定在输出函数名前加上一个下划线前缀，后面加上一个“@”符号和其参数的字节数，格式为_functionname@number。如函数int func(int a, double b)的修饰名是_func@12。
3.__fastcall
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __fastcall调用的主要特点就是快，因为它是通过寄存器来传送参数的（实际上，它用ECX和EDX传送前两个双字（DWORD）或更小的参数，剩下的参数仍旧自右向左压栈传送，被调用的函数在返回前清理传送参数的内存栈）。__fastcall调用约定在输出函数名前加上一个“@”符号，后面也是一个“@”符号和其]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-07-21 15:41:00</pubDate>
		</item>
				<item>
		<title><![CDATA[网络分层协议图]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51396.html</link>
		<description><![CDATA[网络分层协议图]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-06-23 20:29:00</pubDate>
		</item>
				<item>
		<title><![CDATA[进程和线程的区别]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51367.html</link>
		<description><![CDATA[进程和线程都是由操作系统所体会的程序运行的基本单元，系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于：
简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 
线程的划分尺度小于进程，使得多线程程序的并发性高。
另外，进程在执行过程中拥有独立的内存单元，而多个线程共享内存，从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行，必须依存在应用程序中，由应用程序提供多个线程执行控制。
从逻辑角度来看，多线程的意义在于一个应用程序中，有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用，来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间，一个进程崩溃后，在保护模式下不会对其它进程产生影响，而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量，但线程之间没有单独的地址空间，一个线程死掉就等于整个进程死掉，所以多进程的程序要比多线程的程序健壮，但在进程切换时，耗费资源较大，效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作，只能用线程，不能用进程。如果有兴趣深入的话，我建议你们看看《现代操作系统》或者《操作系统的设计与实现》。对就个问题说得比较清楚。
&nbsp;
本文来自CSDN博客http://blog.csdn.net/andy6355/archive/2008/06/03/2506171.aspx]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-06-17 10:58:00</pubDate>
		</item>
				<item>
		<title><![CDATA[C++&nbsp;运算符优先级列表]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51363.html</link>
		<description><![CDATA[Precedence
Operator
Description
Example
Associativity


1
()
[]
-&gt;
.
::
++
--
Grouping operator
Array access
Member access from a pointer
Member access from an object
Scoping operator
Post-increment
Post-decrement
(a + b) / 4;
array[4] = 2;
ptr-&gt;age = 34;
obj.age = 34;
Class::age = 2;
for( i = 0; i &lt; 10; i++ ) ...
for( i = 10; i &gt; 0; i-- ) ...
left to right


2
!
~
++
--
-
+
*
&amp;
(type)
sizeof
Logical negation
Bitwise complement
Pre-increment
Pre-decrement
Unary minus
Unary plus
Dereference
Address of
Cast to a given type
Return size in bytes
if( !done ) ...
flags = ~flags;
for( i = 0; i &lt; 10; ++i ) ...
for( i = 10; i &gt; 0; --i ) ...
int i = -1;
int i = +1;
data = *ptr;
address = &amp;obj;
int i = (int) floatNum;
int size = sizeof(floatNum);
right to left


3
-&gt;*
.*
Member pointer selector
Member pointer selector
ptr-&gt;*var = 24;
obj.*var = 24;
left to right


4
*
/
%
Multipli]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-06-12 20:59:00</pubDate>
		</item>
				<item>
		<title><![CDATA[C++构造函数调用顺序]]></title>
		<link>http://blog.pfan.cn/manbuyuduan/51349.html</link>
		<description><![CDATA[1、如果类里面有成员类，成员类的构造函数优先被调用；
2、创建派生类的对象，基类的构造函数函数优先被调用（也优先于派生类里的成员类）；
3、 基类构造函数如果有多个基类则构造函数的调用顺序是某类在类派生表中出现的
顺序而不是它们在成员初始化表中的顺序；

4、成员类对象构造函数如果有多个成员类对象则构造函数的调用顺序是对象在类中
被声明的顺序而不是它们出现在成员初始化表中的顺序；

5、派生类构造函数
作为一般规则派生类构造函数应该不能直接向一个基类数据成员赋值而是把值传递
给适当的基类构造函数否则两个类的实现变成紧耦合的（tightly coupled）将更加难于
正确地修改或扩展基类的实现。（基类设计者的责任是提供一组适当的基类构造函数）

本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/smilelance/archive/2007/03/30/1546849.aspx]]></description>
		<author><![CDATA[251791451]]></author>
		<pubDate>2010-06-10 19:24:00</pubDate>
		</item>
		</channel>
</rss>