Bagikan melalui


Operator terkait pointer - ambil alamat variabel, lokasi penyimpanan dereferensi, dan lokasi memori akses

Operator pointer memungkinkan Anda untuk mengambil alamat variabel (&), dereferensi pointer (*), membandingkan nilai pointer, dan menambahkan atau mengurangi pointer dan bilangan bulat.

Referensi bahasa C# mendokumentasikan versi bahasa C# yang paling baru dirilis. Ini juga berisi dokumentasi awal untuk fitur dalam pratinjau publik untuk rilis bahasa yang akan datang.

Dokumentasi mengidentifikasi fitur apa pun yang pertama kali diperkenalkan dalam tiga versi terakhir bahasa atau dalam pratinjau publik saat ini.

Petunjuk / Saran

Untuk menemukan kapan fitur pertama kali diperkenalkan di C#, lihat artikel tentang riwayat versi bahasa C#.

Gunakan operator berikut untuk bekerja dengan pointer:

Untuk informasi tentang jenis penunjuk, lihat Jenis penunjuk.

Catatan

Setiap operasi dengan pointer memebutuhkan konteks yang tidak aman. Anda harus mengkompilasi kode yang berisi blok yang tidak aman dengan opsi pengkompilasi AllowUnsafeBlocks .

Alamat operator &

Operator unary & mengembalikan alamat operandnya:

unsafe
{
    int number = 27;
    int* pointerToNumber = &number;

    Console.WriteLine($"Value of the variable: {number}");
    Console.WriteLine($"Address of the variable: {(long)pointerToNumber:X}");
}
// Output is similar to:
// Value of the variable: 27
// Address of the variable: 6C1457DBD4

Operand dari operator & harus berupa variabel tetap. Variabel tetap adalah variabel yang berada di lokasi penyimpanan yang tidak terpengaruh oleh pengumpul sampah . Dalam contoh sebelumnya, variabel number lokal adalah variabel tetap karena berada di tumpukan. Variabel yang berada di lokasi penyimpanan yang dapat dipengaruhi pengumpul sampah (misalnya, relokasi) disebut variabel yang dapat bergerak. Bidang objek dan elemen array adalah contoh variabel yang dapat dipindahkan. Anda bisa mendapatkan alamat variabel bergerak jika Anda "memperbaiki", atau "menyematkannya", dengan menggunakan fixed pernyataan. Alamat yang diperoleh hanya valid di dalam blok pernyataan fixed. Contoh berikut menunjukkan cara menggunakan pernyataan fixed dan operator &:

unsafe
{
    byte[] bytes = { 1, 2, 3 };
    fixed (byte* pointerToFirst = &bytes[0])
    {
        // The address stored in pointerToFirst
        // is valid only inside this fixed statement block.
    }
}

Anda tidak dapat mendapatkan alamat konstanta atau nilai.

Untuk informasi lebih lengkap tentang variabel tetap dan bergerak, lihat bagian Variabel tetap dan dapat dipindahkan dari spesifikasi bahasa C#.

Operator biner & menghitung logis AND dari operan Boolean atau logis bitwise AND dari operan integral.

Operator penunjuk arah *

Operator * tidak langsung penunjuk unary mengakses variabel yang titik operand-nya. Ini juga dikenal sebagai operator dereference. Pengoperasi dari operand * harus berjenis pointer.

unsafe
{
    char letter = 'A';
    char* pointerToLetter = &letter;
    Console.WriteLine($"Value of the `letter` variable: {letter}");
    Console.WriteLine($"Address of the `letter` variable: {(long)pointerToLetter:X}");

    *pointerToLetter = 'Z';
    Console.WriteLine($"Value of the `letter` variable after update: {letter}");
}
// Output is similar to:
// Value of the `letter` variable: A
// Address of the `letter` variable: DCB977DDF4
// Value of the `letter` variable after update: Z

Anda tidak dapat menerapkan operator ke * ekspresi jenis void*.

Operator biner *menghitung produk dari operan numeriknya.

Operator akses anggota pointer ->

Operator -> menggabungkan pointer tidak langsung dan akses anggota. Jika x adalah penunjuk jenis T* dan y merupakan anggota tipe Tyang dapat diakses , ekspresi formulir

x->y

setara dengan:

(*x).y

Contoh berikut menunjukkan penggunaan operator ->:

public struct Coords
{
    public int X;
    public int Y;
    public override string ToString() => $"({X}, {Y})";
}

public class PointerMemberAccessExample
{
    public static unsafe void Main()
    {
        Coords coords;
        Coords* p = &coords;
        p->X = 3;
        p->Y = 4;
        Console.WriteLine(p->ToString());  // output: (3, 4)
    }
}

Anda tidak dapat menggunakan -> operator pada ekspresi jenis void*.

Operator akses elemen pointer []

Untuk ekspresi p jenis penunjuk, akses elemen penunjuk formulir p[n] dievaluasi sebagai *(p + n). Nilai n harus dari jenis yang secara implisit dapat dikonversi ke int, , uintlong, atau ulong. Untuk informasi tentang perilaku operator + dengan pointer, lihat bagian Penambahan atau pengurangan nilai integral ke atau dari penunjuk.

Contoh berikut menunjukkan cara mengakses elemen array dengan menggunakan pointer dan [] operator:

unsafe
{
    char* pointerToChars = stackalloc char[123];

    for (int i = 65; i < 123; i++)
    {
        pointerToChars[i] = (char)i;
    }

    Console.Write("Uppercase letters: ");
    for (int i = 65; i < 91; i++)
    {
        Console.Write(pointerToChars[i]);
    }
}
// Output:
// Uppercase letters: ABCDEFGHIJKLMNOPQRSTUVWXYZ

