??xml version="1.0" encoding="utf-8" standalone="yes"?>欧美精品国产综合久久,久久精品aⅴ无码中文字字幕不卡,久久精品综合一区二区三区http://www.shnenglu.com/weiyan/archive/2006/07/06/9500.htmlwillwillThu, 06 Jul 2006 10:42:00 GMThttp://www.shnenglu.com/weiyan/archive/2006/07/06/9500.htmlhttp://www.shnenglu.com/weiyan/comments/9500.htmlhttp://www.shnenglu.com/weiyan/archive/2006/07/06/9500.html#Feedback0http://www.shnenglu.com/weiyan/comments/commentRss/9500.htmlhttp://www.shnenglu.com/weiyan/services/trackbacks/9500.html C/C+语言struct深层探烦(ch)

出处QPConline

1. struct的巨大作?br />  面对一个h的大型C/C++E序Ӟ只看其对struct的用情冉|们就可以对其~写者的~程l验q行评估。因Z个大型的C/C++E序Q势必要涉及(qing)一?甚至大量)q行数据l合的结构体Q这些结构体可以原本意义属于一个整体的数据l合在一赗从某种E度上来_(d)?x)不会(x)用structQ怎样用struct是区别一个开发h员是否具备丰富开发经历的标志?/font>

  在网l协议、通信控制、嵌入式pȝ的C/C++~程中,我们l常要传送的不是单的字节(char型数l)(j)Q而是多种数据l合h的一个整体,其表现Ş式是一个结构体?/font>

  l验不的开发h员往往所有需要传送的内容依顺序保存在char型数l中Q通过指针偏移的方法传送网l报文等信息。这样做~程复杂Q易出错Q而且一旦控制方式及(qing)通信协议有所变化Q程序就要进行非常细致的修改?/font>

  一个有l验的开发者则灉|q用l构体,举一个例子,假设|络或控制协议中需要传送三U报文,其格式分别ؓ(f)packetA、packetB、packetCQ?/font>

struct structA
{
int a;
char b;
};

struct structB
{
char a;
short b;
};

struct structC
{
int a;
char b;
float c;
}
  优秀的程序设计者这栯计传送的报文Q?/font>

struct CommuPacket
{
int iPacketType;  //报文cd标志
union      //每次传送的是三U报文中的一U,使用union
{
 (tng) struct structA packetA;
 (tng) struct structB packetB;
 (tng) struct structC packetC;
}
};
  在进行报文传送时Q直接传送struct CommuPacket一个整体?/font>

  假设发送函数的原Ş如下Q?/font>

// pSendDataQ发送字节流的首地址QiLenQ要发送的长度
Send(char * pSendData, unsigned int (tng) iLen);
发送方可以直接q行如下调用发送struct CommuPacket的一个实例sendCommuPacketQ?br />Send( (char *)&sendCommuPacket , sizeof(CommuPacket) );
假设接收函数的原形如下:(x)
// pRecvDataQ发送字节流的首地址QiLenQ要接收的长?br />//q回|(x)实际接收到的字节?br />unsigned int Recv(char * pRecvData, unsigned int (tng) iLen)Q?br />  接收方可以直接进行如下调用将接收到的数据保存在struct CommuPacket的一个实例recvCommuPacket中:(x)

Recv( (char *)&recvCommuPacket , sizeof(CommuPacket) );
  接着判断报文cdq行相应处理Q?/font>

switch(recvCommuPacket. iPacketType)
{
 (tng) (tng) (tng) case PACKET_A:
 (tng) (tng) (tng) …?tng) (tng)?//AcL文处?br /> (tng) (tng) (tng) break;
 (tng) (tng) (tng) case PACKET_B:
 (tng) (tng) (tng) …  (tng) //BcL文处?br /> (tng) (tng) (tng) break;
 (tng) (tng) (tng) case PACKET_C:
 (tng) (tng) (tng) …?tng)?//CcL文处?br /> (tng) (tng) (tng) break;
}
  以上E序中最值得注意的是

Send( (char *)&sendCommuPacket , sizeof(CommuPacket) );
Recv( (char *)&recvCommuPacket , sizeof(CommuPacket) );
  中的强制cd转换Q?char *)&sendCommuPacket?char *)&recvCommuPacketQ先取地址Q再转化为char型指针,q样可以直接利用处理字节流的函数?/font>

  利用q种强制cd转化Q我们还可以方便E序的编写,例如要对sendCommuPacket所处内存初始化?Q可以这栯用标准库函数memset()Q?/font>

memset((char *)&sendCommuPacket,0, sizeof(CommuPacket));

