Apa sebenarnya IntPtr itu?


171

Melalui menggunakan IntelliSense dan melihat kode orang lain, saya telah menemukan IntPtrtipe ini ; setiap kali itu perlu digunakan, saya hanya menempatkan nullatau IntPtr.Zerodan menemukan sebagian besar fungsi untuk bekerja. Apa sebenarnya itu dan kapan / mengapa digunakan?

Jawaban:


158

Ini adalah "integer ukuran asli (khusus platform)". Ini direpresentasikan secara internal void*tetapi diekspos sebagai bilangan bulat. Anda dapat menggunakannya kapan pun Anda perlu menyimpan pointer yang tidak dikelola dan tidak ingin menggunakan unsafekode. IntPtr.Zerosecara efektif NULL(pointer nol).


53
Pointer adalah sesuatu yang menunjuk ke suatu alamat dalam memori. Dalam bahasa yang dikelola Anda memiliki referensi (alamat dapat berpindah-pindah) sementara dalam bahasa yang tidak dikelola Anda memiliki petunjuk (alamat tetap)
Colin Mackay

93
Secara umum (lintas bahasa pemrograman), penunjuk adalah angka yang mewakili lokasi fisik dalam memori. Sebuah null pointer adalah (hampir selalu) salah satu yang menunjuk ke 0, dan secara luas diakui sebagai "tidak menunjuk ke apa pun". Karena sistem memiliki jumlah memori yang didukung berbeda, tidak selalu memerlukan jumlah byte yang sama untuk menampung angka itu, jadi kami memanggil "integer ukuran asli" yang dapat menyimpan pointer pada sistem tertentu.
Sam Harwell

5
+1 untuk komentar itu @ 280Z28, itu adalah penjelasan paling ringkas tentang petunjuk yang pernah saya lihat.
BlueRaja - Danny Pflughoeft

9
Ini disebut IntPtr, karena untuk menggunakannya dari kode asli yang tidak dikelola, C / C ++, Anda harus menggunakan tipe analog: intptr_t. IntPtr C # memetakan dengan tepat ke intptr_t C / C ++. Dan itu mungkin diimplementasikan sebagai intptr_t. Dalam C / C ++, tipe intptr_t dijamin dengan ukuran yang sama dengan tipe void *.
Петър Петров

2
@Trap "Tipe platform khusus yang digunakan untuk mewakili pointer atau handle." Bukan "integer khusus platform", "cara khusus platform untuk mewakili pointer atau handle". IntPtrmasuk akal, karena itu adalah bilangan bulat (seperti dalam bilangan bulat matematika) dan sebuah pointer (seperti dalam pointer). Bagian Intini tidak ada hubungannya dengan tipe int - ini adalah konsep, bukan tipe spesifik. Meskipun untuk bersikap adil, satu-satunya spek CLI mengatakan tentang itu adalah bahwa itu memang "bilangan bulat, asli". Oh well :)
Luaan

69

Ini adalah tipe nilai yang cukup besar untuk menyimpan alamat memori seperti yang digunakan dalam kode asli atau tidak aman, tetapi tidak secara langsung dapat digunakan sebagai alamat memori dalam kode yang dikelola dengan aman.

Anda dapat menggunakan IntPtr.Sizeuntuk mengetahui apakah Anda menjalankan proses 32-bit atau 64-bit, karena masing-masing akan menjadi 4 atau 8 byte.


16
Poin bagus tentang mendeteksi ukuran ruang alamat untuk proses tersebut.
Noldorin

@Noldorin Benar, tetapi belum tentu dapat diandalkan. Di masa lalu, ada banyak arsitektur yang memiliki beberapa jenis pointer, dan pada Windows, IntPtrjuga digunakan untuk mewakili pegangan yang 32-bit terlepas dari arsitektur (meskipun Sizemasih mengatakan 8 dalam kasus itu). Spesifikasi CLI hanya mencatat bahwa itu adalah bilangan bulat yang "asli ukuran", tetapi itu tidak banyak bicara, sungguh.
Luaan

