中字符串作参数传递的本质论牛

来源:扬中家居装修网 发布时间:2021-09-06

问题背景: 前几天在论坛中看到有一个提问的问题,内容是:

模块中的代码:

Option Explicit

Public Declare Function GetComputerName Lib \"kernel32\" Alias \"GetComputerNameA\" (ByVal lpBuffer As String, nSize As Long) As Long’声明获取计算机名的API函数

窗体中的代码:

Option Explicit

Private Sub Command1_Click()

Dim computername As String

Dim length As Long

length = 255

str = String(length, 0)

GetComputerName computername, length

int computername,

End Sub

以上程序的功能是获取计算机名。

大家看上面API中的lpBuffer这个形参被声明为Byval(传值)方式。那么在调用之后API函数却可以通过computername这个实参传回计算机名,那么形参不是被声明为传值调用方式吗?即形参值的改变不会影响到实参,可是这里调用API函数后却可以通过实参返回值,这是到底是什么原因呢?

相关知识:

大家都知道,VB中没有C语言中的指针类型。C语言中只有字符数据类型,即字符变量只能存放一个字符,而没有字符串变量,它操作字符串是通过字符型指针来实现的,它的特点是通过’\\0’来判断字符是否结束的。而VB有字符串变量类型,一种变长,一种是定长的。并且VB字符串具体自动保护功能。

例如:dim str as string * 6

str=”abcdef”

int str’那么将显示abcdef

str=”abcdefghijklmnopq”

int str’还显示abcdef,说明它具有保护功能,将超过的字符截掉

在VB中使用的字符是一种叫做BSTR格式的字符串指针类型。

字符个数描述符由VB来使用,BSTR指针直接指向第一个字符。

因为大多数API函数是用C或C++来编写的,在C/C++(API)中使用叫做LPSTR类型的指针。

VB中字符串变量在内存中的存储状态图:

从上图可知:字符串变量X的地址与实际字符串的地址不同,也就是说字符X变量中实际上是存放的字符串的首地址这一点是和C/C++相同的。其实图中descriptor这个描述符就是C中的字符串指针地址。当BSTR指针在忽略字符个数描述前缀的情况下是与LPSTR指针是相同的,在调用API时可以将BSTR以传值方式传递给API。

[下一页]

采用传值方式传递时实际上传递的是实参中所存放的字符串的首地址,当调用过API后,可以通过它来返回数据,API修改传送给它的那个地址所指向的字符串数据,而没有修改实参字符变量内的内容,所以可以返回数据。即并没有与高级语言中所规定的传值方式调用方式的形参改变不影响实参的规则相冲突。

实例:

模块中的代码:

Option Explicit

Public Declare Function GetComputerName Lib \"kernel32\" Alias \"GetComputerNameA\" (ByVal lpBuffer As String, nSize As Long) As Long

窗体中的代码:

Option Explicit

爆米花指数13%。天朝领跑的肯定就是《何以笙箫默》了。1何以笙箫默拍电视剧也就算了 Private Sub Command1_Click()

Dim str As String

Dim str1 as String

Dim length As Long

length = 255

str = String(length, 0)

str1=str

int VarPtr(str),” “,varptr(str1)

int StrPtr(str),” ”,strptr(str1)

int

GetComputerName str, length

int str

int VarPtr(str)

int StrPtr(str), Len(str), length

End Sub

在立即窗口中可以看到运行结果。字符串变量的地址与字符串的地址不同。

还可以看到字符串变量str与str1的地址不同,而且字符串地址也不同,这说明在进行赋值操作,并不是将字符的首地址赋给str1而是在内存中另开一空间用来存放字符串。而在C语言内则可以使多个字符型指针变量指向同一个字符串的首地址。

当将API中的ByVal lpBuffer As String传值方式改为:ByRef lpBuffer As String传址方式时,运行程序中出错,VB编程环境将崩溃。

出错图:

因为传址时将变量本身的地址传给了API,并没有将字符串的首地址传给API,所以API在修改数据时造成访问错误。

总结:

不能用传址方式来调用API,如果用传址方式的话那么传递的是指向指针的指针,API将不能返回数据,并且造成访问数据出错,所以需要用ByVal传递字符串指针。

西安医院白癜风哪好
新标门窗
信阳专业治白癜风医院
相关推荐
杜高犬晚上叫怎么办位置

杜高犬晚上叫怎么办杜高犬晚上叫怎么办 07:59:59出处:络点击:3119 导读: 杜高犬的幼犬小时候也...[详细]

家居装修2022.06.12
杜高犬怎么样杜高犬介绍位置

杜高犬怎么样?杜高犬介绍杜高犬怎么样?杜高犬介绍 12:02:06by 呦呦​杜高犬对喜欢斗犬的人有很大的吸引力,它们身形高大,肩高在厘...[详细]

家居装修2022.06.12
松狮咳嗽怎么办位置

松狮咳嗽怎么办松狮咳嗽怎么办 13:53:41出处:络点击:4691 导读: 咳嗽是是生物对自身的一种防...[详细]

家居装修2022.06.12
松狮吃什么长得胖图位置

松狮吃什么长得胖?【图】松狮吃什么长得胖?【图】 15:45:40出处:络点击:1356 导读: ​现在的...[详细]

家居装修2022.06.12
杜高犬太凶了要怎么办位置

杜高犬太凶了要怎么办杜高犬太凶了要怎么办 10:13:48出处:络点击:675 导读: 宠物狗往往都是非...[详细]

家居装修2022.06.12
杜高犬咬人怎么办位置

杜高犬咬人怎么办杜高犬咬人怎么办 07:57:52出处:络点击:6422 导读: 前段时间有杜高犬咬死人的...[详细]

家居装修2022.06.12
4