2. struct的成员对?br />  Intel、微软等公司曄?gu)一道类似的面试题:(x)
1. #include <iostream.h>
2. #pragma pack(8)
3. struct example1
4. {
5. short a;
6. long b;
7. };
8. struct example2
9. {
10. char c;
11. example1 struct1;
12. short e; (tng) (tng) (tng)
13. };
14. #pragma pack()
15. int main(int argc, char* argv[])
16. {
17. example2 struct2;
18. cout << sizeof(example1) << endl;
19. cout << sizeof(example2) << endl;
20. cout << (unsigned int)(&struct2.struct1) - (unsigned int)(&struct2) << endl;
21. return 0;
22. }
  问程序的输入l果是什么?
  {案是:(x)
8
16
4
  不明白?q是不明白?下面一一道来Q?br />2.1 自然对界
  struct是一U复合数据类型,其构成元素既可以是基本数据类型(如int、long、float{)(j)的变量,也可以是一些复合数据类型(如array、struct、union{)(j)的数据单元。对于结构体Q编译器?x)自动进行成员变量的寚wQ以提高q算效率。缺省情况下Q编译器为结构体的每个成员按其自然对界(natural alignmentQ条件分配空间。各个成员按照它们被声明的顺序在内存?sh)顺序存储,W一个成员的地址和整个结构的地址相同?br />  自然对界(natural alignment)即默认对齐方式,是指按结构体的成员(sh)size最大的成员寚w?br />  例如Q?br />struct naturalalign
{
char a;
short b;
char c;
};
  在上q结构体中,size最大的是shortQ其长度?字节Q因而结构体中的char成员a、c都以2为单位对齐,sizeof(naturalalign)的结果等?Q?br />  如果改ؓ(f)Q?br />struct naturalalign
{
char a;
int b;
char c;
};
  其结果显然ؓ(f)12?/font>

2.2指定对界
  一般地Q可以通过下面的方法来改变~省的对界条Ӟ(x)
  · 使用伪指?pragma pack (n)Q编译器按照n个字节对齐;
  · 使用伪指?pragma pack ()Q取消自定义字节寚w方式?br />  注意Q如?pragma pack (n)中指定的n大于l构体中最大成员的sizeQ则其不起作用,l构体仍然按照size最大的成员q行对界?br />  例如Q?br />#pragma pack (n)
struct naturalalign
{
char a;
int b;
char c;
};
#pragma pack ()
  当n???6Ӟ其对齐方式均一Psizeof(naturalalign)的结果都{于12。而当n?Ӟ其发挥了(jin)作用Q得sizeof(naturalalign)的结果ؓ(f)8?br />  在VC++ 6.0~译器中Q我们可以指定其对界方式Q其操作方式Zơ选择projetct > setting > C/C++菜单Q在struct member alignment中指定你要的对界方式?br />  另外Q通过__attribute((aligned (n)))也可以让所作用的结构体成员寚w在n字节边界上,但是它较?yu)被使用Q因而不作详l讲解?/font>

2.3 面试题的解答
  x(chng)Q我们可以对Intel、微软的面试题进行全面的解答?br />  E序中第2?pragma pack (8)虽然指定?jin)对界?f)8Q但是由于struct example1中的成员最大size?Qlong变量size?Q,故struct example1仍然?字节对界Qstruct example1的size?Q即W?8行的输出l果Q?br />  struct example2中包含了(jin)struct example1Q其本n包含的简单数据成员的最大size?Qshort变量eQ,但是因ؓ(f)其包含了(jin)struct example1Q而struct example1中的最大成员size?Qstruct example2也应?对界Q?pragma pack (8)中指定的对界对struct example2也不起作用,?9行的输出l果?6Q?br />  ׃struct example2中的成员?sh)?为单位对界,故其char变量c后应补充3个空Q其后才是成员struct1的内存空_(d)20行的输出l果??br />



will 2006-07-06 18:42 发表评论
]]>
数据库中存取BMP囑փhttp://www.shnenglu.com/weiyan/archive/2006/07/06/9482.htmlwillwillThu, 06 Jul 2006 03:56:00 GMThttp://www.shnenglu.com/weiyan/archive/2006/07/06/9482.htmlhttp://www.shnenglu.com/weiyan/comments/9482.htmlhttp://www.shnenglu.com/weiyan/archive/2006/07/06/9482.html#Feedback1http://www.shnenglu.com/weiyan/comments/commentRss/9482.htmlhttp://www.shnenglu.com/weiyan/services/trackbacks/9482.html二进制大对象BLOB(Binary Large Object)
其存取的方式与普通数据有所区别。本文将介绍利用ADO在数据库中存取BLOB数据的具体实现过E,q给出实现图像存取显C的完整CZ工程?

二、前期准?

首先我们建立一张名为userinfo的表Q包含三个字D?id,username,old,photo,其中photo是一个可以存储二q制数据的字Dc(din)?

2.1 在SQL SERVER中我们可以在Query Analyzer中直接输入如下语句创建:(x)

CREATE TABLE [dbo].[userphoto] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[username] [varchar] (50) NULL ,
[old] [int] NULL ,
[photo] [image] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
其中photo我们定义为imagecd的字Dc(din)?

2.2 在ACCESS中创建的Ҏ(gu)如下Q?

