|
有人說(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
|
|
|