VB/VBA字符串

VB/VBA字符串

 字符串历来就是编程界的麻烦

前言

字符串在人机交互中,举足轻重,是站人这一边的,其作用甚至比变量和函数更突出。变量详见《变量,还有这些秘密》,函数详见《 VB/VBA中的函数,用了那么久,其实是这样的》。试想没有字符串的中间协助,人根本就不可能理解计算机,更别提与之交互了。

字符串在任何一门编程语言中,都是最让人头疼的。因为字符串大小不定,会涉及到复杂的内存管理,很难像整数(详见《VB的整数,你真的了解?》)那样简单高效。更别提这个世界上除了简单的26个英文字符外,还有其他上百种字符呈现形式,更有从右向左的阿拉伯文。所以,在DOPE中直接丢掉了字符串类型(所以别再苛责VB/VBA了,为了广大非IT科班,可谓已操碎了心),可见字符串处理起来的确麻烦。当然啦,没有字符串的DOPE,自然一无是处。但也无妨,这个教学实验后的BASIC,还是老老实实地捡回来了。

甚至也可以这么说,一门编程语言受欢迎与否,往往在很大程度上,取决于对字符串处理的封装。但终究然并卵,因为字符串的复杂始终在那里,不增不减。封装得再好,也只会便宜源码的书写。

尽管在VB/VBA中,使用了ByRef这样的神器(详情可参阅《为何ByRef在VB/VBA中就能传递指针呢?》),但仍避免不了字符串是VB/VBA成品慢的主要成因。本文就给大家分享铺垫已久的字符串相关内容吧。

一、VB/VBA字符串的真实身份

早先在《早判了,VB已死,但我说话了么?》中就向大家伙说了,VB/VBA是基于COM的语言,因此凡事问COM。而就数据类型而言,COM就该找Variant。Variant还记得么?在《VB的任性,从Variant开始》中介绍Variant的时候,其首成员就是数据类型,这些类型其实就是COM支持的类型,自然囊括了VB/VBA的所有类型。

其中VB/VBA的String类型,就是COM中的BSTR类型。将BSTR的定义翻译成VB/VBA,就是下面的样子:

VB/VBA字符串

 没看错,VB/VBA的String就长这样

可见VB/VBA的String,既有前缀,也有结尾,因此也被称为安全字符串。这与C中的字符串有很大的不同,C依赖Null结束符来判断是否越界,在指针的加持下非常容易越界访问。VB/VBA中的String,无论如何使用都不存在越界的问题。

二、字符串的家常事

1、字符串变量的声明

在VB/VBA中,往往大手一挥,敲下"Dim Str As String",就完成了,后面就可以用Str进行各种字符串的操作了。想想此时,VB/VBA都为我们做了些什么呢?简单使用VarPtr函数获取Str的指针,并借助CopyMemory取数据,来观察下吧,如下图:

VB/VBA字符串

 声明不定长字符串变量,实际仅占位

在以往的文章中,我们知道String类型其实是一个指针的指针,也即在字符串变量指针指向的内存里存储的是字符串数据指针。通过上述验证代码,可以发现声明1个非定长字符串变量时,仅仅是分配了1个指针所需内存,因此String变量的尺寸其实只有4Bytes。该指针未指向任何位置,也即此时的字符串变量其实是一个空指针。其实想想也是,你什么数据都没给,天知道要给第二个成员多大地儿。

2、字符串变量的赋值

StrPtr函数可以获取字符串数据指针,也即第二个成员的首地址。这个数据指针就存放在声明字符串变量时,分配的内存里,也就是说字符串变量的值是一个指针。这和我们通常动态监视的字符串变量,是不一样的。因为在IDE环境下,实际上给我们看的字符串,是已经转换后的。不信,可以将前面的测试代码稍作调整,就更清楚了,如下:

VB/VBA字符串

 字符串就是指针的指针

这段测试代码,添加了一条赋值语句。字符串变量在被赋值之后,字符串变量里存放的确实是字符串数据指针。这说明字符串通过赋值,完成了所需内存分配、数据复制以及数据指针的填充。事实上,的确如此,背后都是OleAuto32.dll里的那帮API在管理VB/VBA的字符串,有兴趣的朋友可以查阅相关资料。所幸在VB/VBA中无需考虑这些细节,就像拖放窗口一样,都封装好了。

VB/VBA字符串

 字符串变量是铁打的营盘,数据才是流水的兵

当重新给一个字符串变量赋值,会发生什么?用上述测试代码,就不难发现,重新赋值时数据指针发生了变化。事实上,背后会调用一系列API函数,申请分配新的内存,拷贝数据,然后释放掉原占用内存。

如果在C中,上述行为都得自己实现,但在VB/VBA中你什么都不用做。是不是觉得VB/VBA中的字符串颇有几分好感呢?且慢,这个老好人,总有让你觉得讨厌的时候。

三、字符串的麻烦事

1、高频低效

如果低频使用字符串变量,无关紧要。但是要高频使用,就麻烦了。因为VB/VBA没有优化高频场景。如此,会有大量的申请、数据拷贝和释放内存的代码被执行。想想大量执行"Str=Str & ?"的场景吧。

2、U/A自动转换

由于历史的原因,计算机在当初设计时,并未考虑非英语环境。这跟当年的千年虫问题一样,谁也没预料到计算机对人类有如此深厚的影响。但随着从英语国家向非英语国家发展,组成字符串的字符集出问题了。为了解决这一问题,不得不对字符集编码进行扩展,也即后来的Unicode。所以Win98后,微软抛弃了ANSI内核,而推出了全新的Unicode内核系统。

但为了兼容,VB/VBA在人机交互层面使用Unicode,而在代码层默认为ANSI。这在当时是具有前瞻性的,但随着Win9.x的全面消失,这一点就画蛇添足了。

3、假身份

从前面的结构不难发现,所谓字符串其实最核心的是个数组。但在VB/VBA中又没有真正的数组。

别慌下结论,字符串的故事源远流长。欢迎关注BtOfficer,带你玩一手顺滑的字符串。

  • 1
    点赞
  • 5
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

BtOfficer

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值