建立一张新表包括id,username,old,photo四个字段Q然后打开表,选视图菜单中设计视图Q将id讄动编L(fng)递增长整型,username为文本,old为数字,photo为OLE对象?
在我们的CZ工程中已l包含了(jin)一个徏立好的ACCESS2000的库Q你可以直接拿来使用?

三、具体步?

3.1 BLOB数据的保?

BLOBcd的数据无法用普通的方式q行存储Q我们需要用AppendChunk函数QAppendChunk包含在Field对象中,原型如下Q?
HRESULT AppendChunk (const _variant_t & Data );
从函数原型中可以看到关键的问题是我们需把二q制数据赋值给VARIANTcd的变量,下面我们l出具体的代码ƈ作简单的分析:

///假设m_pBMPBuffer指针指向一块长度ؓ(f)m_nFileLen的二q制数据,q且已经成功打开?jin)记录集对象m_pRecordset///

char *pBuf = m_pBMPBuffer ;
VARIANT varBLOB;
SAFEARRAY *psa;
SAFEARRAYBOUND rgsabound[1];

m_pRecordset->AddNew(); ///d新记?
m_pRecordset->PutCollect("username",_variant_t("李")); ///为新记录填充username字段
m_pRecordset->PutCollect("old",_variant_t((long)28); ///填充old字段

if(pBuf){
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = m_nFileLen;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound); ///创徏SAFEARRAY对象

for (long i = 0; i < (long)m_nFileLen; i++)
SafeArrayPutElement (psa, &i, pBuf++); ///pBuf指向的二q制数据保存到SAFEARRAY对象psa?

varBLOB.vt = VT_ARRAY | VT_UI1;///varBLOB的类型设|ؓ(f)BYTEcd的数l?

varBLOB.parray = psa; ///为varBLOB变量赋?

m_pRecordset->GetFields()->GetItem("photo")->AppendChunk(varBLOB); ///加入BLOBcd的数?
}

m_pRecordset->Update(); ///保存我们的数据到库中

x(chng)我们的数据已l成功地保存C(jin)数据库中,接下来我们所要做的工作便是将该数据提取出?让我们l吧!

3.2 BLOB数据的读?

对应于保存数据时我们所使用的AppendChunk函数Q读取数据应该用GetChunk函数,GetChunk的原型如?
_variant_t GetChunk (long Length );
l出数据的长度后GetChunk返回包含数据的VARIANTcd变量,然后我们可以利用SafeArrayAccessData函数得到VARIANT变量中指向数据的char *cd的指?以方便我们的处理Q具体代码如下:(x)

long lDataSize = m_pRecordset->GetFields()->GetItem("photo")->ActualSize;
///得到数据的长?

if(lDataSize > 0)
{
_variant_t varBLOB;

varBLOB = m_pRecordset->GetFields()->GetItem("photo")->GetChunk(lDataSize);

if(varBLOB.vt == (VT_ARRAY | VT_UI1)) ///判断数据cd是否正确
{
   char *pBuf = NULL;
   SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
   ///得到指向数据的指?/*****在这里我们可以对pBuf中的数据q行处理*****/
   SafeArrayUnaccessData (varBLOB.parray);
   }

}

以上我们成功实现?jin)BLOB数据在数据库中的存取Qؓ(f)?jin)让大家有现成的例子可以参考,本文提供?jin)示例工E,在示例工E中我们在数据库中保存图像数据,q可以对q些囑փq行览、修改,该例子还涉及(qing)到如何用char *指向的BMP文g数据创徏BITMAP对象然后昄出来?br />



will 2006-07-06 11:56 发表评论
]]>
SAFEARRAY使用Ҏ(gu)CZhttp://www.shnenglu.com/weiyan/archive/2006/07/05/9452.htmlwillwillWed, 05 Jul 2006 12:09:00 GMThttp://www.shnenglu.com/weiyan/archive/2006/07/05/9452.htmlhttp://www.shnenglu.com/weiyan/comments/9452.htmlhttp://www.shnenglu.com/weiyan/archive/2006/07/05/9452.html#Feedback0http://www.shnenglu.com/weiyan/comments/commentRss/9452.htmlhttp://www.shnenglu.com/weiyan/services/trackbacks/9452.html l (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 创徏

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) long i = 0;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) VARIANT va = {0};

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) va . vt = VT_BSTR ;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) SAFEARRAYBOUND bounds [1] = {0};

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) bounds [0]. cElements = 5;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) SAFEARRAY * psa = SafeArrayCreate ( VT_VARIANT , 1, bounds );

 (tng)

l (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 存入元素

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) for ( i = 0; i < 5; i ++)

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) va . bstrVal = SysAllocString (L "test" );

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) SafeArrayPutElement ( psa , & i , & va );

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }

 (tng)

l (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 获取元素

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) for ( i = 0; i < 5; i ++)

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) {

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) va . bstrVal = SysAllocString (L "test" );

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) SafeArrayGetElement ( psa , & i , & va );

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) SysFreeString ( va . bstrVal );

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }

 (tng)

