تعریف پوینتر در Vb.net

ms_vb

Member
سلام
چطور میتونم یه Pointer توی VB.net تعریف کنم که به آدرس یه متغیر اشاره کنه؟
ممنون از جوابتون
 

the_king

مدیرکل انجمن
سلام
چطور میتونم یه Pointer توی VB.net تعریف کنم که به آدرس یه متغیر اشاره کنه؟
ممنون از جوابتون

فرض کنیم که یک متغیر دارید به نام x از نوع داده دلخواه :
کد:
Dim x As Single = 12.5

آدرس حافظه این متغیر زمانی قابل دسترسی است که موقعیت اش در حافظه ثابت باشد، در Net. آدرس حافظه
متغیر ها ممکن است تغییر کند، مگر از Net. بخواهید که جلوی جابجای این متغیر در حافظه را بگیرد. به اینکار
اصطلاحا Pinned کردن حافظه می گویند. برای اینکار شما نیاز به یک GCHandle دارید :
کد:
Dim gc As System.Runtime.InteropServices.GCHandle

GCHandle را روی آن متغیر دلخواه x در وضعیت Pinned تنظیم می کنید :
کد:
gc = System.Runtime.InteropServices.GCHandle.Alloc(x, Runtime.InteropServices.GCHandleType.Pinned)

حالا AddrOfPinnedObject آدرس حافظه آن متغیر را به شما می دهد :
کد:
MessageBox.Show(gc.AddrOfPinnedObject())

مثلا می توانید در متغیری قرارش دهید :
کد:
Dim p As IntPtr = gc.AddrOfPinnedObject

فقط فراموش نکنید که در پایان کار GCHandle را آزاد کنید تا حافظه آن متغیر در حالت Pinned نماند :
کد:
gc.Free()

کد:
Imports System.Runtime.InteropServices

.
.
.
        Dim x As Single = 12.5
        Dim gc As GCHandle
        gc = GCHandle.Alloc(x, GCHandleType.Pinned)
        MessageBox.Show(gc.AddrOfPinnedObject())
        gc.Free()
 

ms_vb

