系列文章之四: Array in IL ( 續 ) 上次談了 Array 中的一維數組,這次要談的是多維數組和鋸齒形數組。 多維數組其實就是數組的數組(好像不如 Arra" name="description" />
ILMILY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">系列文章之四:
Array in IL (續)
上次談了Array中的一維數組,這次要談的是多維數組和鋸齒形數組。
多維數組其實就是數組的數組(好像不如Array of Array那么好聽)。上次說過我們用IL可以做一些在C#中不可能做到的事情,比如定義一個數組,它的下界不是從0開始的而是任意一個值。閑話休說,先來看個二維數組的例子。
.assembly matrix{}
//it is a matrix with 2 dimensions
//dim1 from 3 to 5 and dim2 from 4 to 5
//the matrix like this could not be defined in C#
.class private auto ansi beforefieldinit matrix
extends [mscorlib]System.Object
{
.method public hidebysig static void
{
.entrypoint
.maxstack 4
.locals init (int32[,] matrix)
ldc.i4.3// load the lower bound for dimension 1
ldc.i4.5// load the upper bound for dim 1
ldc.i4.4// load the lower bound for dim 2
ldc.i4.5// load the upper bound for dim 2
newobj instance void int32[,]::.ctor(int32,int32,int32,int32)
// ctor means constructor
stloc matrix
ldloc matrix
ldc.i4.3// index of 1st dimension
ldc.i4.4// index of 2nd dimension
ldc.i4.s 34// the value
call instance void int32[,]::Set(int32,int32,int32)//matrix[3,4] = 34
//a section of error code "matrix[1,1] = 11"
//------------------------------------------------------------------
//ldloc matrix
//ldc.i4.1
//ldc.i4.1
//ldc.i4.s 11
//call instance void int32[,]::Set(int32,int32,int32)
//------------------------------------------------------------------
//it will course an exception "System.IndexOutOfRangeException"
ldloc matrix
ldc.i4.3
ldc.i4.4
call instance int32& int32[,]::Address(int32,int32)
//generate a 32 bit integer instance of matrix element matrix[3,4]
//in order to conver it to string for output
call instance string [mscorlib]System.Int32::ToString()
call void [mscorlib]System.Console::WriteLine(string)
ret
}
}
在這個例子中既有二維數組的普通使用方法,又有下界不為0的定義方法。其實我也沒有太多好說的了,我要說的大多都寫在注釋里了。多維數組的定義比一維數組要復雜一些,需要調用專門的構造函數“void int32[,]::.ctor(int32,int32,int32,int32)”來進行構造。還有一點要注意的了,這里使用的是“newobj”,而不是上次所用的“newarr”。就我們一般的二維數組而言下界都是從0開始的,所以實際上我最常用的是這樣的一個構造函數“void int32[0…,0…]::.ctor(int32,int32)”,在這個構造函數中,我們只需要提供兩個維的上就夠了,下界默認從0開始。例子中間有一段注釋掉的代碼,我利用這段代碼來檢驗IL中定義的非0下界數組是不是真的不從0開始。大家可以試一下這段代碼,它一旦運行起來的話系統就會拋出一個"System.IndexOutOfRangeException",看來IL沒用騙我們,的確是從我們定義的下界開始的。
總的看來雖然二維數組的定義要比一維數組復雜一些,但還是比較規整的。接下來我們要看的就是不太規整的東東了——鋸齒數組(Jagged Array)。寫文章離不了例子,我還是只有從例子開始。
//jagged.cs
class jagged
{
public static void
{
int[][] jagged;
jagged = new int[3][];
jagged[0] = new int[1];
jagged[1] = new int[2];
jagged[2] = jagged[1];
jagged[1][1] = 11;
System.Console.WriteLine(jagged[2][1].ToString());
}
}
通過它的輸出可以看出這個鋸齒數組的第3維(jagged[2])和第2維(jagged[1])其實是同一個一維數組,對第2維的處理就是對第3維的處理。
有些朋友可能已經看出來了,我的第一個例子——matrix,其實也是鋸齒形的,但我們并不稱其為鋸齒數組。為什么呢?反編譯上面的代碼,看看真正的鋸齒數組是怎么實現的。(和以前一樣,為了大家看這方便,我對反編譯出來的代碼作了一些修改。)
.assembly jagged{}
.class private auto ansi beforefieldinit jagged
extends [mscorlib]System.Object
{
.method public hidebysig static void
{
.entrypoint
.maxstack 4
.locals init (int32[][] jagged)
ldc.i4.3
newarr int32[]// the jagged array has 3 dimensions
//create a array of int pointer
stloc jagged// jagged = new int[3][];
ldloc jagged
ldc.i4.0//dimension
ldc.i4.1//length of dimension
newarr [mscorlib]System.Int32//jagged[0] = new int[1];
stelem.ref// set the int[] by reference
ldloc jagged
ldc.i4.1
ldc.i4.2
newarr [mscorlib]System.Int32
stelem.ref// it is like the first dimension
ldloc jagged
ldc.i4.2
//{load pionter of 2nd dimension by reference
ldloc jagged
ldc.i4.1
ldelem.ref
//}
stelem.ref// set the pointer of 3rd dimension
ldloc jagged
ldc.i4.1
ldelem.ref// load jagged[1][]
ldc.i4.1// jagged[1][1]
ldc.i4.s 11
stelem.i4// jagged[1][1] = 11
ldloc jagged
ldc.i4.2
ldelem.ref
ldc.i4.1
ldelema [mscorlib]System.Int32
call instance string [mscorlib]System.Int32::ToString()
call void [mscorlib]System.Console::WriteLine(string)
ret
}
}
在鋸齒形數組中,我們首先定義的是一個三行一列的Pointer數組,每個Pointer指向一個Array的實例(當然有可以沒有)。它的處理方式和一維數組很相似(本質上就是一維數組的集合),都是用的IL基本指令ldelem和stelem,不過這里是按引用的方式傳遞的。鋸齒數組的結構如同下圖所示,
鋸齒形數組有一列指針數組,在對數組的操作時起到作用(我想主要是對數組元數的尋址)。C#語言在實現鋸齒形數組的時候隱藏了這一列Pointer的細節,用戶在使用的時候感覺不到它的存在。當然這是在為用戶著想,使用戶不會在使用鋸齒形數組的時候將心思局限于某些技術細節之中。到這里為止,大家對數組也是很明了了吧,我也就到此為止了。
原文轉自:http://www.anti-gravitydesign.com