l (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 销?/span>

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) SafeArrayDestroy ( psa );

 (tng)

l (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 生成 VARIANT 变量

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) VARIANT vsa = {0};

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) vsa . vt = VT_ARRAY | VT_BSTR ;

 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) vsa . parray = psa ;



will 2006-07-05 20:09 发表评论
]]>
野指?/title><link>http://www.shnenglu.com/weiyan/archive/2006/07/05/9409.html</link><dc:creator>will</dc:creator><author>will</author><pubDate>Tue, 04 Jul 2006 16:32:00 GMT</pubDate><guid>http://www.shnenglu.com/weiyan/archive/2006/07/05/9409.html</guid><wfw:comment>http://www.shnenglu.com/weiyan/comments/9409.html</wfw:comment><comments>http://www.shnenglu.com/weiyan/archive/2006/07/05/9409.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/weiyan/comments/commentRss/9409.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/weiyan/services/trackbacks/9409.html</trackback:ping><description><![CDATA[ (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)野指针,也就是指向不可用内存区域的指针。通常对这U指针进行操作的话,会(x)使程序发生不可预知的错误。但是,我在文中要说的,是野指针的“安全”用方法以?qing)其内部的原?<br /><br /><p>首先误位看以下一D“危险”的C++代码Q?/p><p></p><table class="codetable" cellspacing="1" border="0"><tbody><tr><td><code><font color="blue">void</font> (tng)function( (tng)<font color="blue">void</font> (tng))<br />{<br /> (tng) (tng) (tng) (tng)<font color="blue">char</font>* (tng)str (tng)= (tng)<font color="blue">new</font> (tng)<font color="blue">char</font>[100];<br /> (tng) (tng) (tng) (tng)<font color="blue">delete</font>[] (tng)str;<br /> (tng) (tng) (tng) (tng)<font color="green">// (tng)Do (tng)something</font><br /> (tng) (tng) (tng) (tng)strcpy( (tng)str, (tng)"Dangerous!!" (tng));<br />}</code></td></tr></tbody></table><p>之所以说其危险,是因是一D完全合乎语法的代码Q编译的时候完得一炚w误也不会(x)有,然而当q行到strcpy一句的时候,问题׃(x)出现Q因为在q之前,str的空间已l被delete掉了(jin)Q所以strcpy当然不会(x)成功。对于这U类似的情况Q在林锐博士的书中有q介l,U其为“野指针”?/p><p>那么Q诸位有没有见过安全的“野指针”呢Q下面请看我的一DC++E序Q灵感来自CSDN上的一ơ讨论。在此,我只需要C++的“类”,C++的其余一概不需要,因此我没有用Q何的C++标准库,q输出都是用printf完成的?/p><p></p><table class="codetable" cellspacing="1" border="0"><tbody><tr><td><code><font color="blue">#include</font> (tng)<stdio.h><br /><br /><font color="blue">class</font> (tng)CTestClass<br />{<br /><font color="blue">public</font>:<br /> (tng) (tng) (tng) (tng)CTestClass( (tng)<font color="blue">void</font> (tng));<br /> (tng) (tng) (tng) (tng)<font color="blue">int</font> (tng)m_nInteger;<br /> (tng) (tng) (tng) (tng)<font color="blue">void</font> (tng)Function( (tng)<font color="blue">void</font> (tng));<br />};<br /><br />CTestClass::CTestClass( (tng)<font color="blue">void</font> (tng))<br />{<br /> (tng) (tng) (tng) (tng)m_nInteger (tng)= (tng)0;<br />}<br /><br /><font color="blue">void</font> (tng)CTestClass::Function( (tng)<font color="blue">void</font> (tng))<br />{<br /> (tng) (tng) (tng) (tng)printf( (tng)"This (tng)is (tng)a (tng)test (tng)function.\n" (tng));<br />}<br /><br /><font color="blue">void</font> (tng)main( (tng)<font color="blue">void</font> (tng))<br />{<br /> (tng) (tng) (tng) (tng)CTestClass* (tng)p (tng)= (tng)<font color="blue">new</font> (tng)CTestClass;<br /> (tng) (tng) (tng) (tng)<font color="blue">delete</font> (tng)p;<br /> (tng) (tng) (tng) (tng)p->Function();<br />}</code></td></tr></tbody></table><p>OKQ程序到此ؓ(f)止,怽可以~译q行一下看看结果如何。你也许?x)惊异地发现Q没有Q何的出错信息Q屏q上竟然乖乖地出C(jin)q么一行字W串Q?/p><p>This is a test function.</p><p>奇怪吗Q不要急,q有更奇怪的呢,你可以把dC加上一句更不可理喻的:(x)</p><p></p><table class="codetable" cellspacing="1" border="0"><tbody><tr><td><code>((CTestClass*)NULL)->Function();</code></td></tr></tbody></table><p>q仍然没有问题!Q?/p><p>我这q有呢,哈哈。现在你在主函数中这么写Q倘说上一句不可理喻,那么以下可以叫做无法无天?jin)?x)</p><p></p><table class="codetable" cellspacing="1" border="0"><tbody><tr><td><code><font color="blue">int</font> (tng)i (tng)= (tng)888;<br />CTestClass* (tng)p2 (tng)= (tng)(CTestClass*)&i;<br />p2->Function();</code></td></tr></tbody></table><p>你看C(jin)什么?是的Q“This is a test function.”如U而至Q没有Q何的错误?/p><p>你也许要问ؓ(f)什么,但是在我解答你之前,请你在主函数中加入如下代码:(x)</p><p></p><table class="codetable" cellspacing="1" border="0"><tbody><tr><td><code>printf( (tng)"%d, (tng)%d", (tng)<font color="blue">sizeof</font>( (tng)CTestClass (tng)), (tng)<font color="blue">sizeof</font>( (tng)<font color="blue">int</font> (tng)) (tng));</code></td></tr></tbody></table><p>q时你就?x)看到真怺(jin)Q输出结果是——得到的两个十进制数相等。对Q由sizeof得到的CTestClass的大其实就是它的成员m_nInteger的大。亦x(chng)_(d)对于CTestClass的一个实例化的对象(设ؓ(f)aQ而言Q只有a.m_nInteger是属于aq个对象的,而a.Function()却是属于CTestClassq个cȝ。所以以上看似危险的操作其实都是可行且无误的?/p><p>现在你明白ؓ(f)什么我的“野指针”是安全的了(jin)Q那么以下我所列出的,是在什么情况下Q我的“野指针”不安全Q?/p><ol><li>在成员函数Function中对成员变量m_nIntegerq行操作Q? </li><li>成员函数Function声明函数QvirtualQ?</li></ol><p>以上的两U情况,目的是野指针用属于自q东西D不安全,比如W一U情况中操作本n的m_nIntegerQ第二种情况中变?sh)函数的Function成ؓ(f)?jin)属于对象的函数Q这一点可以从sizeof看出来)(j)?/p><p>其实Q安全的野指针在实际的程序设计中是几乎毫无用处的。我写这一文章,意图q不是像孔乙׃样去琢磨回字有几U写法,而是想通过q个例子向怽写明白C++的对象实例化本质Q希望大家不但要明白what和howQ更要明白why。李马二雉三年二月二十日作于自宅?/p><p><br /><b>关于成员函数CTestClass::Function的补充说?/b><br /><br /></p><p>q个函数是一个普通的成员函数Q它在编译器的处理下Q会(x)成ؓ(f)cM如下的代码:(x)</p><p></p><table class="codetable" cellspacing="1" border="0"><tbody><tr><td><code><font color="blue">void</font> (tng)Function( (tng)<font color="blue">const</font> (tng)CTestClass (tng)* (tng)<font color="blue">this</font> (tng)) (tng)<font color="green">// (tng)?/font><br />{<br /> (tng) (tng) (tng) (tng)printf("This (tng)is (tng)a (tng)test (tng)function.\n");<br />}</code></td></tr></tbody></table><p>那么p->Function();一句将被编译器解释为:(x)</p><p></p><table class="codetable" cellspacing="1" border="0"><tbody><tr><td><code>Function( p ); </code></td></tr></tbody></table><p>q就是说Q普通的成员函数必须l由一个对象来调用Q经由this指针ȀzZQ。那么由上例的delete之后Qp指针会(x)指向一个无效的地址Q然而p本n是一个有效的变量Q因此编译能够通过。ƈ且在~译通过之后Q由于CTestClass::Function的函C内ƈ未对q个传入的this指针q行M的操作,所以在q里Q“野指针”便成了(jin)一个看似安全的东西?/p><p>然而若q样改写C(j)TestClass::FunctionQ?/p><p></p><table class="codetable" cellspacing="1" border="0"><tbody><tr><td><code><font color="blue">void</font> (tng)CTestClass::Function( (tng)<font color="blue">void</font> (tng))<br />{<br /> (tng) (tng) (tng) (tng)m_nInteger (tng)= (tng)0;<br />}</code></td></tr></tbody></table><p>那么它将?x)被~译器解释ؓ(f)Q?/p><p></p><table class="codetable" cellspacing="1" border="0"><tbody><tr><td><code><font color="blue">void</font> (tng)Function( (tng)<font color="blue">const</font> (tng)CTestClass (tng)* (tng)<font color="blue">this</font> (tng))<br />{<br /> (tng) (tng) (tng) (tng)<font color="blue">this</font>->m_nInteger (tng)= (tng)0;<br />}</code></td></tr></tbody></table><p>你看C(jin)Q在p->Function();的时候,pȝ会(x)试在传入的q个无效地址中寻找m_nInteger成员q将其赋gؓ(f)0Q剩下的我不用说?jin)——非法操作出C(jin)?/p><p>至于virtual虚函敎ͼ如果在类定义之中CTestClass声明函数Q?/p><p></p><table class="codetable" cellspacing="1" border="0"><tbody><tr><td><code><font color="blue">class</font> (tng)CTestClass<br />{<br /><font color="blue">public</font>:<br /> (tng) (tng) (tng) (tng)<font color="green">// (tng)...</font><br /> (tng) (tng) (tng) (tng)<font color="blue">virtual</font> (tng)<font color="blue">void</font> (tng)Function( (tng)<font color="blue">void</font> (tng));<br />};</code></td></tr></tbody></table><p>那么C++在构建CTestClasscȝ对象模型Ӟ会(x)Z分配一个虚函数表vptrQ可以从sizeof看出来)(j)。vptr是一个指针,它指向一个函数指针的数组Q数l中的成员即是在CTestClass中声明的所有虚函数。在调用虚函数的时候,必须l由q个vptrQ这也就是ؓ(f)什么虚函数较之普通成员函数要消耗一些成本的~故。以本例而言Qp->Function();一句将被编译器解释为:(x)</p><p></p><table class="codetable" cellspacing="1" border="0"><tbody><tr><td><code>(*p->vptr[1])( (tng)p (tng)); (tng)<font color="green">// (tng)调用vptr表中索引号ؓ(f)1的函敎ͼ即FunctionQ③</font></code></td></tr></tbody></table><p>上面的代码已l说明了(jin)Q如果p指向一个无效的地址Q那么必然会(x)有非法操作?/p><p>备注Q?/p><p>①关于函数的命名Q我采用?jin)原名而没有变化。事实上~译器ؓ(f)?jin)避免函数重载造成的重名情况,?x)对函数的名字进行处理,使之成?f)独一无二的名U?br />②将成员函数声明为staticQ可以成员函数不经由this指针便可调用?br />③vptr表中Q烦(ch)引号0为类的type_info?/p><br /><br /><img src ="http://www.shnenglu.com/weiyan/aggbug/9409.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/weiyan/" target="_blank">will</a> 2006-07-05 00:32 <a href="http://www.shnenglu.com/weiyan/archive/2006/07/05/9409.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VISUAL C++软g开发中几个常用功能http://www.shnenglu.com/weiyan/archive/2006/07/05/9408.htmlwillwillTue, 04 Jul 2006 16:26:00 GMThttp://www.shnenglu.com/weiyan/archive/2006/07/05/9408.htmlhttp://www.shnenglu.com/weiyan/comments/9408.htmlhttp://www.shnenglu.com/weiyan/archive/2006/07/05/9408.html#Feedback0http://www.shnenglu.com/weiyan/comments/commentRss/9408.htmlhttp://www.shnenglu.com/weiyan/services/trackbacks/9408.html一、设|程序自动运行。?tng)?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng)很多监控软g要求软g能够在系l重新启动后不用用户ȝd标启动项目,而是直接能够启动q行Q方法是写注册表Software\\Microsoft\\Windows\\CurrentVersion\\Run。参考程序可以见下:(x)(查找E序目录的执行文Ӟ存在则进行添加注册表操作) (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) HKEY RegKey; (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) CString sPath; (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) GetModuleFileName(NULL,sPath.GetBufferSetLength(MAX_PATH+1),MAX_PATH); (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) sPath.ReleaseBuffer(); (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) int nPos; (tng)
 (tng) (tng) (tng) nPos=sPath.ReverseFind(’\\?; (tng)
 (tng) (tng) (tng) sPath=sPath.Left(nPos); (tng)
 (tng) (tng) (tng) CString lpszFile=sPath+"\\****.exe";//q里加上你要查找的执行文件名UW?
 (tng) (tng) (tng) CFileFind fFind; (tng)
 (tng) (tng) (tng) BOOL bSuccess; (tng)
 (tng) (tng) (tng) bSuccess=fFind.FindFile(lpszFile); (tng)
 (tng) (tng) (tng) fFind.Close(); (tng)
 (tng) (tng) (tng) if(bSuccess) (tng)
 (tng) (tng) (tng) { (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) CString fullName; (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) fullName=lpszFile; (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) RegKey=NULL; (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&RegKey); (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) RegSetValueEx(RegKey,"*****",0,REG_SZ,(const unsigned char*)(LPCTSTR)fullName,fullName.GetLength());//q里加上你需要在注册表中注册的内容?
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) this->UpdateData(FALSE); (tng)
 (tng) (tng) (tng) } (tng)
 (tng) (tng) (tng) else (tng)
 (tng) (tng) (tng) { (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) theApp.SetMainSkin(); (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) ::AfxMessageBox("没找到执行程序,自动q行p|"); (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) exit(0); (tng)
 (tng) (tng) (tng) } (tng)

