(*) unsafe 和 fixed
指針在c#中是不提倡使用的,有關(guān)指針的操作被認(rèn)為是不安全的(unsafe)。因此運(yùn)行這段代碼之前,先要改一個(gè)地方,否則編譯不過無法運(yùn)行。
修改方法:在右側(cè)的solution Explorer中找到你的項(xiàng)目,在項(xiàng)目圖標(biāo)(綠色)上點(diǎn)右鍵,選最后一項(xiàng)properties,然后在Build標(biāo)簽頁里把Allow unsafe code勾選上。之后這段代碼就可以運(yùn)行了,你會看到,上面這段代碼可以像C語言那樣用指針操縱數(shù)組。但前提是必須有fixed (int* p = array),它的意思是讓p固定指向數(shù)組array,不允許改動。因?yàn)镃#的自動垃圾回收機(jī)制會允許已經(jīng)分配的內(nèi)存在運(yùn)行時(shí)進(jìn)行位置調(diào)整,如果那樣,p可能一開始指的是array,但后來array的位置被調(diào)整到別的位置后,p指向的就不是array了。所以要加一個(gè)fixed關(guān)鍵字,把它定在那里一動不動,之后的操作才有保障。
另有兩點(diǎn)需要注意:
1)指針的使用必須放在unsafe的區(qū)域里;unsafe關(guān)鍵字也可作為類或方法的修飾符。
2)fixed (int* p = array)中,p的定義不能寫在別處,而且fixed關(guān)鍵字也只能在unsafe區(qū)域里使用。
(*) 略簡潔的unsafe寫法
{
unsafe public static UInt16 Htons(UInt16 src)
{
UInt16 dest;
// 不能照搬C的源代碼,因?yàn)橛行╊愋烷L度不一樣,如char(2字節(jié)),long(8字節(jié))
// ((char*)&dest)[0] = ((char*)&src)[1];
// ((char*)&dest)[1] = ((char*)&src)[0];
((byte*)&dest)[0] = ((byte*)&src)[1];
((byte*)&dest)[1] = ((byte*)&src)[0];
return dest;
}
public static UInt16 ConciseHtons(UInt16 src)
{
UInt16 dest;
unsafe
{
((byte*)&dest)[0] = ((byte*)&src)[1];
((byte*)&dest)[1] = ((byte*)&src)[0];
}
return dest;
}
static void Main()
{
UInt16 val = 1;
// 如果方法是unsafe的,則必須在unsafe block里調(diào)用
unsafe
{
val = Htons(val);
}
Console.WriteLine(val);
// 更簡潔的寫法是把unsafe block寫在函數(shù)內(nèi)部
val = ConciseHtons(val);
Console.WriteLine(val);
}
}
(*) stackalloc
stackalloc的用處僅僅是把數(shù)組分配在棧上(默認(rèn)是分配在托管堆上的)。
注意:指針指向的內(nèi)存一定要固定。凡是C#里的引用類型(一切類型的數(shù)組都是引用類型)都是分配在托管堆上的,都不固定。有兩種方法強(qiáng)制固定,一種是用stackalloc分配在棧上,另一種是用fixed分配在堆上。