Member
سلام
خیلی ممنون از جوابتون
اما کد زیر نتیجه ای را که میخواهم به من نمی دهد
نمی دانم مشکل کجاست؟
در MsgBox اول باید عدد 12.5 و در دومی باید 5 نمایش داده شود. درسته؟
کد:
[COLOR=black][FONT=Consolas]  [/FONT][/COLOR]
[COLOR=black][FONT=Consolas]      [/FONT][/COLOR][COLOR=blue][FONT=Consolas]Dim[/FONT][/COLOR][COLOR=black][FONT=Consolas] x [/FONT][/COLOR][COLOR=blue][FONT=Consolas]As[/FONT][/COLOR][COLOR=blue][FONT=Consolas]Single[/FONT][/COLOR][COLOR=black][FONT=Consolas] = 12.5
[/FONT][/COLOR][COLOR=blue]Dim[/COLOR] gc [COLOR=blue]As[/COLOR] [COLOR=#2b91af]GCHandle[/COLOR] [/LEFT]
[COLOR=blue]Dim[/COLOR] p [COLOR=blue]As[/COLOR] [COLOR=#2b91af]IntPtr[/COLOR]    
gc = [COLOR=#2b91af]GCHandle[/COLOR].Alloc(x, [COLOR=#2b91af]GCHandleType[/COLOR].Pinned) 
p = gc.AddrOfPinnedObject()
MsgBox(p)
x = 5
MsgBox(p)
[LEFT][COLOR=black][FONT=Consolas]gc.Free()
[/FONT][/COLOR][/LEFT]
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلام
خیلی ممنون از جوابتون
اما کد زیر نتیجه ای را که میخواهم به من نمی دهد
نمی دانم مشکل کجاست؟
در MsgBox اول باید عدد 12.5 و در دومی باید 5 نمایش داده شود. درسته؟
کد:
[COLOR=black][FONT=Consolas]  [/FONT][/COLOR]
[COLOR=black][FONT=Consolas]      [/FONT][/COLOR][COLOR=blue][FONT=Consolas]Dim[/FONT][/COLOR][COLOR=black][FONT=Consolas] x [/FONT][/COLOR][COLOR=blue][FONT=Consolas]As[/FONT][/COLOR][COLOR=blue][FONT=Consolas]Single[/FONT][/COLOR][COLOR=black][FONT=Consolas] = 12.5
[/FONT][/COLOR][COLOR=blue]Dim[/COLOR] gc [COLOR=blue]As[/COLOR] [COLOR=#2b91af]GCHandle[/COLOR] [/LEFT]
[COLOR=blue]Dim[/COLOR] p [COLOR=blue]As[/COLOR] [COLOR=#2b91af]IntPtr[/COLOR]    
gc = [COLOR=#2b91af]GCHandle[/COLOR].Alloc(x, [COLOR=#2b91af]GCHandleType[/COLOR].Pinned) 
p = gc.AddrOfPinnedObject()
MsgBox(p)
x = 5
MsgBox(p)
[LEFT][COLOR=black][FONT=Consolas]gc.Free()
[/FONT][/COLOR][/LEFT]


نه، شما دارید p یعنی مقدار اشاره گر رو نمایش می دهید، یعنی آدرس حافظه رو. این ربطی به مقداری که در اون آدرس هست و p بهش اشاره می کنه نداره.​
 

ms_vb

Member
خب چطور محتویات آدرسی که p بهش اشاره میکنه رو نمایش بدم؟
 

the_king

مدیرکل انجمن
خب چطور محتویات آدرسی که p بهش اشاره میکنه رو نمایش بدم؟

اگر هدف صرفا خواندن مقدار باشه، ساده است، کد زیر مقداری که p بهش اشاره می کنه رو در (a(0 کپی می کنه و می توانید از آن بخوانید :
کد:
            Dim a(0 To 0) As Single
            Marshal.Copy(p, a, 0, 1)

این مشخصه PtrValue هم می تونه بخونه و هم بنویسه و بهتره که در کدتون همچین چیزی داشته باشید :
کد:
    Private Property PtrValue(ByVal ptr As IntPtr) As Single
        Get
            Dim a(0 To 0) As Single
            Marshal.Copy(ptr, a, 0, 1)
            Return a(0)
        End Get
        Set(ByVal value As Single)
            Dim a() As Single = {value}
            Marshal.Copy(a, 0, ptr, 1)
        End Set
    End Property

مثلا :
کد:
        PtrValue(p) = 12.5

کد:
Dim n As Single = PtrValue(p)

اما به دلیل خصوصیت ذاتی حافظه مدیریت شده در Net. وقتی شما مقدار متغیر x رو تغییر می دهید، حافظه اش جابجا میشه و در نتیجه مقدار p بجای مقدار جدید
همچنان به مقدار قبلی اشاره می کنه، ظاهرا باید 12.5 و 20 نمایش داده بشه اما در عمل 12.5 و 12.5 ئه :
کد:
        Dim x As Single = 12.5
        Dim gc As GCHandle = GCHandle.Alloc(x, GCHandleType.Pinned)
        Dim p As IntPtr = gc.AddrOfPinnedObject
        Dim n As Single = PtrValue(p)
        x += 7.5
        MessageBox.Show(n.ToString() + ", " + PtrValue(p).ToString())
        gc.Free()

چاره اش اینه که بجای حافظه مدیریت شده متغیری مثل x با Marshal.AllocHGlobal حافظه مدیریت نشده تخصیص بدهید :
کد:
        Dim p As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(Single)))
        PtrValue(p) = 12.5
        Dim n As Single = PtrValue(p)
        PtrValue(p) += 7.5
        MessageBox.Show(n.ToString() + ", " + PtrValue(p).ToString())
        Marshal.FreeHGlobal(p)
 

ms_vb

Member
سلام خیلی خیلی ممنون از حوابتون
چاره اش اینه که بجای حافظه مدیریت شده متغیری مثل x با Marshal.AllocHGlobal حافظه مدیریت نشده تخصیص بدهید :
کد:
        Dim p As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(Single)))
        PtrValue(p) = 12.5
        Dim n As Single = PtrValue(p)
        PtrValue(p) += 7.5
        MessageBox.Show(n.ToString() + ", " + PtrValue(p).ToString())
        Marshal.FreeHGlobal(p)

اینجا باید با تغییر مقدار متغیر P مقدار n هم تغییر کنه، درسته؟
چون هر دوی آنها دارند به یک مکان از حافظه اشاره میکنند
اما با تغییر P مقدار n همان 12.5 باقی می ماند

من میخواهم در صورت تغییر مقدار P متغیر n هم تغییر کند یا برعکس

بازهم ممنونم از جوابهای ارزنده و بدرد بخورتون
 

the_king

مدیرکل انجمن
سلام خیلی خیلی ممنون از حوابتون


اینجا باید با تغییر مقدار متغیر P مقدار n هم تغییر کنه، درسته؟
چون هر دوی آنها دارند به یک مکان از حافظه اشاره میکنند
اما با تغییر P مقدار n همان 12.5 باقی می ماند

من میخواهم در صورت تغییر مقدار P متغیر n هم تغییر کند یا برعکس

بازهم ممنونم از جوابهای ارزنده و بدرد بخورتون

p یک اشاره گر است و n یک متغیر داده ای single اما ترتیب سطر های کد را ببینید. مقدار p زمانی مشخص شده که هنوز n ای در کار نیست،
در نتیجه p اگر می خواست هم نمی توانست به n اشاره کند. ما موقتا یک مقدار را در n کپی کرده ایم وگرنه ارتباطی بین p و n نیست.

p به یک حافظه مدیریت نشده اشاره می کنه، نه به حافظه متغیر n . متغیر n از حافظه مدیریت شده Net. استفاده می کنه.
حافظه ای که p بهش اشاره می کنه کاملا مستقل از حافظه مدیریت شده n است و تنها p است که آدرس این حافظه مدیریت نشده رو می دونه،
نوع داده ای که در اون حافظه چند بایتی مدیریت نشده قرار گرفته نامشخصه، حتی p هم نمی دونه که اون داده اعشاری single است. p صرفا موقعیت شروع
حافظه است، خود ما از اون حافظه برای نگهداری داده اعشاری single استفاده کرده ایم اما در واقع اون صرفا چند بایته.

ما متغیر n و سایر متغیر های single را فقط و فقط برای این بکار می بریم که بتوانیم اون چند بایت رو به یک داده اعشاری single تبدیل کنیم وگرنه اون p
اصلا احتیاجی به متغیری مثل n نداره، خودش حافظه مستقلی داره که با Marshal.AllocHGlobal تخصیص دادیم.
اون n صرفا یک واسطه است با یک حافظه مستقل و بی ربط به p ، بین مقدار p و n هیچ رابطه ای وجود نداره.

از اون جایی که متغیر های Net. در حافظه مدیریت شده قرار دارند نمی توانید متغیری مثل n را روی حافظه مدیریت نشده ای که آدرسش در p است تنظیم کنید.
برعکس اش امکان پذیر است، همانطور که در کد ها بود می توانید آدرس یک حافظه مدیریت شده x را در p داشته باشید، اما به محض اینکه مقدار x را تغییر بدهید
آدرس p قبلی ارتباط اش با مقدار جدید x را از دست می دهد. در Net. اشاره گر ها عملا توسط object ها و بر اساس class ها پیاده سازی می شوند،
نه برای انواع داده ای ساده مثل Integer و Single و یا ساختار Struct ها.
 

جدیدترین ارسال ها

بالا