二、自动配|数据源 (tng)
 (tng) (tng) (tng) 很多的程序都要用到数据库l合的操作,q里举例ACCESSQ因为ACCESS在中型VCpȝ开发中是最常用到的Q如果程序的ULQ如果对于很初的用h_(d)你还需要他到配|面板中q行数据源配|的话,那就有点说不q去?jin)。?
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) #include <odbcinst.h> (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) //配置数据源,数据库在应用E序目录?q里比如数据库文件名?**.mdbQ程序运行时候可以将数据库文件拷贝到E序目录下面。?
 (tng) (tng) (tng) CString sPath; (tng)
 (tng) (tng) (tng) GetModuleFileName(NULL,sPath.GetBufferSetLength (MAX_PATH+1),MAX_PATH); (tng)
 (tng) (tng) (tng) sPath.ReleaseBuffer(); (tng)
 (tng) (tng) (tng) int nPos; (tng)
 (tng) (tng) (tng) nPos=sPath.ReverseFind(’\\?; (tng)
 (tng) (tng) (tng) sPath=sPath.Left(nPos); (tng)
 (tng) (tng) (tng) CString lpszFileName = sPath + "\\***.mdb";//q里修改成你的数据库文g名称 (tng)
 (tng) (tng) (tng) CFileFind (tng) fFind; (tng)
 (tng) (tng) (tng) if(!fFind.FindFile(lpszFileName)) (tng)
 (tng) (tng) (tng) { (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) ::AfxMessageBox("没有扑ֈ数据?); (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) exit(0); (tng)
 (tng) (tng) (tng) } (tng) (tng)
 (tng) (tng) (tng) CString szDesc; (tng)
 (tng) (tng) (tng) szDesc.Format( "DSN=****;Description=****;DESCRIPTION=The DataBase For ***;FIL=MicrosoftAccess;DEFAULTDIR=%s;DBQ=%s;" ,sPath,lpszFileName);//q里***号可以添加成你的描述 (tng)

 (tng) (tng) (tng) //d数据源?
 (tng) (tng) (tng) if(!::SQLConfigDataSource(NULL,ODBC_ADD_DSN, "Microsoft Access Driver (*.mdb)",(LPCSTR)szDesc)) (tng)
 (tng) (tng) (tng) { (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) ::AfxMessageBox("32位ODBC数据源配|错?"); (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) exit(0); (tng)
 (tng) (tng) (tng) } (tng)

三、设|显C模式:(x) (tng)
 (tng) (tng) (tng) 很多的程序的UL的运行环境是改变的。有可能你的原来开发环境是1024X768Q但是到?jin)那些显C器大于17的时候(分L率超q你的开发时的分辨率Ӟ(j)Q程序的昄可能׃好看?jin)。?
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) DEVMODE lpDevMode; (tng)
 (tng) (tng) (tng) lpDevMode.dmPelsHeight=768;//Y方向象素点?
 (tng) (tng) (tng) lpDevMode.dmPelsWidth=1024;//X方向象素点?
 (tng) (tng) (tng) lpDevMode.dmDisplayFrequency=85;//屏幕h率?
 (tng) (tng) (tng) lpDevMode.dmFields=DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY; (tng)
 (tng) (tng) (tng) ChangeDisplaySettings(&lpDevMode,0); (tng)

