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.

Anda menggunakan operator berikut untuk bekerja dengan pointer:

Untuk informasi tentang jenis penunjuk, lihat Jenis penunjuk.

Catatan

Setiap operasi dengan pointer memebutuhkan konteks yang tidak aman. Kode yang berisi blok tidak aman harus dikompilasi dengan opsi compiler 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 pengoperasian pengumpul sampah. Di Dalam contoh sebelumnya, variabel number lokal adalah variabel tetap, karena berada di tumpukan. Variabel yang berada di lokasi penyimpanan yang dapat dipengaruhi oleh pengumpul sampah (misalnya, direlokasi) disebut dengan variabel yang dapat dipindahkan. Bidang objek dan elemen array adalah contoh variabel yang dapat dipindahkan. Anda bisa mendapatkan alamat variabel yang dapat dipindahkan jika Anda "memperbaiki", atau "pin", itu dengan 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 pointer unary * memperoleh variabel yang ditunjuk oleh operandnya. 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. Artinya jika x adalah penunjuk jenis T* dan y merupakan anggota jenis T yang 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 menerapkan operator ke -> ekspresi jenis void*.

Operator akses elemen pointer []

Untuk ekspresi p dari jenis penunjuk, akses elemen penunjuk dari formulir p[n] dievaluasi sebagai *(p + n), di mana n harus dari jenis yang secara implisit dapat dikonversi ke int, uint, long, 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 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 oleh jenis numerik, lihat Operator aritmatika.

Penambahan atau pengurangan nilai integral ke atau dari pointer

Untuk penunjuk p tipe T* dan ekspresi n tipe yang secara implisit dapat dikonversi menjadi int, uint, long, atau ulong, penambahan dan pengurangan didefinisikan sebagai berikut:

  • Kedua ekspresi p + n dan n + p menghasilkan penunjuk jenis T* yang dihasilkan dari penambahan n * sizeof(T) ke alamat yang diberikan oleh p.
  • p - n Ekspresi menghasilkan penunjuk jenis T* yang dihasilkan dari pengurangan n * sizeof(T) dari alamat yang diberikan oleh p.

Operatorsizeof mendapatkan ukuran jenis dalam byte.

Contoh berikut menunjukkan penggunaan operator +:

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 kedua pointer p1 dan p2 jenis T*, ekspresi p1 - p2 menghasilkan perbedaan antara alamat yang diberikan oleh p1 dan p2 dibagi dengan sizeof(T). Jenis hasilnya adalah long. Artinya, p1 - p2 bisa dihitung sebagai ((long)(p1) - (long)(p2)) / sizeof(T).

Contoh berikut menunjukkan pengurangan pointer:

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 sudah didukung dalam dua bentuk: postfix (p++ dan p--) dan awalan (++p dan --p). Hasil dari p++ dan 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 tersebut 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

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

Spesifikasi bahasa C#

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

Lihat juga