ผ่านการใช้ IntelliSense และดูรหัสของคนอื่นฉันได้เจอกับIntPtr
ประเภทนี้ ทุกครั้งที่จำเป็นต้องใช้ฉันใส่null
หรือIntPtr.Zero
พบฟังก์ชั่นส่วนใหญ่ในการทำงานทุกครั้ง มันคืออะไรกันแน่และเมื่อไร / ทำไมมันถึงใช้?
ผ่านการใช้ IntelliSense และดูรหัสของคนอื่นฉันได้เจอกับIntPtr
ประเภทนี้ ทุกครั้งที่จำเป็นต้องใช้ฉันใส่null
หรือIntPtr.Zero
พบฟังก์ชั่นส่วนใหญ่ในการทำงานทุกครั้ง มันคืออะไรกันแน่และเมื่อไร / ทำไมมันถึงใช้?
คำตอบ:
มันเป็น "จำนวนเต็มขนาดเนทีฟ (เฉพาะแพลตฟอร์ม)" มันแสดงเป็นภายในvoid*
แต่เปิดเผยเป็นจำนวนเต็ม คุณสามารถใช้ทุกครั้งที่คุณต้องการจัดเก็บพอยน์เตอร์ที่ไม่มีการจัดการและไม่ต้องการใช้unsafe
รหัส IntPtr.Zero
ได้อย่างมีประสิทธิภาพNULL
(ตัวชี้โมฆะ)
IntPtr
ทำให้รู้สึกที่สมบูรณ์แบบเพราะมันเป็นจำนวนเต็ม (เช่นเดียวกับในจำนวนเต็มทางคณิตศาสตร์) และตัวชี้ (เช่นเดียวกับในตัวชี้) Int
ส่วนหนึ่งมีน้อยจะทำอย่างไรกับชนิด int - มันเป็นแนวคิดที่ไม่ได้ชนิดที่เฉพาะเจาะจง แม้ว่าจะมีความเป็นธรรมสิ่งเดียวที่สเป็ค CLI พูดเกี่ยวกับมันคือว่ามันเป็น "จำนวนเต็มขนาดดั้งเดิม" โอ้ดี :)
ประเภทของค่ามีขนาดใหญ่พอที่จะเก็บที่อยู่หน่วยความจำตามที่ใช้ในรหัสเนทีฟหรือรหัสที่ไม่ปลอดภัย แต่ไม่สามารถใช้งานโดยตรงเป็นที่อยู่หน่วยความจำในรหัสที่จัดการอย่างปลอดภัย
คุณสามารถใช้IntPtr.Size
เพื่อตรวจสอบว่าคุณกำลังทำงานอยู่ในกระบวนการ 32- บิตหรือ 64- บิตเพราะมันจะเป็น 4 หรือ 8 ไบต์ตามลำดับ
IntPtr
นอกจากนี้ยังใช้เพื่อเป็นตัวแทนจับซึ่งเป็น 32 บิตโดยไม่คำนึงถึงสถาปัตยกรรม ( แต่Size
ยังคงพูดว่า 8 ในกรณีที่) ข้อมูลจำเพาะของ CLI นั้นให้ข้อสังเกตว่ามันเป็นจำนวนเต็มที่มี "ขนาดดั้งเดิม" แต่นั่นไม่ได้พูดอะไรมาก
นี่คือตัวอย่าง:
ฉันกำลังเขียนโปรแกรม C # ที่เชื่อมต่อกับกล้องความเร็วสูง กล้องมีไดรเวอร์ของตัวเองที่รับภาพและโหลดลงในหน่วยความจำของคอมพิวเตอร์สำหรับฉันโดยอัตโนมัติ
ดังนั้นเมื่อฉันพร้อมที่จะนำภาพล่าสุดมาไว้ในโปรแกรมเพื่อทำงานร่วมกับไดรเวอร์กล้องให้ฉันด้วย IntPtr ไปยังตำแหน่งที่เก็บภาพไว้ในหน่วยความจำกายภาพดังนั้นฉันจึงไม่ต้องเสียเวลา / ทรัพยากรในการสร้างอีก บล็อกหน่วยความจำเพื่อเก็บภาพที่อยู่ในหน่วยความจำแล้ว IntPtr แสดงให้ฉันเห็นว่าภาพนั้นอยู่ที่ไหน
IntPtrเป็นจำนวนเต็มซึ่งเป็นขนาดเดียวกับตัวชี้
คุณสามารถใช้ IntPtr เพื่อจัดเก็บค่าตัวชี้ในประเภทที่ไม่ใช่ตัวชี้ คุณลักษณะนี้มีความสำคัญใน. NET เนื่องจากการใช้พอยน์เตอร์มีข้อผิดพลาดสูงและผิดกฎหมายในบริบทส่วนใหญ่ โดยการอนุญาตให้เก็บค่าตัวชี้ในชนิดข้อมูล "ปลอดภัย" การวางท่อประปาระหว่างเซ็กเมนต์รหัสที่ไม่ปลอดภัยอาจถูกนำไปใช้ในรหัสระดับสูงที่ปลอดภัยกว่าหรือแม้แต่ในภาษา. NET ที่ไม่สนับสนุนพอยน์เตอร์โดยตรง
ขนาดของ IntPtr เป็นเฉพาะแพลตฟอร์ม แต่รายละเอียดนี้ไม่ค่อยได้รับการพิจารณาเนื่องจากระบบจะใช้ขนาดที่ถูกต้องโดยอัตโนมัติ
ชื่อ "IntPtr" ทำให้เกิดความสับสน - สิ่งที่คล้ายกันHandle
อาจเหมาะสมกว่า การเดาเริ่มต้นของฉันคือ "IntPtr" เป็นตัวชี้ไปยังจำนวนเต็ม MSDN เอกสารของ IntPtrไปในรายละเอียดค่อนข้างคลุมเครือโดยไม่เคยให้ความเข้าใจมากเกี่ยวกับความหมายของชื่อ
An IntPtr
คือตัวชี้ที่มีข้อ จำกัด สองประการ:
กล่าวอีกนัยหนึ่งIntPtr
คือเหมือนvoid*
- แต่ด้วยคุณสมบัติพิเศษที่สามารถใช้ (แต่ไม่ควร) สำหรับการคำนวณทางคณิตศาสตร์ขั้นพื้นฐาน
เพื่อที่จะ dereference IntPtr
คุณสามารถทิ้งให้เป็นตัวชี้ความจริง (การทำงานที่สามารถดำเนินการเฉพาะในบริบท "ไม่ปลอดภัย" เป็นพิเศษ) หรือคุณสามารถส่งผ่านไปยังผู้ช่วยประจำเช่นผู้ให้บริการโดยInteropServices.Marshal
ระดับ การใช้Marshal
คลาสทำให้เห็นภาพลวงตาของความปลอดภัยเนื่องจากคุณไม่จำเป็นต้องอยู่ในบริบท "ไม่ปลอดภัย" อย่างชัดเจน อย่างไรก็ตามจะไม่ลบความเสี่ยงของการหยุดทำงานซึ่งมีอยู่ในการใช้ตัวชี้
ตัวชี้คืออะไร
ในทุกภาษาตัวชี้เป็นตัวแปรชนิดหนึ่งที่เก็บที่อยู่หน่วยความจำและคุณสามารถขอให้พวกเขาบอกที่อยู่ที่พวกเขาชี้ไปหรือค่าตามที่อยู่ที่ชี้ไป
ตัวชี้สามารถถือเป็นเครื่องหมายของหนังสือได้ ยกเว้นแทนที่จะถูกใช้เพื่อข้ามไปยังหน้าอย่างรวดเร็วในหนังสือตัวชี้จะถูกใช้เพื่อติดตามหรือแมปบล็อกหน่วยความจำ
ลองนึกภาพว่าหน่วยความจำของโปรแกรมของคุณเหมือนกับอาร์เรย์ขนาดใหญ่ 65535 ไบต์
พอยน์เตอร์ชี้อย่างเชื่อฟัง
พอยน์เตอร์จำที่อยู่หน่วยความจำหนึ่งอันแต่ละอันดังนั้นพวกมันจึงชี้ไปยังที่อยู่เดียวในหน่วยความจำ
ในฐานะที่เป็นกลุ่มพอยน์เตอร์จะจดจำและเรียกคืนที่อยู่หน่วยความจำเชื่อฟังคำสั่งโฆษณาทุกคำสั่งของคุณ
คุณคือราชาของพวกเขา
พอยน์เตอร์ใน C #
โดยเฉพาะใน C # ตัวชี้เป็นตัวแปรจำนวนเต็มที่เก็บที่อยู่หน่วยความจำระหว่าง 0 ถึง 65534
เฉพาะกับ C # พอยน์เตอร์เป็นประเภท int และดังนั้นจึงได้ลงนาม
คุณไม่สามารถใช้ที่อยู่ที่มีหมายเลขเป็นลบได้และคุณไม่สามารถเข้าถึงที่อยู่ที่อยู่เหนือ 65534 ความพยายามใด ๆ ที่ทำเช่นนั้นจะเป็นการโยน System.AccessViolationException
ตัวชี้ชื่อMyPointerถูกประกาศอย่างเช่น:
int * MyPointer;
ตัวชี้ใน C # เป็น int แต่ที่อยู่หน่วยความจำใน C # เริ่มต้นที่ 0 และขยายได้ถึง 65534
สิ่งที่ควรได้รับการจัดการด้วยความระมัดระวังเป็นพิเศษ
คำที่ไม่ปลอดภัยมีจุดประสงค์เพื่อทำให้คุณกลัวและด้วยเหตุผลที่ดีมาก: พอยน์เตอร์เป็นสิ่งที่มีประโยชน์และสิ่งที่มีความสำคัญเช่นดาบขวานพอยน์เตอร์ ฯลฯ ควรได้รับการดูแลเป็นพิเศษ
พอยน์เตอร์ให้โปรแกรมเมอร์ควบคุมระบบอย่างเข้มงวด ดังนั้นความผิดพลาดที่เกิดขึ้นมีแนวโน้มที่จะเกิดผลกระทบที่ร้ายแรงกว่า
ในการใช้พอยน์เตอร์จะต้องเปิดใช้งานรหัสที่ไม่ปลอดภัยในคุณสมบัติของโปรแกรมของคุณและต้องใช้พอยน์เตอร์ในวิธีหรือบล็อกที่ทำเครื่องหมายว่าไม่ปลอดภัยเท่านั้น
ตัวอย่างของบล็อกที่ไม่ปลอดภัย
unsafe
{
// Place code carefully and responsibly here.
}
วิธีใช้พอยน์เตอร์
เมื่อตัวแปรหรือวัตถุถูกประกาศหรือยกตัวอย่างพวกมันจะถูกเก็บไว้ในหน่วยความจำ
int *MyPointer;
MyPointer = &MyVariable;
เมื่อกำหนดที่อยู่ให้กับตัวชี้แล้วจะใช้ข้อมูลต่อไปนี้:
MyPointer = &MyVariable; // Set MyPointer to point at MyVariable
"MyPointer is pointing at " + *MyPointer;
เนื่องจากตัวชี้เป็นตัวแปรที่เก็บที่อยู่หน่วยความจำที่อยู่หน่วยความจำนี้จึงสามารถเก็บไว้ในตัวแปรตัวชี้ได้
ตัวอย่างของพอยน์เตอร์ที่ใช้อย่างระมัดระวังและมีความรับผิดชอบ
public unsafe void PointerTest()
{
int x = 100; // Create a variable named x
int *MyPointer = &x; // Store the address of variable named x into the pointer named MyPointer
textBox1.Text = ((int)MyPointer).ToString(); // Displays the memory address stored in pointer named MyPointer
textBox2.Text = (*MyPointer).ToString(); // Displays the value of the variable named x via the pointer named MyPointer.
}
ขอให้สังเกตว่าประเภทของตัวชี้เป็น int นี่เป็นเพราะ C # ตีความหน่วยความจำที่อยู่เป็นตัวเลขจำนวนเต็ม (int)
ทำไมถึงเป็น int แทนที่จะเป็น uint
ไม่มีเหตุผลที่ดี
ทำไมต้องใช้พอยน์เตอร์?
พอยน์เตอร์มีความสนุกสนานมากมาย ด้วยคอมพิวเตอร์ส่วนใหญ่ที่ถูกควบคุมโดยหน่วยความจำพอยน์เตอร์จะให้อำนาจโปรแกรมเมอร์ที่มีการควบคุมหน่วยความจำของโปรแกรมมากขึ้น
การตรวจสอบหน่วยความจำ
ใช้พอยน์เตอร์เพื่ออ่านบล็อกของหน่วยความจำและตรวจสอบว่าค่าที่ชี้ไปนั้นเปลี่ยนแปลงตลอดเวลาอย่างไร
เปลี่ยนค่าเหล่านี้อย่างรับผิดชอบและติดตามว่าการเปลี่ยนแปลงของคุณมีผลกับคอมพิวเตอร์อย่างไร
65534
ดูเหมือนว่าผิดมากในช่วงตัวชี้ คุณควรให้ข้อมูลอ้างอิง
System.IntPtr
คำถามคือเกี่ยวกับ ฉันอยากจะเห็นคำตอบที่ได้รับการปรับปรุงในตอนท้ายอธิบายว่าอะไรบ้างSystem.IntPtr
และเกี่ยวข้องกับพอยน์เตอร์ที่ไม่ปลอดภัยใน C # ได้ไหม
MSDN บอกเรา:
ประเภท IntPtr ได้รับการออกแบบให้เป็นจำนวนเต็มที่มีขนาดเฉพาะแพลตฟอร์ม นั่นคืออินสแตนซ์ของประเภทนี้คาดว่าจะเป็น 32- บิตบนฮาร์ดแวร์และระบบปฏิบัติการ 32- บิตและ 64- บิตบนฮาร์ดแวร์และระบบปฏิบัติการ 64- บิต
ประเภท IntPtr สามารถใช้งานได้โดยภาษาที่สนับสนุนพอยน์เตอร์และเป็นวิธีการทั่วไปในการอ้างถึงข้อมูลระหว่างภาษาที่ไม่สนับสนุนพอยน์เตอร์
วัตถุ IntPtr ยังสามารถใช้เพื่อจับที่จับ ตัวอย่างเช่นอินสแตนซ์ของ IntPtr มีการใช้อย่างกว้างขวางในคลาส System.IO.FileStream เพื่อจัดการไฟล์
ประเภท IntPtr เป็นไปตาม CLS ในขณะที่ประเภท UIntPtr ไม่ได้เป็น เฉพาะชนิด IntPtr ที่ใช้ในรันไทม์ภาษาทั่วไป ประเภท UIntPtr นั้นส่วนใหญ่มีไว้เพื่อรักษาความสมมาตรทางสถาปัตยกรรมด้วยประเภท IntPtr
http://msdn.microsoft.com/en-us/library/system.intptr(VS.71).aspx
อย่างนี้เป็นหน้า MSDNIntPtr
ที่เกี่ยวข้องกับ
บรรทัดแรกอ่าน:
ชนิดเฉพาะแพลตฟอร์มที่ใช้เพื่อแทนตัวชี้หรือหมายเลขอ้างอิง
สำหรับสิ่งที่ตัวชี้หรือหมายเลขอ้างอิงเป็นหน้าไปสู่สถานะ:
ประเภท IntPtr สามารถใช้งานได้โดยภาษาที่สนับสนุนพอยน์เตอร์และเป็นวิธีการทั่วไปในการอ้างถึงข้อมูลระหว่างภาษาที่ไม่สนับสนุนพอยน์เตอร์
วัตถุ IntPtr ยังสามารถใช้เพื่อจับที่จับ ตัวอย่างเช่นอินสแตนซ์ของ IntPtr มีการใช้อย่างกว้างขวางในคลาส System.IO.FileStream เพื่อจัดการไฟล์
ตัวชี้เป็นการอ้างอิงไปยังพื้นที่ของหน่วยความจำที่เก็บข้อมูลบางอย่างที่คุณสนใจ
หมายเลขอ้างอิงสามารถเป็นตัวระบุสำหรับวัตถุและส่งผ่านระหว่างวิธี / คลาสเมื่อทั้งสองฝ่ายจำเป็นต้องเข้าถึงวัตถุนั้น
An IntPtr
เป็นประเภทค่าที่ใช้เพื่อเก็บที่อยู่หน่วยความจำหรือที่จับเป็นหลัก ชี้ที่อยู่ในหน่วยความจำ ตัวชี้สามารถพิมพ์ (เช่นint*
) หรือ untyped (เช่นvoid*
) ของ Windows จับเป็นค่าที่มักจะมีขนาดเท่ากัน (หรือขนาดเล็กกว่า) ที่อยู่หน่วยความจำและแสดงให้เห็นถึงระบบทรัพยากร (เช่นไฟล์หรือหน้าต่าง)