C# unsafe code(轉)

http://www.cnblogs.com/dc10101/archive/2009/03/06/1404586.html

unsafe

{               

    int[] array = new int[10];

    for (int i = 0; i < array.Length; i++)

    {

        array[i] = i;

    }

    fixed (int* p = array) 

    {

        for (int i = 0; i < array.Length; i++)

        {

            System.Console.WriteLine(p[i]);

        }                    

    }               

}

指針在c#中是不提倡使用的,有關指針的操作被認為是不安全的(unsafe)。因此運行這段代碼之前,先要改一個地方,否則編譯不過無法運行。
修改方法:在右側的solution Explorer中找到你的項目,在項目圖標(綠色)上點右鍵,選最後一項properties,然後在Build標簽頁裡把Allow unsafe code勾選上。之後這段代碼就可以運行了,你會看到,上面這段代碼可以像C語言那樣用指針操縱數組。但前提是必須有fixed (int* p = array),它的意思是讓p固定指向數組array,不允許改動。因為C#的自動垃圾回收機制會允許已經分配的內存在運行時進行位置調整,如果那樣,p可能一開始指的是array,但後來array的位置被調整到別的位置後,p指向的就不是array了。所以要加一個fixed關鍵字,把它定在那裡一動不動,之後的操作才有保障。

另有兩點需要注意:

1)指針的使用必須放在unsafe區域裡;unsafe關鍵字也可作為類或方法的修飾符。

2)fixed (int* p = array)中,p的定義不能寫在別處,而且fixed關鍵字也只能在unsafe區域裡使用。

 

(*) 略簡潔的unsafe寫法

class Program

    {

        unsafe public static UInt16 Htons(UInt16 src) 

        {

            UInt16 dest;

            // 不能照搬C的源代码,因为有些类型长度不一样,如char(2字节),long(8字节)

            // ((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里调用

            unsafe

            {                

                val = Htons(val);

            }

            Console.WriteLine(val);



            // 更简洁的写法是把unsafe block写在函数内部

            val = ConciseHtons(val);

            Console.WriteLine(val);

        }                

    }

(*) stackalloc

stackalloc的用處僅僅是把數組分配在棧上(默認是分配在托管堆上的)。

class MyClass

    {

        public int val;

    }



    class Program

    {                

        static void Main() 

        {            

            unsafe

            {                

                MyClass *p = stackalloc MyClass[1]; // Error!! 如果类型要放在托管堆上则不行,如果MyClass是struct就OK了

                p->val = 1;



                int *iArray = stackalloc int[100];  // OK,在栈上创建数组, int类型本身就是放在栈上的

            }            

        }                

    }

注意:指針指向的內存一定要固定。凡是C#裡的引用類型(一切類型的數組都是引用類型)都是分配在托管堆上的,都不固定。有兩種方法強制固定,一種是用stackalloc分配在棧上,另一種是用fixed分配在堆上。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值