2010-11-30 33 views
7

這是第一問題using c# pointersC#指針VS的IntPtr

所以在c#指針是「不安全」的和而一個IntPtr是被管理對象不會被垃圾收集器管理的第二部分。但爲什麼使用指針呢?什麼時候可以交換使用兩種方法?

+9

記住`IntPtr`僅僅是在.NET原始數據類型這是旨在舉行一個地址。它基本上只是一個「int」,它是32位機器上的32位和64位機器上的64位。 「IntPtr」本身沒有關於指針的具體內容。 – 2010-11-30 23:28:18

回答

7

CLI區分託管指針和非託管指針。託管指針是鍵入的,指向值的類型由運行時知道,並且只允許類型安全分配。非託管指針只能用支持它們的語言直接使用,C++/CLI就是最好的例子。

C#語言中非託管指針的等效值爲IntPtr。您可以自由地轉換指針與來自演員。即使它的名字聽起來像「指向int的指針」,它也沒有與它關聯,它相當於C/C++中的void*。使用這種指針需要pinvoke,Marshal類或轉換爲託管指針類型。

一些代碼一起玩:

using System; 
using System.Runtime.InteropServices; 

unsafe class Program { 
    static void Main(string[] args) { 
     int variable = 42; 
     int* p = &variable; 
     Console.WriteLine(*p); 
     IntPtr raw = (IntPtr)p; 
     Marshal.WriteInt32(raw, 666); 
     p = (int*)raw; 
     Console.WriteLine(*p); 
     Console.ReadLine(); 
    } 
} 

注意unsafe關鍵字是如何適用於本案。你可以打電話給Marshal.WriteInt64(),你什麼都不會投訴。它破壞了堆棧幀。

5

IntPtr是一個託管對象,但它指向的對象仍然沒有垃圾收集。在C#中使用不安全的指針確實是你應該避免的。使用不安全指針的代碼可能不會考慮x86和x64系統之間的內存地址差異。它允許您直接操作內存地址,這與IntPtr不一樣,因爲您需要在指針和存儲在此內存地址處的實際結構之間進行編組。使用不安全的指針可以直接使用底層的類型:這裏是我寫的一個blog post,說明了不安全指針的一種可能用法。另一個常見的例子是manipulating image pixels直接。

7

IntPtr不能用作指針的替代品。

IntPtr只包含一個數值,因此您不能使用它來訪問任何數據。由此得名;它是一個與指針大小相同的整數值。您需要將該值轉換爲訪問指向的數據的指針,因此如果不使用不安全的代碼,則無法訪問數據。

另外請注意IntPtr是一個結構,而不是一個對象,所以垃圾收集器根本就沒有直接關心它。

+1

實際上有使用編組 – 2010-11-30 23:40:05

+2

@Ali Tarhini:這只是調用一種爲您使用不安全代碼的方法。關鍵是最終必須使用不安全的代碼,否則無法訪問數據。 – Guffa 2010-11-30 23:42:12

2

解引用指向的數據由IntPtr的是這僅僅粘附的IntPtr的數量爲不安全的ptr的地址,如下