2009-02-26 33 views
20

trong C#, là có một cách đểC địa chỉ # bộ nhớ và biến

  1. Lấy địa chỉ bộ nhớ lưu trữ trong một biến kiểu tham khảo?
  2. Lấy địa chỉ bộ nhớ của biến số ?

EDIT:

int i; 
int* pi = &i; 
  • Làm thế nào để bạn in ra các giá trị hex của pi?

Trả lời

13

Đối # 2, & điều hành sẽ làm việc trong thời trang tương tự như trong C. Nếu biến không phải là trên stack, bạn có thể cần phải sử dụng một tuyên bố fixed để ghim nó xuống khi bạn làm việc để thùng rác người thu gom không di chuyển nó.

Đối với số 1, các loại tham chiếu phức tạp hơn: bạn cần sử dụng GCHandle và loại tham chiếu phải có thể ghi được, tức là có bố cục bộ nhớ được xác định và có thể sao chép bit.

Để truy cập vào địa chỉ như một con số, bạn có thể đúc từ loại con trỏ đến IntPtr (một kiểu số nguyên được định nghĩa là kích thước giống như một con trỏ), và từ đó đến uint hoặc ulong (tùy thuộc vào kích thước con trỏ của máy cơ bản).

using System; 
using System.Runtime.InteropServices; 

[StructLayout(LayoutKind.Sequential)] 
class Blittable 
{ 
    int x; 
} 

class Program 
{ 
    public static unsafe void Main() 
    { 
     int i; 
     object o = new Blittable(); 
     int* ptr = &i; 
     IntPtr addr = (IntPtr)ptr; 

     Console.WriteLine(addr.ToString("x")); 

     GCHandle h = GCHandle.Alloc(o, GCHandleType.Pinned); 
     addr = h.AddrOfPinnedObject(); 
     Console.WriteLine(addr.ToString("x")); 

     h.Free(); 
    } 
} 
+1

# 2, điều đó thật tuyệt. nhưng làm thế nào bạn có thể nhận được địa chỉ bộ nhớ như một chuỗi. nói int i; int * pi = & i; Tôi không thể in nó bằng cách sử dụng Console.WriteLine (pi); Tôi mong đợi một cái gì đó như 0x0439ecc4 được in. Bất kỳ đầu mối? –

+0

Console.WriteLine ("0x" + pi.ToString ("x") sẽ in giá trị hex –

+0

@Hamish, pi.ToString ("x") tăng lỗi biên dịch. "Toán tử '. Không thể áp dụng cho toán hạng loại 'int *' " –

5

Số 1 là không thể, bạn không thể có con trỏ đến đối tượng được quản lý. Tuy nhiên, bạn có thể sử dụng một cấu trúc IntPtr để có được thông tin về địa chỉ của con trỏ trong tài liệu tham khảo:

GCHandle handle = GCHandle.Alloc(str, GCHandleType.Pinned); 
IntPtr pointer = GCHandle.ToIntPtr(handle); 
string pointerDisplay = pointer.ToString(); 
handle.Free(); 

Đối số 2 bạn sử dụng & điều hành:

int* p = &myIntVariable; 

Pointers tất nhiên phải được thực hiện trong một khối không an toàn và bạn phải cho phép mã không an toàn trong cài đặt dự án. Nếu biến là biến cục bộ trong phương thức, nó được cấp phát trên ngăn xếp, vì vậy nó đã được sửa, nhưng nếu biến là thành viên của đối tượng, bạn phải ghim đối tượng đó vào bộ nhớ bằng cách sử dụng từ khóa fixed để từ khóa không bị di chuyển bộ thu gom rác.

+0

Rất tiếc, tại sao mã không thể biên dịch với chuỗi str =" hello "; string * ptr = str;? bất kỳ ý tưởng nào? –

+0

Điều xấu của tôi, điều đó thực sự không thể thực hiện được. không thể có một con trỏ đến một đối tượng được quản lý, bạn phải sử dụng một IntPtr. – Guffa

+5

Tại sao các downvote? Nếu bạn không nói những gì nó là bạn không thích, nó là vô nghĩa ... – Guffa

2

Để trả lời câu hỏi của bạn một cách chính xác nhất:

# 1 là có thể nhưng một chút khéo léo, và cần được chỉ được thực hiện vì lý do gỡ lỗi:

object o = new object(); 
TypedReference tr = __makeref(o); 
IntPtr ptr = **(IntPtr**)(&tr); 

này làm việc cho bất kỳ đối tượng và thực sự trả về nội trỏ đến đối tượng trong bộ nhớ. Hãy nhớ rằng địa chỉ có thể thay đổi bất cứ lúc nào vì GC, mà thích di chuyển các đối tượng trên bộ nhớ.

# 2 Con trỏ không phải là đối tượng và do đó không kế thừa ToString từ chúng. Bạn phải đưa con trỏ đến IntPtr như sau:

Console.WriteLine((IntPtr)pi); 
Các vấn đề liên quan