Dalam contoh sebelumnya, stackalloc ekspresi mengalokasikan blok memori pada tumpukannya.

Catatan

Operator akses elemen penunjuk tidak memeriksa kesalahan di luar batas.

Anda tidak dapat menggunakan [] untuk akses elemen penunjuk dengan ekspresi jenis void*.

Anda juga bisa menggunakan [] operator untuk elemen array atau akses pengindeks.

Operator aritmetika dasar

Anda bisa melakukan operasi aritmatika berikut dengan penunjuk:

  • Menambah atau mengurangi nilai integral ke atau dari penunjuk
  • Kurangilah dua pointer
  • Menambah atau mengurangi pointer

Anda tidak dapat melakukan operasi tersebut dengan penunjuk jenis void*.

Untuk informasi tentang operasi aritmatika yang didukung dengan menggunakan jenis numerik, lihat Operator aritmatika.

Menambah atau mengurangi nilai integral ke atau dari penunjuk

Untuk penunjuk p jenis T* dan ekspresi n jenis yang secara implisit dapat dikonversi ke int, , uint, longatau ulong, penambahan dan pengurangan berfungsi sebagai berikut:

  • Keduanya p + n dan n + p memberi Anda penunjuk jenis T*. Anda mendapatkan pointer ini dengan menambahkan n * sizeof(T) ke alamat yang p menunjuk ke.
  • p - n Ekspresi memberi Anda penunjuk jenis T*. Anda mendapatkan pointer ini dengan mengurangi n * sizeof(T) dari alamat yang p menunjuk ke.

Operatorsizeof mendapatkan ukuran jenis dalam byte.

Contoh berikut menunjukkan cara menggunakan + operator dengan penunjuk:

unsafe
{
    const int Count = 3;
    int[] numbers = new int[Count] { 10, 20, 30 };
    fixed (int* pointerToFirst = &numbers[0])
    {
        int* pointerToLast = pointerToFirst + (Count - 1);

        Console.WriteLine($"Value {*pointerToFirst} at address {(long)pointerToFirst}");
        Console.WriteLine($"Value {*pointerToLast} at address {(long)pointerToLast}");
    }
}
// Output is similar to:
// Value 10 at address 1818345918136
// Value 30 at address 1818345918144

Pengurangan pointer

Untuk dua pointer p1 dan p2 jenis T*, ekspresi p1 - p2 memberi Anda perbedaan antara alamat yang p1 dan p2 menunjuk ke, dibagi dengan sizeof(T). Hasilnya adalah jenis long. Dengan kata lain, p1 - p2 dihitung sebagai ((long)(p1) - (long)(p2)) / sizeof(T).

Contoh berikut menunjukkan pengurangan penunjuk:

unsafe
{
    int* numbers = stackalloc int[] { 0, 1, 2, 3, 4, 5 };
    int* p1 = &numbers[1];
    int* p2 = &numbers[5];
    Console.WriteLine(p2 - p1);  // output: 4
}

Kenaikan dan penurunan pointer

++ Operator kenaikan menambahkan 1 ke operand pointernya. --Operator penurunan mengurangi 1 dari operan penunjuknya.

Kedua operator mendukung dua bentuk: postfix (p++ dan p--) dan awalan (++p dan --p). Hasil dan p++p-- adalah nilai psebelum operasi. Hasil dan ++p--p adalah nilai psetelah operasi.

Contoh berikut ini menunjukkan perilaku operator peningkatan postfix dan prefiks:

unsafe
{
    int* numbers = stackalloc int[] { 0, 1, 2 };
    int* p1 = &numbers[0];
    int* p2 = p1;
    Console.WriteLine($"Before operation: p1 - {(long)p1}, p2 - {(long)p2}");
    Console.WriteLine($"Postfix increment of p1: {(long)(p1++)}");
    Console.WriteLine($"Prefix increment of p2: {(long)(++p2)}");
    Console.WriteLine($"After operation: p1 - {(long)p1}, p2 - {(long)p2}");
}
// Output is similar to
// Before operation: p1 - 816489946512, p2 - 816489946512
// Postfix increment of p1: 816489946512
// Prefix increment of p2: 816489946516
// After operation: p1 - 816489946516, p2 - 816489946516

Operator perbandingan penunjuk

Anda dapat menggunakan operator ==, !=, <, >, <=, dan >= untuk membandingkan operan jenis penunjuk apa pun, termasuk void*. Operator ini membandingkan alamat yang diberikan oleh dua operan seolah-olah mereka bilangan bulat yang tidak ditandatangani.

Untuk informasi tentang perilaku operator tersebut untuk operan jenis lain, lihat artikel Operator persamaan dan operator Perbandingan.

Prioritas operator

Daftar berikut mengurutkan operator bitwise dan shift mulai dari prioritas tertinggi ke terendah:

  • Operator kenaikan x++ dan penurunan x-- postfix dan operator -> dan []
  • Operator kenaikan ++x dan penurunan --x awalan dan operator & dan *
  • Operator tambahan + dan -
  • Perbandingan operator <, >, <=, dan >=
  • Persamaan == dan != operator

Gunakan tanda kurung, (), untuk mengubah urutan evaluasi yang diberlakukan oleh prioritas operator.

Untuk daftar lengkap operator C# yang diurutkan berdasarkan tingkat prioritas, lihat bagian Prioritas operator dari artikel operator C#.

Kelebihan beban operator

Anda tidak dapat membebani operator &terkait pointer , , *, ->dan [] dalam jenis yang ditentukan pengguna.

Spesifikasi bahasa C#

Untuk informasi selengkapnya, lihat bagian berikut dari spesifikasi bahasa C#:

Lihat juga