【发布时间】:2019-02-09 12:24:58
【问题描述】:
在使用ParamArray 并通过它传递数组元素时,我注意到VBA 中有一个奇怪的地方。在某些情况下,到达函数的不是数组元素的值,而是 var 指针。 (Excel 2016,32 位)。
经过一番折腾后,我发现将函数定义为变体数组 - 结合参数列表和 ParamArray - 似乎是意外行为的起源,但我看不出任何可行的原因为什么会这样。
在以下情况下行为恢复正常:
1) 变量 r 在函数声明中被删除
2) b 声明为 Dim b()
3) 函数返回Variant,而不是Variant()
我很欣赏这是一个相当深奥的问题,而且它似乎可以通过各种方式进行控制,但是否有解释这种行为的解释?
Sub Variantarraybug()
Dim b: b = [{1, 2, 3}]
Debug.Print farray1(2, b(1))(0)
Debug.Print Application.WorksheetFunction.Sum(farray1(2, b(1)))
Debug.Print Join(farray1(2, b(1)), " ")
Debug.Print farray2(2, b(1))(0)
Debug.Print Application.WorksheetFunction.Sum(farray2(2, b(1)))
Debug.Print Join(farray2(2, b(1)), " ")
Debug.Print VarPtr(b(1)), VarPtr(b(2))
End Sub
Function farray1(r, ParamArray plop()) As Variant
farray1 = Array(plop(0), 3)
End Function
Function farray2(r, ParamArray plop()) As Variant()
farray2 = Array(plop(0), 5)
End Function
调试窗口中的结果:
1
4
1 3
1
6
358808368 5
358808368 358808384
注1:我的理解是VarPtr函数返回的是那个变量所需内存的起始地址的内存位置。这里仅用于证明farray2 函数看到的意外数字(358808368)实际上是该元素的地址。
注意 2: 这与您如何生成数组(例如 b=array(1,2,3)、b=[1,2,3] 等)以及如何声明 b(b、b(1 to 3))无关, 等等。)。但是,如果您用Dim b() 声明b,意外行为就会消失。 (在这种情况下您不能打印VarPtr(b),因为VarPtr 不能接受数组变量。)
【问题讨论】:
-
不是真正的解释,但 x = farray2(2, b(1)) Debug.Print Join(x, " ") 将给出字符串中的值而不是指针。看起来 Join 函数在带有 ParamArray 的 Variant() 上的行为不同(不同的评估步骤......??)
-
你并不孤单!看到这个:stackoverflow.com/questions/3375562/…
-
感谢 Blackhawk,对问题 3375562 的公认答案是它是一个错误。上一个问题确实是相似的,但在实现上有所不同。共同点是函数参数中的第一个元素(上面的 farray 中的 r )对于修改参数数组行为至关重要,并且两个问题都注意到这种行为是不稳定的,并且取决于应该不连接的内容(例如 sub 代替功能,b 的不同声明等)
-
我认为它是是stackoverflow.com/q/3375562/11683的副本。