关键字:VB、HCAK、指针、SafeArray、数组指针、效率、数组、排序
难度:中级或高级
要求:熟悉VB,了解基本的排序算法,会用VC更好。
引言:
上回说到,虽然指针的运用让我们的数组排序在性能上有了大大的提高,但是CopyMemory始终是我们心里一个挥之不去的阴影,因为它还是太慢。在C里我们用指针,从来都是来去自如,随心所欲,四两拨千斤;而在VB里,我们用指针却要瞻前顾后,哪怕一个字节都要用到CopyMemory乾坤大挪移,真累。今天我们就来看看,能不能让VB里的指针也能指哪儿打哪儿,学学VB指针的凌波微步。
各位看官,您把茶端好了。
一、帮VB做点COM家务事
本系列开张第一篇里,我就曾说过VB的成功有一半的功劳要记到COM开发小组身上,COM可是M$公司打的一手好牌,从OLE到COM+,COM是近十年来M$最成功技术之一,所以有必要再吹它几句。
COM组件对象模型就是VB的基础,Varinat、String、Current、Date这些数据类型都是COM的,我们用的CStr、CInt、CSng等Cxxx函数根本就是COM开发小组写的,甚至我们在VB里用的数学函数,COM里都有对应的VarxxxDiv、VarxxxAdd,VarxxxAbs。嘿嘿,VB开发小组非常聪明。我们也可以说COM的成功也有VB开发小组和天下无数VB程序员的功劳,Bill大叔英明地将COM和VB捆绑在一起了。
所以说,学VB而不需要了解COM,你是幸福的,你享受着VB带给你的轻松写意,她把那些琐碎的家务事都干了,但同时你又是不幸的,因为你从来都不曾了解你爱的VB,若有一天VB对你发了脾气,你甚至不知该如何去安慰她。所以,本系列文章将拿出几大篇来教大家如何帮VB做点COM方面的家务事,以备不时之需。
想一口气学会所有COM家务事,不容易,今天我们先拿数组来开个头,更多的技术我以后再一一道来。
二、COM自动化里的SafeArray
就象洗衣机、电饭堡、吹尘器,VB洗衣服、做饭、打扫卫生都会用到COM自动化。它包含了一切COM里通用的东西,所有的女人都能用COM自动化来干家务,无论是犀利的VC、温柔的VB、还是小巧的VBScript,她们都能用COM自动化,还能通过COM自动化闲话家常、交流感情。这是因为COM自动化提供了一种通用的数据结构和数据转换传递的方式。而VB的数据结构基本上就是COM自动化的数据结构,比如VB里的数组,在COM里叫做SafeArray。所以在VB里处理数组时我们要清楚的知道我们是在处理SafeArray,COM里的一种安全的数组。
准备下厨,来做一道数组指针排序的菜,在看主料SafeArray的真实结构这前,先让我们来了解一下C里的数组。
在C和C++里一个数组指针和数组第一个元素的指针是一回事,如对下:
可以看到结果a和&a[0]是相同的,这里的数组是才数据结构里真实意义上的数组,它们在内存里一个接着一个存放,我们通过第一个元素就能访问随后的元素,我们可以称这样的数组为"真数组"。但是它不安全,因为我们无法从这种真数组的指针上得知数组的维数、元素个数等非常重要的信息,所以也无法控制对这种数组的访问。我们可以在C里将一个二维数组当做一维数组来处理,我们还可以通过一个超过数组大小的索引去访问数组外的内存,但这些都是极不安全的,数组边界错误可以说是C里一个非常容易犯却不易发现的错误。
因此就有了COM里的SafeArray安全数组来解决这个问题,在VB里我们传递一个数组时,传递的实际上COM里的SafeAraay结构指构的指针,SafeAraay结构样子如下:
紧接在pvData这后的rgsabound是个真数组,所以不能在上面的结构里用VB数组来声明,记住,在VB里的数组都是SafeArray,在VB里没有声明真数组的方法。
不过这不是问题,因为上面SFArrayBOUND结构的真数组在整个SAFEARRAY结构的位置是不变的,总是在最后,我们可以用指针来访问它。SFArrayBOUND数组的元素个数有cDims个,每一个元素记录着一个数组维数的信息,下面看看它的样子:
还有一个东西没说清,那就是上面SAFEARRAY结构里的fFeatures,它是一组标志位来表示数组有那些待性,这些特性的标志并不需要仔细的了解,本文用不上这些,后面的文章用到它们时我会再来解释。
看了上面的东西,各位一定很头大,好在本文的还用不了这么多东西,看完本文你就知道其实SafeArray也不难理解。先来看看如下的声明:
这个数组做为SafeArray在内存里是什么样子呢?如图一: