电竞比分网-中国电竞赛事及体育赛事平台

分享

內(nèi)存__【C#】不安全代碼中的指針用法

 ~飄落~ 2011-06-27
有人說(shuō):"有的女人就像c#,長(zhǎng)得很漂亮,但家務(wù)活不行。"  呵呵,其實(shí)我倒是認(rèn)為不是那個(gè)女人不行,而是那個(gè)男人不行,征服不了那個(gè)女人。C#長(zhǎng)得的確算漂亮,如果你駕馭了它,一樣能讓它服服帖帖做好家務(wù)。
    對(duì)于習(xí)慣C的程序員,Java之類(lèi)的面向?qū)ο缶幊陶Z(yǔ)言用著不是很爽,很多直接訪(fǎng)問(wèn)內(nèi)存的操作行不通。而C#提供了指針的機(jī)制,以滿(mǎn)足C族程序員的這點(diǎn)嗜好。不過(guò)剛開(kāi)始了解到C#支持指針的時(shí)候,我也不以為然,總覺(jué)得這么搞顯得不倫不類(lèi)的。經(jīng)過(guò)一番研究,慢慢感覺(jué)到了在一個(gè)有著強(qiáng)大基礎(chǔ)類(lèi)庫(kù)的OO語(yǔ)言中使用指針的價(jià)值和威力。下面用代碼展示一下使用指針的一些常用操作在C#中是怎么玩的,由于僅僅是展示,所以雜七雜八的代碼全放在一起了。
view plaincopy to clipboardprint?
01. 1using System;  
02. 2  
03. 3namespace Sophy.UnsafeCode  
04. 4{  
05. 5    unsafe class Program  
06. 6    {  
07. 7        static void Main(string[] args)  
08. 8        {  
09. 9            //在棧上分配內(nèi)存  
10.10            byte* arr_on_stack = stackalloc byte[100];  
11.11  
12.12            //下標(biāo)訪(fǎng)問(wèn)數(shù)組  
13.13            for (int i = 0; i < 100; i++)  
14.14            {  
15.15                arr_on_stack[i] = 0;  
16.16            }  
17.17  
18.18            //在堆上分配內(nèi)存  
19.19            fixed (byte* arr_on_heap = new byte[100])  
20.20            {  
21.21                //指針訪(fǎng)問(wèn)數(shù)組  
22.22                for (int i = 0; i < 100; i++)  
23.23                {  
24.24                    *(arr_on_heap + i) = 0;  
25.25                }  
26.26            }  
27.27  
28.28            //在棧上分配一個(gè)結(jié)構(gòu)體  
29.29            Point p = new Point();  
30.30            //用結(jié)構(gòu)體指針操作棧上的結(jié)構(gòu)體  
31.31            Point* pp = &p;  
32.32            pp->x = 200;  
33.33            (*pp).y = 300;  
34.34  
35.35            //在堆上分配一個(gè)結(jié)構(gòu)體  
36.36            fixed (byte* bs = new byte[sizeof(Point)])  
37.37            {  
38.38                //用結(jié)構(gòu)體指針操作堆上的結(jié)構(gòu)體  
39.39                Point* ph = (Point*)bs;  
40.40                (*ph).x = 400;  
41.41                ph->y = 500;  
42.42            }  
43.43  
44.44            //打印結(jié)構(gòu)體內(nèi)存地址  
45.45            Console.WriteLine("pp Memory Address: 0x{0:X}.", ((int)pp).ToString());  
46.46  
47.47            //識(shí)別CPU字節(jié)序  
48.48            pp->x = 1;  
49.49            byte* pb = (byte*)&(pp->x);  
50.50            if (1 == *pb)  
51.51            {  
52.52                Console.WriteLine("Your CPU is little endian.");  
53.53            }  
54.54            else if (1 == *(pb + sizeof(int) - 1))  
55.55            {  
56.56                Console.WriteLine("Your CPU is big endian.");  
57.57            }  
58.58            else 
59.59            {  
60.60                Console.WriteLine("Unkown.");  
61.61            }  
62.62        }  
63.63    }  
64.64  
65.65    unsafe struct Point  
66.66    {  
67.67        public int x;  
68.68        public int y;  
69.69    }  
70.70} 
 1using System;
 2
 3namespace Sophy.UnsafeCode
 4{
 5    unsafe class Program
 6    {
 7        static void Main(string[] args)
 8        {
 9            //在棧上分配內(nèi)存
10            byte* arr_on_stack = stackalloc byte[100];
11
12            //下標(biāo)訪(fǎng)問(wèn)數(shù)組
13            for (int i = 0; i < 100; i++)
14            {
15                arr_on_stack[i] = 0;
16            }
17
18            //在堆上分配內(nèi)存
19            fixed (byte* arr_on_heap = new byte[100])
20            {
21                //指針訪(fǎng)問(wèn)數(shù)組
22                for (int i = 0; i < 100; i++)
23                {
24                    *(arr_on_heap + i) = 0;
25                }
26            }
27
28            //在棧上分配一個(gè)結(jié)構(gòu)體
29            Point p = new Point();
30            //用結(jié)構(gòu)體指針操作棧上的結(jié)構(gòu)體
31            Point* pp = &p;
32            pp->x = 200;
33            (*pp).y = 300;
34
35            //在堆上分配一個(gè)結(jié)構(gòu)體
36            fixed (byte* bs = new byte[sizeof(Point)])
37            {
38                //用結(jié)構(gòu)體指針操作堆上的結(jié)構(gòu)體
39                Point* ph = (Point*)bs;
40                (*ph).x = 400;
41                ph->y = 500;
42            }
43
44            //打印結(jié)構(gòu)體內(nèi)存地址
45            Console.WriteLine("pp Memory Address: 0x{0:X}.", ((int)pp).ToString());
46
47            //識(shí)別CPU字節(jié)序
48            pp->x = 1;
49            byte* pb = (byte*)&(pp->x);
50            if (1 == *pb)
51            {
52                Console.WriteLine("Your CPU is little endian.");
53            }
54            else if (1 == *(pb + sizeof(int) - 1))
55            {
56                Console.WriteLine("Your CPU is big endian.");
57            }
58            else
59            {
60                Console.WriteLine("Unkown.");
61            }
62        }
63    }
64
65    unsafe struct Point
66    {
67        public int x;
68        public int y;
69    }
70}
 
