11

最终编辑:它确实似乎是一个编译器错误 - 请参阅接受的答案。

在 Excel 2007 中使用 VBA,我在“Class1”中有以下代码:

Option Explicit

Public Function strange(dummy As String, ParamArray pa())
    Debug.Print pa(LBound(pa))
End Function

Public Sub not_strange(dummy As String, ParamArray pa())
    Debug.Print pa(LBound(pa))
End Sub

Public Function also_not_strange(ParamArray pa())
    Debug.Print pa(LBound(pa))
End Function

以及模块中的一些模式代码:

Option Explicit

Public Function not_strange_either(dummy As String, ParamArray pa())
    Debug.Print pa(LBound(pa))
End Function

Public Sub outer(v)
    Dim c As Class1
    Set c = New Class1

    Call c.strange("", v(LBound(v)))
    Call c.not_strange("", v(LBound(v)))
    Call c.also_not_strange(v(LBound(v)))

    Call not_strange_either("", v(LBound(v)))
End Sub

如果像这样从立即窗口调用“外部”:

call outer(array("a"))

我得到了看起来很奇怪的输出:

 102085832 
a
a
a

被调用的例程是否在类模块中,是 Sub 还是 Function,以及是否有初始参数,似乎都很重要。我是否遗漏了有关 VBA 应该如何工作的内容?有任何想法吗?

奇怪的数字随着运行而变化。我说“看起来很像一个指针”,因为如果我这样称呼:

Public Sub outer2(v)
    Dim c As Class1
    Set c = New Class1

    Dim ind As Long
    For ind = LBound(v) To UBound(v)
        Call c.strange("", v(ind))
    Next ind
End Sub

像这样:

call outer2(array("a","b","c"))

我得到如下输出:

 101788312 
 101788328 
 101788344 

增加16让我怀疑,但我真的不知道。另外,传递一个值,比如调用:

Call c.strange("", CStr(v(ind)))

工作得很好。

编辑:更多信息......如果我将'c.strange'的返回值分配给某物而不是将其丢弃,我会得到相同的行为:

Public Sub outer3(v)
    Dim c As Class1
    Set c = New Class1

    Dim x
    x = c.strange("", v(LBound(v)))

    Call c.not_strange("", v(LBound(v)))
    Call c.also_not_strange(v(LBound(v)))

    Call not_strange_either("", v(LBound(v)))
End Sub

有趣的是,如果我如上所述调用我的测试例程,并使用调用“数组”产生的参数,则假定的指针值会发生变化。但是,如果我这样称呼它:

call outer([{1,2,3}])

即使我反复拨打电话,我也会收到相同的号码。(如果我切换到 Windows 中的另一个应用程序,比如我的浏览器,这个数字会发生变化。)所以,现在我很感兴趣的是 Excel 评估器(用括号调用)似乎缓存了它的结果......

4

1 回答 1

10

现在这太棒了。

转载于 Office 2003。
看起来像一个编译器错误。

问题出在这一行:

Call c.strange("", v(LBound(v)))

在这里,编译器创建了一个Variant包含Variant's 的一维数组,其中唯一的元素是指针而不是值。这个指针然后转到strange实际上并不奇怪的函数,它只打印Variant\Long传递给它的值。

这个技巧使编译器恢复了理智:

Call c.strange("", (v(LBound(v))))

编辑

是的,这个幻数是指向应该传递给strange方法的 VARIANT 结构的指针。其中的第一个字段是8,即是vbString,而数据字段包含一个指向实际字符串的指针"a"

因此,它绝对是一个编译器错误......另一个关于数组的 VB 编译器错误;)

于 2010-07-30T22:05:10.900 回答