您的位置:首页 > 编程语言 > Delphi

Delphi2005学习笔记3——数组参数的研究

2004-12-03 19:18 381 查看
有如下代码:
  procedure Change(a:array of Int32);
  procedure Change0(var a:array of Int32);
type
  Ta = array[0..10] of Int32;
  procedure Change2(a:Ta);
  procedure Change3(var a:Ta);

var
  aa:Ta;
  bb:array of Int32;

implementation

{$AUTOBOX ON}

procedure Change(a:array of Int32);
begin
  a[0]:=123;
  a:=bb;
end;

procedure Change0(var a:array of Int32);
begin
  a[0]:=123;
  a:=bb;
end;

procedure Change2(a:Ta);
begin
  a[0]:=123;
  a:=bb;
end;

procedure Change3(var a:Ta);
begin
  a[0]:=123;
  a:=bb;
end;

然后执行下面的语句
SetLength(bb,11);bb[0]:=5678;

  aa := Ta(&Array.CreateInstance(typeof(Int32),11));
  aa[0]:=0;
  Change(aa);
  MessageBox.Show(aa[0].ToString());
  if &Object(aa)=&Object(bb) then MessageBox.Show('=');

  aa := Ta(&Array.CreateInstance(typeof(Int32),11));
  aa[0]:=0;
  Change0(aa);
  MessageBox.Show(aa[0].ToString());
  if &Object(aa)=&Object(bb) then MessageBox.Show('=');

  aa := Ta(&Array.CreateInstance(typeof(Int32),11));
  aa[0]:=0;
  Change2(aa);
  MessageBox.Show(aa[0].ToString());
  if &Object(aa)=&Object(bb) then MessageBox.Show('=');

  aa := Ta(&Array.CreateInstance(typeof(Int32),11));
  aa[0]:=0;
  Change3(aa);
  MessageBox.Show(aa[0].ToString());
  if &Object(aa)=&Object(bb) then MessageBox.Show('=');
结果发现 array of Int32 方式,可以改变数组元素的值,但不能改变数组变量中存储的数组首地址,输出123
var  array of Int32 既可以改变数组的值,又可以改变数组变量中存储的数组首地址,输出5678和=
Ta方式,不能改变数组元素的值,但是却很奇怪,aa和bb指向同一个数组,输出0和=
var Ta方式 可以改变数组元素的值,但是却不是5678而是123;但是aa和bb指向同一个数组,输出123和=

反汇编结果如下
method public static void Change(int32[] a) cil managed
{
      // Code Size: 13 byte(s)
      .maxstack 3
      L_0000: ldarg.0
      L_0001: ldc.i4.0
      L_0002: ldc.i4.s 123
      L_0004: stelem.i4
      L_0005: ldsfld int32[] WinForm.Units.WinForm::bb
      L_000a: starg.s a
      L_000c: ret
}

Change0([]& a)
{

3
L_0000:

L_0002:
L_0003:
L_0005:
L_0006:
L_0007: [] ::
L_000c:
L_000d:
}
Change2([] a)
{

4
(
num1)
L_0000:
L_0006:  []
L_000b:  a
L_000d:
L_000e:
L_000f:
L_0011:
L_0012:  [] ::
L_0017:
L_0018:
L_0019:
L_001a:
L_001b:
L_001c:
L_001e:  L_0023
L_0020:
L_0022:
L_0023:
L_0024:   []::([], [], )
L_0029:
}
Change3([]& a)
{

4
(
num1)
L_0000:

L_0002:
L_0003:
L_0005:
L_0006:  [] ::
L_000b:
L_000c:
L_000d:
L_000e:
L_000f:
L_0010:
L_0011:
L_0013:  L_0018
L_0015:
L_0017:
L_0018:
L_0019:   []::([], [], )
L_001e:
}

结论:
使用array of Int32 方式,实际上对应于C#的可变数目参数,即 params Int32[],
这种参数方式是传递的数组的首地址(即参数的值),而不是存放数组首地址的变量的地址
加上Var修饰,即加入ref修饰,传递的是存放数组首地址的变量的地址(即参数变量自身的地址)

使用Ta方式,则在函数内部对数组的值进行克隆,既不改变数组的首地址,也不改变原数组的值
加入var 修饰,好像传递的是变量自身的地址,这里还是没看懂是为什么。

对应的C#代码为
Change( [] a)
{
[] = ;
= .;
}

Change0(  [] a)
{
[] = ;
= .;
}
Change2([] a)
{
= ([]) .();
[] = ;
num1 = ..;
( > )
{
= ;
}
.(., , );
}
Change3( [] a)
{
[] = ;
num1 = ..;
( > )
{
= ;
}
.(., , );
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  delphi winform object cil byte c#