奇怪的观察:
通常,当我想将地址保存到变量中的函数时,我会执行以下操作:
Function getAddress(ByVal func As LongPtr) As LongPtr
getAddress = func
End Function
Sub printAddress()
Dim functionPointer As LongPtr
functionPointer = getAddress(AddressOf myFunc)
Debug.Print functionPointer
End Sub
Run Code Online (Sandbox Code Playgroud)
但是我发现我可以使用1缸套
functionPointer = VBA.CLngPtr(AddressOf myFunc)
Run Code Online (Sandbox Code Playgroud)
而
functionPointer = CLngPtr(AddressOf myFunc)
Run Code Online (Sandbox Code Playgroud)
...不起作用并加薪
编译错误:
预期:表达
这是怎么回事?据我所知,唯一的区别CLngPtr是在全局变量(class?)中声明了,而VBA.CLngPtr显式限定了声明,但我不知道为什么这会导致观察到的行为(它们都指向同一个函数,但没有他们?)
如果您使用默认的 IDE 设置(关键字和标识符的设置并没有真正不同),那么这一点不会很明显。这是使用不同颜色时的外观:

您可以看到它CLngPtr像圣诞树一样亮起来,看起来就像任何其他关键字一样。将其与 进行比较Abs,它也是一个函数,但保持浅蓝色,就好像它只是一个标识符。
这是由 VBA 编译器优化的提示CLngPtr,因此它实际上是内联方法1,这就是如果您尝试用作CLngPtr表达式时会出现错误的原因。然而,aVBA.CLngPtr是一个真函数,因此可以用作表达式的一部分,但由于非优化路径而导致性能损失非常轻微。
CLng您会在 say或任何转换函数,甚至Mid语句(而不是函数)中看到同样的情况。其中有几个函数VBA可能会被编译器内联,并且通常会因它们是否变成关键字而有所不同。另请注意,括号的颜色不同。
哎呀,甚至还Debug.Print得到了特殊待遇,如果您熟悉它,您可能知道它不完全是一个类,也不完全是一个模块,但您不能Print没有Debug.
C***()基本上VBA.C***()是一样的东西。然而,VBA 编译器可以并且将会尝试通过内部重新排列用于转换的机器指令(或内联函数正在执行的任何操作)来优化这些位。重新排列指令的结果是它可能不再在所有上下文中兼容。在这种情况下,我可以想象(但不知道事实!)CLngPtr()内联指令返回一个值,而不是一个引用,这与参数声明不兼容,这就是为什么当我们尝试时会出现语法错误将其用作参数。请注意,这种情况不会发生AddressOf- LHS 上的任何其他函数都会有相同的语法错误,因此它与AddressOf内联方法无关。