C#使用指針詳細(xì)介紹
指針在C\C++里面可是一個(gè)好東西,但是到j(luò)ava,.net的時(shí)代指針已經(jīng)被封裝起來(lái),對(duì)用戶不可見(jiàn),這點(diǎn)java做的非常的徹底。.net可能因?yàn)檫€存在一個(gè)托管C++,因此指針并沒(méi)有完全廢除,C#還是保留了指針的操作。
要C#使用指針首先要對(duì)使用指針的代碼用unsafe進(jìn)行進(jìn)行聲明,聲明和public聲明一樣,可以對(duì)整個(gè)類進(jìn)行聲明,也可以是類里面某個(gè)方法或者屬性。在代碼里什么后,還需要修改工程項(xiàng)目的Build屬性,讓編譯器支持指針的操作。
做好事前的工作就可以C#使用指針了。指針的使用方法和C++下使用沒(méi)有太多差別。只要編譯器不報(bào)錯(cuò)就沒(méi)有太大問(wèn)題。
下面是對(duì)指針的一些使用上的理解:
1.指針類型可以是實(shí)體變量(int,double)也可以是enum,同時(shí)也支持結(jié)構(gòu)體變量struct。但不能是類。不過(guò)空指針可以指向類,只不過(guò)空指針不能進(jìn)行任何操作,也只能把空指針作為傳遞對(duì)象來(lái)使用。
2.C#提供一個(gè)的關(guān)鍵字stackalloc用于申請(qǐng)堆棧內(nèi)存。注意,這個(gè)申請(qǐng)內(nèi)存分配的是棧內(nèi)存,當(dāng)函數(shù)執(zhí)行完畢后,內(nèi)存會(huì)被自動(dòng)回收。不過(guò)我想用這個(gè)棧內(nèi)存基本可以解決40%的問(wèn)題,而且使用的時(shí)候不必?fù)?dān)心內(nèi)存泄漏問(wèn)題。
3 .net好像不直接支持堆內(nèi)存的申請(qǐng)(這個(gè)對(duì).net來(lái)說(shuō)很危險(xiǎn)),不過(guò)我們可以通過(guò)調(diào)用win32 api 的方法進(jìn)行申請(qǐng)。這樣就可以解決剩下40%的問(wèn)題。堆內(nèi)存申請(qǐng)的方法在MSDN里面有相關(guān)的文檔,具體實(shí)現(xiàn)代碼見(jiàn)附1。
4.結(jié)構(gòu)體是一個(gè)特殊的對(duì)象。他與類的定義就差一個(gè)關(guān)鍵字,使用方法也和類一樣,可以定義屬性,可以定義方法。但是在進(jìn)行指針操作的時(shí)候雙方就有很大的差別了。結(jié)構(gòu)體可以通過(guò)sizeof()取得大小,大小與結(jié)構(gòu)體里有多少實(shí)體變量有關(guān),但是如果struck里定義了類的對(duì)象,或者指針,sizeof可能會(huì)編譯不過(guò)(void* 的空指針例外,不過(guò)需要在結(jié)構(gòu)體聲明處加上unsafe)。
5.fixed關(guān)鍵字:目前了解的不多,不過(guò)有一個(gè)很實(shí)用的例子可以讓C#使用指針能夠和.net里的數(shù)組進(jìn)行交互操作:
- byte[]buffer=newbyte[100];
 - fixed(byte*p=buffer)
 - {
 - P[0]=123;
 - ……
 - }
 
其它
- publicunsafeclassMemory
 - {
 - //Handlefortheprocessheap.Thishandleisusedinallcallstothe
 - //HeapXXXAPIsinthemethodsbelow.
 - staticintph=GetProcessHeap();
 - //Privateinstanceconstructortopreventinstantiation.
 - privateMemory(){}
 - //Allocatesamemoryblockofthegivensize.Theallocatedmemoryis
 - //automaticallyinitializedtozero.
 - publicstaticvoid*Alloc(intsize)
 - {
 - void*result=HeapAlloc(ph,HEAP_ZERO_MEMORY,size);
 - if(result==null)thrownewOutOfMemoryException();
 - returnresult;
 - }
 - //Copiescountbytesfromsrctodst.Thesourceanddestination
 - //blocksarepermittedtooverlap.
 - publicstaticvoidCopy(void*src,void*dst,intcount)
 - {
 - byte*ps=(byte*)src;
 - byte*pd=(byte*)dst;
 - if(ps>pd)
 - {
 - for(;count!=0;count--)*pd++=*ps++;
 - }
 - elseif(ps<pd)
 - {
 - for(ps+=count,pd+=count;count!=0;count--)*--pd=*--ps;
 - }
 - }
 - //Freesamemoryblock.
 - publicstaticvoidFree(void*block)
 - {
 - if(!HeapFree(ph,0,block))thrownewInvalidOperationException();
 - }
 - //Re-allocatesamemoryblock.Ifthereallocationrequestisfora
 - //largersize,theadditionalregionofmemoryisautomatically
 - //initializedtozero.
 - publicstaticvoid*ReAlloc(void*block,intsize)
 - {
 - void*result=HeapReAlloc(ph,HEAP_ZERO_MEMORY,block,size);
 - if(result==null)thrownewOutOfMemoryException();
 - returnresult;
 - }
 - //Returnsthesizeofamemoryblock.
 - publicstaticintSizeOf(void*block)
 - {
 - intresult=HeapSize(ph,0,block);
 - if(result==-1)thrownewInvalidOperationException();
 - returnresult;
 - }
 - //HeapAPIflags
 - constintHEAP_ZERO_MEMORY=0x00000008;
 - //HeapAPIfunctions
 - [DllImport("kernel32")]
 - staticexternintGetProcessHeap();
 - [DllImport("kernel32")]
 - staticexternvoid*HeapAlloc(inthHeap,intflags,intsize);
 - [DllImport("kernel32")]
 - staticexternboolHeapFree(inthHeap,intflags,void*block);
 - [DllImport("kernel32")]
 - staticexternvoid*HeapReAlloc(inthHeap,intflags,
 - void*block,intsize);
 - [DllImport("kernel32")]
 - staticexternintHeapSize(inthHeap,intflags,void*block);
 - }
 
【編輯推薦】















 
 
 
 
 
 
 