四、在你的E序中间加蝲其他应用E序Q?
 (tng) (tng) (tng) 你的E序除了(jin)调用到各个模块进行协同工作外QDLLQ,q有可能调用不是同一个开发环境下的应用程序,比如VC环境下调用DELPHIQVB开发的执行E序Q你可以用C面的Ҏ(gu)Q将调用的应用程序拷贝程序目录中Q:(x) (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) CString sPath; (tng)
 (tng) (tng) (tng) GetModuleFileName(NULL,sPath.GetBufferSetLength (MAX_PATH+1),MAX_PATH); (tng)
 (tng) (tng) (tng) sPath.ReleaseBuffer(); (tng)
 (tng) (tng) (tng) int nPos; (tng)
 (tng) (tng) (tng) nPos=sPath.ReverseFind(’\\?; (tng)
 (tng) (tng) (tng) sPath=sPath.Left(nPos); (tng)
 (tng) (tng) (tng) CString lpszFileName = sPath + "\\***.exe";//q里修改成你的调用应用程序的文g名称 (tng)
 (tng) (tng) (tng) CFileFind (tng) fFind; (tng)
 (tng) (tng) (tng) if(!fFind.FindFile(lpszFileName)) (tng)
 (tng) (tng) (tng) { (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) ::AfxMessageBox("没有扑ֈ调用的应用程序!"); (tng) (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) return FALSE; (tng)
 (tng) (tng) (tng) } (tng)
 (tng) (tng) (tng) else (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) ShellExecute(NULL,NULL,_T("***.exe"),NULL,sPath,NULL); (tng) (tng)

五、结束进E:(x) (tng)
 (tng) (tng) (tng) 在你的程序中l束别的E序q程Q采用的Ҏ(gu)是进行进E列举,然后采用查找的方法进行:(x) (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) #include "TLHELP32.H" (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) DWORD ProcessID[50]; (tng)
 (tng) (tng) (tng) CString kkk[50]; (tng)
 (tng) (tng) (tng) HANDLE SnapShot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); (tng) (tng)
 (tng) (tng) (tng) PROCESSENTRY32* info=new PROCESSENTRY32; (tng)
 (tng) (tng) (tng) PROCESSENTRY32 ProcessInfo;//声明q程信息变量 (tng)
 (tng) (tng) (tng) ProcessInfo.dwSize=sizeof(ProcessInfo);//讄ProcessInfo的大?
 (tng) (tng) (tng) //q回pȝ中第一个进E的信息 (tng)
 (tng) (tng) (tng) BOOL Status=Process32First(SnapShot,&ProcessInfo); (tng)
 (tng) (tng) (tng) int m_nProcess=0; (tng) (tng)
 (tng) (tng) (tng) while(Status) (tng)
 (tng) (tng) (tng) { (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) CString s,str1,str2; (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) s.Format("%d",ProcessInfo.cntThreads); (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) str1.Format("%s",ProcessInfo.szExeFile); (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) str1=ProcessInfo.szExeFile; (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) kkk[m_nProcess]=ProcessInfo.szExeFile; (tng) (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) ProcessID[m_nProcess]=ProcessInfo.th32ProcessID; (tng) (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) if(str1=="***.exe")//***.exe是你要l束的进E的名称 (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) { (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) HANDLE ProcessHandle; (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) ProcessHandle=OpenProcess (PROCESS_ALL_ACCESS,FALSE,ProcessID[m_nProcess]); (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) TerminateProcess(ProcessHandle,0); (tng) (tng) (tng) (tng) (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) } (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) Status=Process32Next(SnapShot,&ProcessInfo); (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) m_nProcess++; (tng)
 (tng) (tng) (tng) } (tng)



