C# unsafe code

來源:互聯網
上載者:User

(*) unsafe 和 fixed

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分配在堆上。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.