@Luaan itu tidak benar-benar mengubah apa pun dalam jawaban saya, bukan? IntPtr disebut (dan digunakan di seluruh sumber CLR) sebagai nilai yang cukup besar untuk menampung alamat memori. Itu bisa memiliki nilai yang lebih kecil tentunya. Beberapa arsitektur memiliki beberapa tipe penunjuk, tetapi harus memiliki satu yang terbesar dari himpunan.
Daniel Earwicker

@DanielEarwicker Yah, itu tidak masalah dengan implementasi .NET saat ini, sejauh yang saya tahu. Namun, masalah (historis) bukan hanya tentang ukuran - berbagai petunjuk mungkin sepenuhnya tidak kompatibel. Dalam contoh yang lebih dekat dengan hari ini, PAE akan menggunakan alamat 64-bit meskipun "ukuran pointer asli" masih 32-bit. Semua kembali ke argumen "apa artinya 'sistem 32-bit', sebenarnya?" Kami memiliki register numerik 256-bit dan 512-bit sekarang, tetapi masih menyebutnya 64-bit. Meskipun Anda tidak dapat benar - benar mengatasi memori fisik 64-bit dengan "pointer" 64-bit Anda. Ini berantakan.
Luaan

1
Beberapa di antaranya rumit, tetapi IntPtr masih "tipe nilai yang cukup besar untuk menyimpan alamat memori". Tidak sebesar register perangkat keras terbesar, untuk mengambil salah satu contoh Anda. Bukan hanya itu untuk apa. Cukup besar untuk mewakili alamat memori. Lalu ada hal-hal seperti ini: stackoverflow.com/questions/12006854/... di mana kita memiliki kata "pointer" yang digunakan untuk sesuatu selain alamat memori - itulah sebabnya saya secara khusus mengatakan "alamat memori".
Daniel Earwicker

48

Ini sebuah contoh:

Saya sedang menulis program C # yang berinteraksi dengan kamera kecepatan tinggi. Kamera memiliki driver sendiri yang memperoleh gambar dan memuatnya ke dalam memori komputer untuk saya secara otomatis.

Jadi ketika saya siap untuk membawa gambar terbaru ke dalam program saya untuk bekerja dengan, driver kamera memberi saya IntPtr ke tempat gambar SUDAH disimpan dalam memori fisik, jadi saya tidak perlu membuang waktu / sumber daya membuat yang lain blok memori untuk menyimpan gambar yang sudah ada dalam memori. IntPtr hanya menunjukkan kepada saya di mana gambar sudah.


7
Jadi IntPtr sederhana memungkinkan Anda untuk menggunakan pointer yang tidak dikelola (seperti yang digunakan pada driver kamera Anda) dalam kode terkelola?
Callum Rogers

5
Iya. Nah dalam kasus ini, kemungkinan besar driver kamera menggunakan driver yang tidak dikelola di bawah kap, tetapi untuk beroperasi dengan baik di dunia Managed-only ini memberikan IntPtr untuk memungkinkan saya bekerja dengan data dengan aman.
bufferz

3
Jadi mengapa itu tidak hanya memberi Anda kembali aliran (byte array)? Mengapa tidak aman atau tidak dapat mengembalikan nilai?
The Muffin Man

35

Penafsiran langsung

Sebuah IntPtr adalah bilangan bulat yang merupakan ukuran yang sama sebagai pointer .

Anda dapat menggunakan IntPtr untuk menyimpan nilai pointer dalam tipe non-pointer. Fitur ini penting dalam. NET karena menggunakan pointer sangat rawan kesalahan dan karenanya ilegal dalam sebagian besar konteks. Dengan membiarkan nilai pointer disimpan dalam tipe data "aman", masukkan antara yang tidak aman segmen kode yang dapat diimplementasikan dalam kode tingkat tinggi yang lebih aman - atau bahkan dalam bahasa .NET yang tidak secara langsung mendukung pointer.

Ukuran IntPtr khusus untuk platform, tetapi detail ini jarang perlu dipertimbangkan, karena sistem akan secara otomatis menggunakan ukuran yang benar.

Nama "IntPtr" membingungkan - sesuatu seperti Handlemungkin lebih tepat. Dugaan awal saya adalah "IntPtr" adalah pointer ke integer. The MSDN dokumentasi IntPtr masuk ke detail agak samar tanpa pernah memberikan banyak wawasan tentang arti nama.

