有如下代碼:
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
}
.method public static void Change0(int32[]& a) cil managed{ // Code Size: 14 byte(s) .maxstack 3 L_0000: ldarg.0 L_0001: ldind.ref L_0002: ldc.i4.0 L_0003: ldc.i4.s 123 L_0005: stelem.i4 L_0006: ldarg.0 L_0007: ldsfld int32[] WinForm.Units.WinForm::bb L_000c: stind.ref L_000d: ret }
.method public static void Change2(int32[] a) cil managed{ // Code Size: 42 byte(s) .maxstack 4 .locals ( int32 num1) L_0000: ldarg.0 L_0001: callvirt instance object [mscorlib]System.Array::Clone() L_0006: castclass int32[] L_000b: starg.s a L_000d: ldarg.0 L_000e: ldc.i4.0 L_000f: ldc.i4.s 123 L_0011: stelem.i4 L_0012: ldsfld int32[] WinForm.Units.WinForm::bb L_0017: dup L_0018: ldlen L_0019: stloc.0 L_001a: ldarg.0 L_001b: ldloc.0 L_001c: ldc.i4.s 11 L_001e: ble.s L_0023 L_0020: ldc.i4.s 11 L_0022: stloc.0 L_0023: ldloc.0 L_0024: call void [mscorlib]System.Array::Copy([mscorlib]System.Array, [mscorlib]System.Array, int32) L_0029: ret }
.method public static void Change3(int32[]& a) cil managed{ // Code Size: 31 byte(s) .maxstack 4 .locals ( int32 num1) L_0000: ldarg.0 L_0001: ldind.ref L_0002: ldc.i4.0 L_0003: ldc.i4.s 123 L_0005: stelem.i4 L_0006: ldsfld int32[] WinForm.Units.WinForm::bb L_000b: dup L_000c: ldlen L_000d: stloc.0 L_000e: ldarg.0 L_000f: ldind.ref L_0010: ldloc.0 L_0011: ldc.i4.s 11 L_0013: ble.s L_0018 L_0015: ldc.i4.s 11 L_0017: stloc.0 L_0018: ldloc.0 L_0019: call void [mscorlib]System.Array::Copy([mscorlib]System.Array, [mscorlib]System.Array, int32) L_001e: ret }
結論:
使用array of Int32 方式,實際上對應于C#的可變數目參數,即 params Int32[],
這種參數方式是傳遞的數組的首地址(即參數的值),而不是存放數組首地址的變量的地址
加上Var修飾,即加入ref修飾,傳遞的是存放數組首地址的變量的地址(即參數變量自身的地址)
使用Ta方式,則在函數內部對數組的值進行克隆,既不改變數組的首地址,也不改變原數組的值
加入var 修飾,好像傳遞的是變量自身的地址,這里還是沒看懂是為什么。
對應的C#代碼為public static void Change(params int[] a){ a[0] = 0x7b; a = WinForm.bb;}
|
|
新聞熱點
疑難解答
圖片精選