Kode Tidak Aman, Pointer & Buffer Tetap
Gunakan kata kunci unsafe, bekerja dengan pointer, mengunci memori terkelola menggunakan fixed, dan mengakses buffer berukuran tetap dalam struct.
Kode Tidak Aman, Pointer & Buffer Tetap adalah pelajaran C# Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar C# Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus C# Academy mencakup 4 pelajaran total.
Apa Itu Kode Unsafe?
Kata kunci unsafe pada C# memungkinkan manipulasi memori secara langsung: penunjuk mentah, aritmetika penunjuk, dan buffer berukuran tetap. Kata kunci ini melewati jaminan keamanan pengumpul sampah. Aktifkan dengan <AllowUnsafeBlocks>true</AllowUnsafeBlocks> dalam berkas proyek Anda.
// Must add to .csproj:
// <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
// Unsafe blocks can appear inside methods:
unsafe
{
int x = 42;
int* ptr = &x; // get address of x
Console.WriteLine(*ptr); // dereference — prints 42
*ptr = 100;
Console.WriteLine(x); // 100 — x was mutated via pointer
}Tipe Penunjuk dalam C#
Sintaks penunjuk menyerupai C/C++: T* adalah penunjuk ke T. Anda dapat mendeklarasikan penunjuk ke tipe nilai yang tidak terkelola (int, double, dan struktur tanpa anggota referensi). Penunjuk ke tipe terkelola tidak diperbolehkan.
unsafe
{
int i = 10;
double d = 3.14;
int* ip = &i;
double* dp = &d;
// Dereference with *
Console.WriteLine(*ip); // 10
// Pointer arithmetic — move to next int in memory
int[] arr = { 1, 2, 3 };
fixed (int* p = arr)
{
Console.WriteLine(*(p + 0)); // 1
Console.WriteLine(*(p + 1)); // 2
Console.WriteLine(*(p + 2)); // 3
}
}Pernyataan fixed
Objek terkelola dapat dipindahkan oleh pengumpul sampah. Untuk mengambil alamat objek terkelola, Anda harus menyematkannya dengan fixed. Pengumpul sampah tidak akan memindahkan objek tersebut selama blok fixed berlangsung.
byte[] buffer = new byte[256];
unsafe
{
fixed (byte* pBuf = buffer)
{
// pBuf is valid only inside this block
// GC won't relocate 'buffer' here
for (int i = 0; i < buffer.Length; i++)
pBuf[i] = (byte)i;
}
// After 'fixed', GC can move 'buffer' again
}
Console.WriteLine(buffer[5]); // 5Aritmetika Penunjuk
Anda dapat menambahkan atau mengurangkan bilangan bulat dari penunjuk. Menambahkan 1 ke int* akan memajukannya sebesar 4 byte (ukuran int). Inilah dasar operasi memori massal yang cepat.
unsafe
{
int[] data = { 10, 20, 30, 40, 50 };
fixed (int* start = data)
{
int* p = start;
long sum = 0;
for (int i = 0; i < data.Length; i++)
{
sum += *p;
p++; // advance by sizeof(int) = 4 bytes
}
Console.WriteLine(sum); // 150
// Or with index syntax:
Console.WriteLine(start[2]); // 30
}
}stackalloc: Alokasi pada Tumpukan
stackalloc mengalokasikan blok memori pada tumpukan, bukan heap. Tidak ada tekanan pada pengumpul sampah dan tidak diperlukan penyematan. Alokasi ini terbatas pada bingkai tumpukan metode saat ini—memori dibebaskan secara otomatis saat metode mengembalikan nilai.
// Stack-allocated buffer — zero heap allocation
Span<int> buffer = stackalloc int[128]; // safe Span wrapper
buffer.Fill(0);
buffer[0] = 42;
Console.WriteLine(buffer[0]); // 42
// Or raw pointer form (requires unsafe):
unsafe
{
int* raw = stackalloc int[128];
raw[0] = 99;
Console.WriteLine(raw[0]); // 99
}
// Stack frame popped — memory goneBuffer Berukuran Tetap dalam Struktur
Buffer berukuran tetap menyematkan larik dengan panjang tetap secara langsung di dalam struktur—tanpa alokasi heap dan tanpa penunjuk tambahan. Gunakan pengubah fixed di dalam struktur yang dideklarasikan dalam konteks unsafe.
unsafe struct NetworkPacket
{
public int Length;
public byte Command;
public fixed byte Payload[256]; // 256 bytes inline in the struct
}
unsafe
{
NetworkPacket pkt;
pkt.Length = 10;
pkt.Command = 0x01;
// Fill payload inline — no heap allocation
for (int i = 0; i < 10; i++)
pkt.Payload[i] = (byte)i;
Console.WriteLine(pkt.Payload[5]); // 5
}
// sizeof(NetworkPacket) = 4 + 1 + 256 = ~261 bytes on stackvoid* dan Pengecoran Tipe
void* adalah penunjuk tanpa tipe yang berguna untuk operasi memori umum. Anda harus melakukan pengecoran ke penunjuk bertipe sebelum melakukan dereferensi. Operator sizeof(T) bekerja pada tipe yang tidak terkelola dalam konteks unsafe.
unsafe
{
int value = 42;
void* vp = &value; // typeless pointer
int* ip = (int*)vp; // cast back to int*
Console.WriteLine(*ip); // 42
// sizeof works on unmanaged types
Console.WriteLine(sizeof(int)); // 4
Console.WriteLine(sizeof(double)); // 8
Console.WriteLine(sizeof(long)); // 8
}MemoryMarshal dan Kelas Unsafe
System.Runtime.CompilerServices.Unsafe dan System.Runtime.InteropServices.MemoryMarshal menyediakan alternatif aman, tanpa kata kunci, untuk banyak operasi tingkat rendah. Keduanya kompatibel dengan Span dan dapat digunakan tanpa kata kunci unsafe.
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Reinterpret a Span<byte> as Span<int> — no copy, no unsafe keyword
byte[] raw = new byte[16];
Span<int> ints = MemoryMarshal.Cast<byte, int>(raw);
ints[0] = 12345678;
Console.WriteLine(ints[0]); // 12345678
// Unsafe.As<,> — reinterpret reference type (advanced)
ref int first = ref MemoryMarshal.GetReference(ints);
Unsafe.Add(ref first, 1) = 99999;
Console.WriteLine(ints[1]); // 99999Kapan (Tidak) Menggunakan Unsafe
Gunakan kode unsafe hanya jika terdapat kebutuhan kinerja yang jelas dan tidak ada alternatif aman. Minimalkan bagian unsafe—isolasi pada metode pembantu privat atau tipe khusus. Tulis pengujian menyeluruh dan dokumentasikan asumsi yang digunakan.
// GOOD: narrow unsafe scope
public static unsafe int SumBytes(ReadOnlySpan<byte> data)
{
int total = 0;
fixed (byte* p = data)
{
byte* end = p + data.Length;
for (byte* cur = p; cur < end; cur++)
total += *cur;
}
return total;
}
// BETTER for modern code: use SIMD via Vector<T> or hardware intrinsics
// which stay in managed code but still achieve native-level perfDunia Nyata: Mengurai Protokol Biner
Penunjuk unsafe dan buffer berukuran tetap sangat berguna saat mengurai protokol biner yang tata letak strukturnya harus sama persis dengan format data. Struktur tersebut dapat langsung dikonversi dari buffer byte tanpa penyalinan.
[StructLayout(LayoutKind.Sequential, Pack = 1)]
unsafe struct MessageHeader
{
public uint Magic; // 4 bytes
public ushort Version; // 2 bytes
public ushort PayloadLen; // 2 bytes
public fixed byte Id[16]; // 16 bytes GUID inline
}
unsafe ReadOnlySpan<byte> SerializeHeader(MessageHeader hdr)
{
// Cast struct directly to bytes — zero copy
return new ReadOnlySpan<byte>(&hdr, sizeof(MessageHeader));
}
unsafe MessageHeader ParseHeader(ReadOnlySpan<byte> buf)
{
fixed (byte* p = buf)
return *(MessageHeader*)p; // reinterpret cast
}Pemeriksaan Singkat
Mengapa pernyataan fixed diperlukan saat mengambil alamat objek terkelola?
Ringkasan: Kode Unsafe, Penunjuk, dan Buffer Tetap
Poin-poin utama:
- Kata kunci
unsafememungkinkan penggunaan penunjuk mentah—memerlukanAllowUnsafeBlocksdalam proyek - Pernyataan
fixedmenyematkan objek terkelola agar pengumpul sampah tidak memindahkannya - Aritmetika penunjuk bertambah berdasarkan ukuran elemen, bukan byte
stackallocmengalokasikan memori pada tumpukan—tanpa tekanan pada pengumpul sampah, dan dibebaskan saat metode selesai- Buffer berukuran tetap (
fixed byte Payload[N]) menyematkan larik secara langsung di dalam struktur - Untuk sebagian besar skenario, lebih baik gunakan kelas
Span<T>,MemoryMarshal, danUnsafe
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Kode Tidak Aman, Pointer & Buffer Tetap” gratis?
Ya — teks lengkap “Kode Tidak Aman, Pointer & Buffer Tetap” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus C# Academy, upgrade ke CoddyKit PRO. Kursus C# Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Kode Tidak Aman, Pointer & Buffer Tetap”?
Gunakan kata kunci unsafe, bekerja dengan pointer, mengunci memori terkelola menggunakan fixed, dan mengakses buffer berukuran tetap dalam struct. Kamu berlatih C# Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai C# Academy?
Tidak diperlukan pengalaman sebelumnya. C# Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.
Berapa lama pelajaran “Kode Tidak Aman, Pointer & Buffer Tetap” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran C# Academy ini?
Ya. Setiap pelajaran C# Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Dasar-Dasar P/Invoke
- LibraryImport & P/Invoke yang Dibuat dari Sumber
- Kode Tidak Aman, Pointer & Buffer Tetap
- Interoperabilitas COM & Runtime Callable Wrapper