Perspektif alternatif

An IntPtradalah pointer dengan dua batasan:

  1. Itu tidak bisa secara langsung direferensikan
  2. Ia tidak tahu tipe data yang ditunjuknya.

Dengan kata lain, sebuah IntPtrseperti void*- tetapi dengan fitur tambahan yang dapat (tetapi tidak seharusnya) digunakan untuk aritmatika pointer dasar.

Untuk melakukan dereferensi IntPtr, Anda dapat melemparkannya ke pointer yang benar (operasi yang hanya dapat dilakukan dalam konteks "tidak aman") atau Anda dapat meneruskannya ke rutinitas pembantu seperti yang disediakan oleh InteropServices.Marshalkelas. Menggunakan Marshalkelas memberikan ilusi keselamatan karena tidak mengharuskan Anda berada dalam konteks eksplisit "tidak aman". Namun, itu tidak menghapus risiko menabrak yang melekat dalam penggunaan pointer.


2
Ada beberapa preseden untuk nama "intptr" dari standar C99 dari bahasa pemrograman "C". linux.die.net/man/3/intptr_t .
Brent Bradburn

17

Apa itu Pointer?

Dalam semua bahasa, penunjuk adalah jenis variabel yang menyimpan alamat memori, dan Anda bisa meminta mereka untuk memberi tahu Anda alamat yang mereka tunjuk atau nilai pada alamat yang mereka tunjuk.

Pointer dapat dianggap sebagai semacam tanda buku. Kecuali, alih-alih digunakan untuk melompat dengan cepat ke halaman dalam buku, pointer digunakan untuk melacak atau memetakan blok memori.

Bayangkan memori program Anda persis seperti satu array besar 65535 byte.

Pointer menunjuk dengan patuh

Pointer masing-masing mengingat satu alamat memori, dan karenanya masing-masing menunjuk ke satu alamat dalam memori.

Sebagai sebuah grup, pointer mengingat dan mengingat alamat memori, mematuhi setiap perintah dan mual Anda.

Anda adalah raja mereka.

Pointer dalam C #

Khususnya dalam C #, pointer adalah variabel integer yang menyimpan alamat memori antara 0 dan 65534.

Juga spesifik untuk C #, pointer bertipe int dan karenanya ditandatangani.

Anda tidak dapat menggunakan alamat bernomor negatif, Anda juga tidak dapat mengakses alamat di atas 65534. Upaya apa pun untuk melakukannya akan melempar System.AccessViolationException.

Pointer bernama MyPointer dinyatakan seperti ini:

int * MyPointer;

Pointer di C # adalah sebuah int, tetapi alamat memori di C # mulai dari 0 dan diperluas hingga 65534.

Hal-hal yang runcing harus ditangani dengan perawatan khusus

Kata tidak aman adalah dimaksudkan untuk menakut-nakuti Anda, dan untuk alasan yang sangat baik: Pointer adalah hal-hal runcing, dan hal runcing misalnya pedang, kapak, pointer, dll harus ditangani dengan perawatan khusus ekstra.

Pointer memberi programmer kontrol ketat terhadap suatu sistem. Karena itu kesalahan yang dilakukan cenderung memiliki konsekuensi yang lebih serius.

Untuk menggunakan pointer, kode tidak aman harus diaktifkan di properti program Anda, dan pointer harus digunakan secara eksklusif dalam metode atau blok yang ditandai sebagai tidak aman.

Contoh blok yang tidak aman

unsafe
{
    // Place code carefully and responsibly here.

}

Cara menggunakan Pointer

Ketika variabel atau objek dideklarasikan atau dipakai, mereka disimpan dalam memori.

  • Deklarasikan pointer dengan menggunakan awalan simbol *.

int *MyPointer;

  • Untuk mendapatkan alamat variabel, Anda menggunakan awalan & simbol.

MyPointer = &MyVariable;

Setelah alamat ditetapkan ke pointer, hal berikut ini berlaku:

  • Tanpa * awalan untuk merujuk ke alamat memori yang ditunjuk sebagai int.

MyPointer = &MyVariable; // Set MyPointer to point at MyVariable

  • Dengan * awalan untuk mendapatkan nilai yang tersimpan di alamat memori yang ditunjuk.