will 2006-07-05 00:26 发表评论
]]>
在VC中添加响应自定义的消息的代码步骤http://www.shnenglu.com/weiyan/archive/2006/07/02/9288.htmlwillwillSun, 02 Jul 2006 10:00:00 GMThttp://www.shnenglu.com/weiyan/archive/2006/07/02/9288.htmlhttp://www.shnenglu.com/weiyan/comments/9288.htmlhttp://www.shnenglu.com/weiyan/archive/2006/07/02/9288.html#Feedback0http://www.shnenglu.com/weiyan/comments/commentRss/9288.htmlhttp://www.shnenglu.com/weiyan/services/trackbacks/9288.html1. 首先定义一个消息代?/p>

#define WM_DEBUG (tng) (tng) (tng) (tng) WM_USER + 1999

2. 在窗口头文g中添?/p>

class CStreamServerDlg : public CDialog
{
 (tng)// Generated message map functions
 (tng)//{{AFX_MSG(CStreamServerDlg)
...
 (tng)//}}AFX_MSG
 (tng)afx_msg void OnDebug(WPARAM wParam, LPARAM lParam); (tng)
...
}

3. 在窗口的cpp文g中添?/p>


BEGIN_MESSAGE_MAP(CStreamServerDlg, CDialog)
...
 (tng)ON_MESSAGE(WM_DEBUG, OnDebug)
