为啥通过 ParamArray 将数组元素传递给函数时,varpointer 会到达函数中?
Posted
技术标签:
【中文标题】为啥通过 ParamArray 将数组元素传递给函数时,varpointer 会到达函数中?【英文标题】:Why, when passing an array element to a function through a ParamArray, does a varpointer arrive in the function?为什么通过 ParamArray 将数组元素传递给函数时,varpointer 会到达函数中? 【发布时间】: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() 上的行为不同(不同的评估步骤......??) 你并不孤单!看到这个:***.com/questions/3375562/… 如果您想深入挖掘,我建议采取两种可能的行动方案:1. 您可以使用我的答案here 中的类型来处理底层数据结构 VARIANT 和 SAFEARRAY 2. 您可以反编译实际运行的已编译 VBA 代码,以查看各个 pcode 指令是否显示编译器错误,使用类似this 感谢 Blackhawk,对问题 3375562 的公认答案是它是一个错误。上一个问题确实是相似的,但在实现上有所不同。共同点是函数参数中的第一个元素(上面的 farray 中的 r )对于修改参数数组行为至关重要,并且两个问题都注意到这种行为是不稳定的,并且取决于应该不连接的内容(例如 sub 代替功能,b 的不同声明等) 我认为它是是***.com/q/3375562/11683的副本。 【参考方案1】:我认为这个错误是由于数组“声明”而出现的。 在这一点上,我认为微软明确表示:
数组
您可以声明一个变量来保存一个数组,该数组可以保存多个值。要指定一个变量包含一个数组,请在其变量名后面紧跟括号。
开启here
【讨论】:
我认为你错过了重点:使用 ParamArray 时,有时传递的指针被解释为 'val' 而不是 'var'。【参考方案2】:我认为,这是“C”中的粗心大意。您会遇到这样的错误
#include <stdio.h>
int main(int argc, char **argv)
int *X;
int i;
i = 7;
X = &i;
printf("%d\n", X);
printf("%d\n", *X);
return(0);
阐述:
“C”是一种抽象汇编器。您必须了解通过地址(或指针)访问内存的概念。与
int i;
你声明一个变量,它保存一个整数(这个整数的位数取决于编译器)。与
i = 7;
你在内存中定义这个变量的值(这里是 7)。与
int *X;
您声明一个变量,该变量将指针的值(指针的位数取决于编译器;通常整数和指针的位数相等)到包含整数的位置.与
X = &i;
您将指针 X 的值定义为变量 i 的地址。与
*X
您可以访问内存中 X 指向的位置的(整数)值。与
printf("%d\n", X);
您打印指针 X 的值(解释为整数)。与
printf("%d\n", *X);
您打印内存的(整数)值,X 指向的位置。
我相信,有人忘记了“*”。
【讨论】:
你能详细说明一下吗?我不做C.... 希望对您有所帮助...以上是关于为啥通过 ParamArray 将数组元素传递给函数时,varpointer 会到达函数中?的主要内容,如果未能解决你的问题,请参考以下文章