Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

Pointer Data Types ใน C# - Unsafe Code

Pointer คือตัวแปรที่เก็บ ที่อยู่หน่วยความจำ (Memory Address) ของตัวแปรอีกตัวหนึ่ง ใน C# Pointer ใช้ได้เฉพาะในบริบท unsafe code เท่านั้น เนื่องจาก C# เป็น Managed Language ที่ Garbage Collector จัดการหน่วยความจำให้อัตโนมัติ

Syntax การประกาศ Pointer

type* variableName;

ตัวอย่างการประกาศ

int* ip;      // Pointer to integer
double* dp;   // Pointer to double
char* cp;     // Pointer to char
int** ipp;    // Pointer to pointer

Unsafe Context - ข้อกำหนด

  1. ต้องคอมไพล์ด้วย flag /unsafe (Project Properties → Build → Allow unsafe code)
  2. โค้ดที่ใช้ pointer ต้องอยู่ในบล็อก unsafe หรือเมธอดที่มี modifier unsafe
  3. ใช้ได้กับ Unmanaged Types เท่านั้น (primitive types, enum, struct ที่ไม่มี reference fields)

ตัวอย่างการใช้งาน Pointer

using System;

namespace PointerDemo {
    class Program {
        static unsafe void Main(string[] args) {
            int var = 20;
            int* p = &var;  // & = Address-of operator
            
            Console.WriteLine("Data is: {0}", var);        // 20
            Console.WriteLine("Address is: {0}", (int)p);  // Memory address
            
            // Dereference - เข้าถึงค่าผ่าน pointer
            Console.WriteLine("Value via pointer: {0}", *p);  // 20
            
            // แก้ไขค่าผ่าน pointer
            *p = 30;
            Console.WriteLine("New value: {0}", var);  // 30
            
            Console.ReadKey();
        }
    }
}

ผลลัพธ์

Data is: 20
Address is: 12345678 (ตัวอย่าง)
Value via pointer: 20
New value: 30

Operators สำคัญกับ Pointer

Operator ชื่อ คำอธิบาย
& Address-of lấyที่อยู่ของตัวแปร
* Dereference / Indirection เข้าถึงค่าที่ address นั้นๆ
-> Member Access เข้าถึงสมาชิกของ struct ผ่าน pointer (p->Member)
[] Pointer Indexing เข้าถึงแบบ Array (p[i] เทียบเท่า *(p+i))

Pointer Arithmetic

unsafe {
    int[] arr = { 10, 20, 30, 40, 50 };
    
    fixed (int* p = arr) {  // pin array ในหน่วยความจำ
        for (int i = 0; i < 5; i++) {
            Console.WriteLine(*(p + i));  // 10, 20, 30, 40, 50
        }
    }
}

Fixed Statement - ป้องกัน GC ย้ายหน่วยความจำ

Garbage Collector อาจย้าย Object ใน Heap ได้ ต้องใช้ fixed เพื่อ "Pin" Object ไว้ชั่วคราว

unsafe {
    string s = "Hello";
    fixed (char* p = s) {
        // p ชี้ไปที่ char แรกของ string
        for (int i = 0; i < s.Length; i++) {
            Console.Write(p[i]);
        }
    }
    // s ถูก unpinned อัตโนมัติเมื่อออกจากบล็อก fixed
}

Stackalloc - จัดสรรหน่วยความจำบน Stack

unsafe {
    int* arr = stackalloc int[100];  // ไม่ต้อง fixed, ฟรีอัตโนมัติเมื่อจบ scope
    for (int i = 0; i < 100; i++) arr[i] = i * i;
}

เมื่อไหร่ควรใช้ Pointer?

  • Interop กับ Unmanaged Code (C/C++ DLL, Win32 API, COM)
  • Performance-critical code (Image processing, Cryptography, Game engines)
  • Memory-mapped files, Hardware communication

⚠️ ข้อควรระวัง

  • Pointer ทำให้ Code ไม่ปลอดภัย (Type Safety, Memory Safety)
  • GC ไม่สามารถติดตาม Memory ผ่าน Pointer ได้
  • Buffer Overrun, Dangling Pointer, Memory Leak เป็นความเสี่ยง
  • ใช้ Span<T>, Memory<T> แทนได้ในหลายกรณี (Safe, Modern)