"MyPointer is pointing at " + *MyPointer;

Karena pointer adalah variabel yang menyimpan alamat memori, alamat memori ini dapat disimpan dalam variabel pointer.

Contoh pointer digunakan dengan hati-hati dan bertanggung jawab

    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.

    }

Perhatikan jenis pointer adalah int. Ini karena C # mengartikan alamat memori sebagai angka integer (int).

Mengapa itu int bukan uint?

Tidak ada alasan bagus.

Mengapa menggunakan pointer?

Pointer sangat menyenangkan. Dengan begitu banyak komputer yang dikendalikan oleh memori, pointer memberdayakan seorang programmer dengan lebih banyak kontrol memori program mereka.

Pemantauan memori.

Gunakan pointer untuk membaca blok memori dan memantau bagaimana nilai-nilai yang ditunjukkan berubah seiring waktu.

Ubah nilai-nilai ini secara bertanggung jawab dan catat bagaimana perubahan Anda memengaruhi komputer Anda.


2
65534tampaknya sangat salah sebagai rentang pointer. Anda harus memberikan referensi.
Brent Bradburn

1
Saya memilih ini karena ini adalah artikel yang bagus menjelaskan petunjuk. Saya ingin melihat beberapa referensi untuk spesifikasi yang telah Anda sebutkan (seperti yang dikomentari di atas). Namun; jawaban ini tidak ada hubungannya dengan pertanyaan. Pertanyaannya adalah tentang System.IntPtr. Saya ingin melihat jawaban diperbarui di akhir menjelaskan apa juga System.IntPtrdan bagaimana hubungannya dengan pointer tidak aman di C # tolong.
Michael Puckett II

7

MSDN memberi tahu kami:

Jenis IntPtr dirancang untuk menjadi bilangan bulat yang ukurannya khusus untuk platform. Yaitu, instance dari tipe ini diharapkan 32-bit pada perangkat keras dan sistem operasi 32-bit, dan 64-bit pada perangkat keras dan sistem operasi 64-bit.

Jenis IntPtr dapat digunakan oleh bahasa yang mendukung pointer, dan sebagai cara umum untuk merujuk ke data antara bahasa yang melakukan dan tidak mendukung pointer.

Objek IntPtr juga dapat digunakan untuk memegang gagang. Sebagai contoh, contoh IntPtr digunakan secara luas di kelas System.IO.FileStream untuk memegang file menangani.

Tipe IntPtr adalah CLS-compliant, sedangkan tipe UIntPtr tidak. Hanya tipe IntPtr yang digunakan dalam runtime bahasa umum. Tipe UIntPtr disediakan sebagian besar untuk menjaga simetri arsitektur dengan tipe IntPtr.

http://msdn.microsoft.com/en-us/library/system.intptr(VS.71).aspx


5

Yah ini adalah halaman MSDN yang berhubungan dengan IntPtr.

Baris pertama berbunyi:

Jenis platform khusus yang digunakan untuk mewakili pointer atau pegangan.

Sehubungan dengan pointer atau handle, halaman selanjutnya menyatakan:

Jenis IntPtr dapat digunakan oleh bahasa yang mendukung pointer, dan sebagai cara umum untuk merujuk ke data antara bahasa yang melakukan dan tidak mendukung pointer.

Objek IntPtr juga dapat digunakan untuk memegang gagang. Sebagai contoh, contoh IntPtr digunakan secara luas di kelas System.IO.FileStream untuk memegang file menangani.

Pointer adalah referensi ke area memori yang menyimpan beberapa data yang Anda minati.

Pegangan dapat menjadi pengidentifikasi untuk objek dan diteruskan antara metode / kelas ketika kedua belah pihak perlu mengakses objek itu.


2

Sebuah IntPtradalah jenis nilai yang terutama digunakan untuk alamat memori memegang atau menangani. Sebuah pointer adalah alamat memori. Pointer dapat diketik (mis. int*) Atau tidak diketik (mis void*.). Sebuah Windows pegangan adalah nilai yang biasanya ukuran yang sama (atau lebih kecil) dari alamat memori dan merupakan sistem sumber daya (seperti file atau jendela).

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.