C#指針使用簡析
C#指針的存在狀況簡析:指針在C\C++里面可是一個好東西,但是到java,.net的時代指針已經被封裝起來,對用戶不可見,這點java做的非常的徹底。.net可能因為還存在一個托管C++,因此指針并沒有完全廢除,C#還是保留了指針的操作。
要使用指針首先要對使用指針的代碼用unsafe進行進行聲明,聲明和public聲明一樣,可以對整個類進行聲明,也可以是類里面某個方法或者屬性。在代碼里什么后,還需要修改工程項目的Build屬性,讓編譯器支持指針的操作。
做好事前的工作就可以使用指針了。指針的使用方法和C++下使用沒有太多差別。只要編譯器不報錯就沒有太大問題。
下面就C#指針來看其他指針的一些使用上的理解:
1. 指針類型可以是實體變量(int,double)也可以是enum,同時也支持結構體變量struct。但不能是類。不過空指針可以指向類,只不過空指針不能進行任何操作,也只能把空指針作為傳遞對象來使用。
2. C#提供一個的關鍵字stackalloc用于申請堆棧內存。注意,這個申請內存分配的是棧內存,當函數執行完畢后,內存會被自動回收。不過我想用這個棧內存基本可以解決40%的問題,而且使用的時候不必擔心內存泄漏問題。
3. .net 好像不直接支持堆內存的申請(這個對.net來說很危險),不過我們可以通過調用win32 api 的方法進行申請。這樣就可以解決剩下40%的問題。堆內存申請的方法在MSDN里面有相關的文檔,具體實現代碼見附。
4. 結構體是一個特殊的對象。他與類的定義就差一個關鍵字,使用方法也和類一樣,可以定義屬性,可以定義方法。但是在進行指針操作的時候雙方就有很大的差別了。結構體可以通過sizeof()取得大小,大小與結構體里有多少實體變量有關,但是如果struck里定義了類的對象,或者指針,sizeof可能會編譯不過(void* 的空指針例外,不過需要在結構體聲明處加上unsafe)。
5. fixed關鍵字:目前了解的不多,不過有一個很實用的例子可以讓指針能夠和.net里的數組進行交互操作:
- byte[] buffer = new byte[100];
- fixed (byte* p = buffer)
- {
- P[0] = 123;
- ……
- }
附C#指針的實現:
- public unsafe class Memory
- {
- // Handle for the process heap.
- // This handle is used in all calls to the
- // HeapXXX APIs in the methods below.
- static int ph = GetProcessHeap();
- // Private instance constructor to prevent instantiation.
- private Memory() { }
- // Allocates a memory block of the given size.
- //The allocated memory is
- // automatically initialized to zero.
- public static void* Alloc(int size)
- {
- void* result = HeapAlloc(ph, HEAP_ZERO_MEMORY, size);
- if (result == null) throw new OutOfMemoryException();
- return result;
- }
- // Copies count bytes from src to dst.
- //The source and destination
- // blocks are permitted to overlap.
- public static void Copy(void* src, void* dst, int count)
- {
- byte* ps = (byte*)src;
- byte* pd = (byte*)dst;
- if (ps > pd)
- {
- for (; count != 0; count--) *pd++ = *ps++;
- }
- else if (ps < pd)
- {
- for (ps += count, pd += count;
- count != 0; count--) *--pd = *--ps;
- }
- }
- // Frees a memory block.
- public static void Free(void* block)
- {
- if (!HeapFree(ph, 0, block))
- throw new InvalidOperationException();
- }
- // Re-allocates a memory block.
- //If the reallocation request is for a
- // larger size, the additional region of memory is automatically
- // initialized to zero.
- public static void* ReAlloc(void* block, int size)
- {
- void* result = HeapReAlloc(ph, HEAP_ZERO_MEMORY, block, size);
- if (result == null) throw new OutOfMemoryException();
- return result;
- }
- // Returns the size of a memory block.
- public static int SizeOf(void* block)
- {
- int result = HeapSize(ph, 0, block);
- if (result == -1) throw new InvalidOperationException();
- return result;
- }
- // Heap API flags
- const int HEAP_ZERO_MEMORY = 0x00000008;
- // Heap API functions
- [DllImport("kernel32")]
- static extern int GetProcessHeap();
- [DllImport("kernel32")]
- static extern void* HeapAlloc(int hHeap, int flags, int size);
- [DllImport("kernel32")]
- static extern bool HeapFree(int hHeap, int flags, void* block);
- [DllImport("kernel32")]
- static extern void* HeapReAlloc(int hHeap, int flags,
- void* block, int size);
- [DllImport("kernel32")]
- static extern int HeapSize(int hHeap, int flags, void* block);
- }
C#指針方面的內容就向你介紹到這里,希望對你了解學習C#指針有所幫助。
【編輯推薦】