在C#中想要使用指針,要給類(lèi)型、方法或者代碼段加上unsafe關(guān)鍵字,并且編譯的時(shí)候要加上/unsafe選項(xiàng)。在Visual Studio 2005中,勾上“項(xiàng)目屬性->生成”里的“允許不安全代碼”,編譯時(shí)就會(huì)自動(dòng)加上/unsafe選項(xiàng)。
    C#中的指針只能指向值類(lèi)型,并且值類(lèi)型中不能含有引用類(lèi)型。如果允許指針指向引用類(lèi)型,那將是非常令人迷惑的事情。也許你注意到了這行代碼:
     fixed (byte* bs = new byte[sizeof(Point)])
     {
     }
     它把一個(gè)數(shù)組賦給了一個(gè)指針變量,數(shù)組是引用類(lèi)型,那不是和上面說(shuō)的矛盾了嗎?其實(shí)我認(rèn)為是編譯器做了特殊處理,在這里直接將數(shù)組的地址賦給了指針變量。一個(gè)簡(jiǎn)單的fixed關(guān)鍵字,編譯器在背后肯定做了不少事情。因?yàn)橐妙?lèi)型是在托管堆中分配的,受運(yùn)行庫(kù)管理,當(dāng)內(nèi)存中碎片太多時(shí),垃圾回收器可能會(huì)啟動(dòng)內(nèi)存壓縮,有可能將數(shù)組移動(dòng)到別的地方,這時(shí)指針指向的就不是原來(lái)的數(shù)組了,所以fixed作用還在于,把引用類(lèi)型的數(shù)組“釘”在內(nèi)存的那個(gè)位置上,不允許垃圾回收器移動(dòng),直到代碼執(zhí)行到fixed后面兩個(gè)大括號(hào)之外為止。
 
本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/yfqvip/archive/2009/09/24/4588254.aspx

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多