END_MESSAGE_MAP()

LRESULT (tng) CStreamServerDlg::OnDebug(WPARAM wParam, LPARAM lParam)
{
}

4. 其他地方可以发送消?/p>

pWnd->PostMessage(WM_DEBUG, (tng) (WPARAM)p, 0) )


说明Q?br />
#define ON_MESSAGE(message, memberFxn)
{ message, 0, 0, 0, AfxSig_lwl,
(AFX_PMSG)(AFX_PMSGW)(LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM))&memberFxn },




will 2006-07-02 18:00 发表评论
]]>
þù| ɫʹþۺ| þѾƷav| ޾ƷþþþþͼƬ| þۺϹapp | ŷɫۺϾþþþþ| ޹СƵƷþþ| һɫþ88ۺ޾Ʒ| 99þþƷһ| þ˿ྫƷĻ| þùƷ99| þԭav| þþ㽶ۺϼձ| ۺϾþۺϼþ| þֹۺ޾Ʒ| ޹Ʒþþþ | ѾƷþ| þþĻ| AVպƷþþþ| þþƷĻ23ҳ| vĻþ | 99þþƷëƬ| 91ƷۺϾþþƷ| þþƷAV㽶| Ʒþþþþ | ޾ƷۺϾþ| ޹Ʒþþ| ˾Ʒþһ| һþƵ| þۺ³³| ɫ͵͵88ŷƷþþ| þ97þ97Ʒӿ| ˾þþƷ鶹һ| 㽶þҹɫƷС˵| ھƷþþþӰԺ | þþþþþþòҰ߳| þ¶ݺɫ| ɫþþþþþС˵| þþþþþƷѿSSS| þþ뾫Ʒպý | þ˽˹Ʒ|