ตอน 23 ตัวแปร และตัวแปรแบบ pointer ในภาษา C#

ไปหน้าแรก | สารบัญ | Laploy.comระเบียนบทความ | บทความจากลาภลอย

เว็บไซต์นี้เป็นตัวอย่างเนื้อหาบางตอนในหนังสือ "เรียนรู้ด้วยตนเอง OOP C# ASP.NET" ครอบคลุม บทที่ 1 ถึงบทที่ 6 (ในหนังสือมี 21 บท) เนื้อหาใน Blog อาจอาจแตกต่างจากในหนังสือเพราะเป็นเนื้อหาที่ยังไม่ได้ตรวจแก้ขัดเกลา (edit)

กดที่นี่เพื่อดูรายละเอียดเนื้อหาในแต่ละบท

กดที่นี่เพื่อไปยังเว็บบอร์ด ถาม-ตอบ 

 

 

ตัวแปร – pointer และ unsafe code

 

ตัวแปร (Variable)

ตัวแปรหรือ variable ในภาษา C# เหมือนตัวแปรในภาษาอื่นๆ ที่มีไว้ใช้เก็บข้อมูลต่างๆ เพื่อการประมวลผล แต่การใช้งานตัวแปรในภาษา C# เมื่อเปรียบเทียบกับภาษาอื่นอย่าง VB6, C, C++, JavaScript และ Java แล้วมีความแตกต่างและเหมือนกันบางประการดังนี้

 

  • ในภาษา C# ไม่มีตัวแปรโดดๆ ที่อยู่อย่างลอยๆ (อย่างในภาษา VB6 และ JavaScript) ตัวแปรทุกตัวต้องเป็นสมาชิกของคลาส หรือ struct หรือเป็นตัวแปรท้องถิ่นภายใน method
  • ตัวแปรในภาษา C# มีลักษณะ type safe (หรือ strong type ตรงข้ามกับ weak type ในภาษาอื่น เช่นภาษา JavaScript) คือเคร่งครัดใน type ทำให้เมื่อประกาศตัวแปรแล้ว เราจะไม่สามารถเปลี่ยน type ของตัวแปรได้อีก
  • ตัวแปรที่เป็นสมาชิกของคลาส (หรือ struct) จะเรียกว่า field (เหมือนภาษา Java)
  • ตัวแปรที่ประกาศไว้ภายใน method เรียกว่า local variable หรือตัวแปรท้องถิ่น
  • Field จะมี scope เป็น global ภายในคลาส (หรือ struct) คือโค้ดทุกแห่งในคลาสสามารถเข้าถึงตัวแปรนั้นๆ ได้
  • ตัวแปรจะมี scope อยู่ภายใน คลาส (หรือ struct) ที่ประกาศมันเท่านั้น
  • ตัวแปรที่ถูกประกาศไว้ภายใต้ block ใดๆ จะมีภาวะเป็นตัวแปรท้องถิ่นของ block นั้น และมี scope อยู่เฉพาะใน block นั้นๆ ยกตัวอย่างเช่น หากเราประกาศตัวแปรชื่อ a ไว้ภายใน block ของ for ตัวแปร a จะมี scope อยู่เฉพาะใน loop for นั้นเท่านั้น
  • ตัวแปรอาจเป็น reference type และ value type ก็ได้
  • Derived class รับมรดกตัวแปรแบบ filed ของ base class ได้
  • ภาษา C# มีตัวแปรแบบ pointer เช่นเดียวกับภาษา C (เฉพาะใน unsafe code)
  • เมื่อคอมไพล์โปรแกรมแล้ว ชื่อของตัวแปรจะถูกนำไปเก็บไว้ใน assembly ในลักษณะของ metadata

โปรดพิจารณาตัวอย่างโค้ดต่อไปนี้

int a = 10; 

โค้ดข้างบนคือการประกาศตัวแปรชื่อ a ให้มี type เป็น int และกำหนดค่าเริ่มต้นเป็น 10 เมื่อคำสั่งบรรทัดนี้ทำงาน CLR จะสร้างที่เก็บข้อมูล (ใน heap หากตัวแปรนี้เป็น filed หรือใน stack หากตัวแปรนี้เป็นตัวแปรท้องถิ่นของ method) แล้วใช้ a เป็นตัวอ้างอิง (ซึ่งทำหน้าที่เหมือน pointer)ชี้ไปยังที่เก็บข้อมูลนั้น

a = a + 5;

โค้ดบรรทัดนี้หากกล่าวอย่างมโนคติจะพูดว่า “นำค่าที่เก็บอยู่ในตัวแปร a มาบวกกับเลข 5 แล้วนำไปเก็บในตัวแปร a” แต่ถ้าจะกล่าวให้ถูกต้องตามความจริงจะต้องพูดว่า “นำเลข 5 ไปบวกกับค่าที่ถูกชี้โดย a แล้วนำผลลัพธ์ที่ได้ไปเก็บในที่ซึ่งชี้โดย a”

จะเห็นว่าตัวแปร a ทำหน้าที่อ้างอิงไปยังค่า (ซึ่งตอนแรกเป็น 10 ต่อมาภายหลังกลายเป็น 15) โดยตรง การอ้างไปยังค่าโดยตรงเช่นนี้ ทำให้ตัวแปร a มีภาวะเป็น value type

 

pointer

Pointer คือตัวแปรที่เก็บค่าอ้างอิงไปยังตำแหน่งในหน่วยความจำ (เหมือน indirect addressing mode ในภาษาแอสเซมบลี) ในภาษา C# Pointer ถือเป็น data type แบบที่สาม (สองแบบแรกคือ value type และ reference type ที่ท่านคงจำได้จากในบทที่ 3)

pointer คือตัวแปรที่เราใช้งานได้ภายในบล็อก unsafe เท่านั้น ภาษา C# สนับสนุนการนำ pointer ไปใช้เป็นสมาชิกของคลาส และ struct (ภาษา Java ก็มี pointer แต่เราไม่สามารถเขียนโปรแกรมจัดการกับ pointer ได้โดยตรง)

ภาษา C# สนับสนุนตัวแปร pointer ทุกแบบเช่นเดียวกับภาษา C++ เช่น pointer ธรรมดา pointer ที่ชี้ไปยัง pointer, pointer ที่ชี้ไปยัง array และ pointer ที่ชี้ไปยัง array ของ pointer เป็นต้น data type ที่กำหนดให้ pointer ได้คือ sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, และ bool

ตัวแปรแบบ pointer แตกต่างจากตัวแปรธรรมดา เมื่อเราอ้างถึงชื่อของตัวแปร ชื่อสมาชิกของ structure หรือชื่อสมาชิกของคลาส เท่ากับเราบอกคอมพิวเตอร์ว่า เราต้องการทำบางอย่างกับหน่วยความจำที่ชื่อนั้นเป็นเจ้าของ โปรดพิจารณาตัวอย่างโค้ดต่อไปนี้

char foo = "A";
char oldFoo;
oldFoo = foo; 

ตัวอย่างโค้ดข้างบนเป็นตัวอย่างโปรแกรมที่ใช้ตัวแปรธรรมดา (ที่ไม่ใช่ pointer) บรรทัดแรกสั่งให้คอมพิวเตอร์นำตัวอักษร A ไปเก็บยังหน่วยความจำที่ตัวแปร foo ครอบครองอยู่ บรรทัดต่อมาสร้างตัวแปรชื่อ oldFoo บรรทัดสุดท้ายบอกคอมพิวเตอร์ให้คัดลอกข้อมูลที่เก็บอยู่ภายหน่วยความจำของ foo ไปเก็บไว้ในหน่วยความจำของ oldFoo

ตัวแปรแบบ pointer แตกต่างจากตัวแปรในตัวอย่างข้างบน เพราะสิ่งที่ pointer เก็บคือเลขตำแหน่งหน่วยความจำ ซึ่งโดยปรกติแล้ว จะเป็นเลขตำแหน่งของตัวแปร หรือเลขตำแหน่งของสมาชิกของคลาสหรือ struct

ต่อไปนี้ผู้เขียนจะอธิบายวิธีสร้างและใช้งาน pointer หากท่านเคยเรียน หรือเคยเขียนโปรแกรมภาษา C หรือ C++ ท่านจะพบว่า pointer ในภาษา C# ไม่มีความแตกต่างใดๆ กับ pointer ในสองภาษาที่กล่าวมา ท่านจึงอาจข้ามหัวข้อถัดไปนี้ได้เลย

ภาพนี้แสดงความแตกต่างระหว่างตัวแปรธรรมดากับตัวแปรแบบ pointer คำสั่ง int foo = 567; ทำหน้าที่สร้างตัวแปรธรรมดา (เป็นแบบ value type) เนื่องจาก foo เป็นตัวแปรท้องถิ่นของ method (โค้ดตัวอย่างไม่ได้แสดงการประกาศ method) มันจึงมีที่อยู่ใน stack ในที่นี้สมมุติว่าอยู่ที่เลขตำแหน่งของหน่วยความจำ (memory address) 100 โค้ดบรรทัดที่สองคือ int* bar = &foo; ทำหน้าที่นำ memory address ของตัวแปร foo มาเก็บไว้ในตัวแปร pointer bar ทำให้ bar มีค่าเท่ากับ 100

 

วิธีประกาศ pointer

การสร้างตัวแปรแบบ pointer ก็เหมือนการสร้างตัวแปรธรรมดา แต่มีจุดแตกต่างเล็กน้อย ตัวอย่างข้างล่างแสดงการประกาศตัวแปรแบบ pointer ชื่อ foo

char* foo;

คำสั่งประกาศตัวแปรแบบ pointer มีองค์ประกอบสี่ส่วนดังนี้

• ชนิดข้อมูล: ชนิดข้อมูลของตำแหน่งที่ pointer ชี้
• เครื่องหมายจอกจัน: บอกคอมพิวเตอร์ว่ากำลังประกาศตัวแปร pointer
• ชื่อตัวแปร: ใช้เพื่อแยกความแตกต่างระหว่าง pointer แต่ละตัว และใช้เพื่ออ้างถึง pointer ภายในโปรแกรม
• เครื่องหมายอัฒภาค: (เครื่องหมาย😉 ใช้บอกให้คอมพิวเตอร์รู้ว่าคำสั่งบรรทัดนี้จบแล้ว

ภาษา C# สนับสนุนการประกาศตัวแปรหลายๆ ตัวในคำสั่งเดียว โดยมีวิธีทำดังนี้

int* p1, p2, p3;      // ถูก
int *p1, *p2, *p3;    // ผิด

นี่คือการประกาศตัวแปรแบบ pointer ที่มี data type เป็น int สามตัว

 

data type และ pointer

เราใช้ data type ในการประกาศตัวแปรธรรมดา บอกให้คอมพิวเตอร์รู้ว่าจะต้องจองเนื้อที่ในหน่วยความจำขนาดเท่าใด และใช้เก็บข้อมูลชนิดใด แต่ตัวแปรแบบ pointer ไม่เป็นอย่างนั้น data type ที่ใช้เมื่อประกาศตัวแปร pointer ทำหน้าที่บอกคอมพิวเตอร์ว่าหน่วยความจำ address ที่มันชี้ มี data type เป็นแบบใด

ถ้าท่านอ่านแล้วไม่เข้าใจก็ไม่ต้องแปลกใจ เพราะนักเขียนโค้ดหลายคนก็งงกับเรื่องนี้ ถ้าจะให้หายงงก็ต้องทบทวนเรื่องพื้นฐานสักนิด

เครื่องหมายดอกจันที่ใช้ในการประกาศ pointer ทำหน้าที่บอกคอมพิวเตอร์ถึงขนาดของหน่วยความจำที่ต้องจอง และบอกถึง data type ของข้อมูลที่จะนำไปเก็บ นั่นคือสำรองเนื้อที่ในหน่วยความจำให้มีขนาดใหญ่เพียงพอที่จะเก็บเลขตำแหน่ง และ data type ของข้อมูลที่จะนำไปเก็บ (คือเลขตำแหน่ง)

ท่านอาจสงสัยว่าทำไมเวลาประกาศ pointer จึงต้องใส่ data type การที่จะเข้าใจคำตอบ ท่านจะต้องเข้าใจเรื่อง pointer เป็นอย่างดีเสียก่อน ตัวอย่างต่อไปนี้จะทำให้เข้าใจดีขึ้น

    int productNumber;
    double price;
    double* ptPrice;
    int* ptProductNumber;

โปรแกรมนี้ประกาศตัวแปรสี่ตัว บรรทัดแรกประกาศตัวแปรชนิด int ชื่อ productNumber บรรทัดที่สองประกาศตัวแปรชนิด double ชื่อ price และสองบรรทัดสุดท้ายประกาศตัวแปรแบบ pointer

ข้อมูลชนิด double ที่ใช้ประกาศ ptPrice ทำหน้าที่บอกคอมพิวเตอร์ว่าเลขตำแหน่งที่จะเก็บไว้ใน ptPrice เป็นเลขตำแหน่งของข้อมูลที่มี data type เป็น double และ ptPrice ใช้ชี้ไปยังตัวแปร price

ในทำนองเดียวกัน ข้อมูลชนิด int ที่ใช้ประกาศ ptProductNumber บอกคอมพิวเตอร์ว่าเราจะใช้ ptProductNumber เก็บเลขตำแหน่งของ data type แบบ int และจะใช้มันเก็บเลขตำแหน่งของตัวแปร productNumber

เพราะอะไรถึงต้องบอกคอมพิวเตอร์ว่า เลขตำแหน่งที่จะเก็บเป็น data type อะไร คำตอบคือ เพราะเราต้องการดำเนินการทางคณิตศาสตร์กับ pointer การจะทำเช่นนั้นได้ต้องให้คอมพิวเตอร์รู้ว่า data type ที่เลขตำแหน่งอ้างถึง เป็น data type ใด ท่านจะได้เรียนวิธีกระทำทางคณิตศาสตร์กับ pointer ภายหลัง

 

การกำหนด address ให้ pointer

วิธีนำเลข address ไปใส่ pointer ทำได้โดยใช้เครื่องหมาย & (address operator) ก่อนอื่นมาทบทวนวิธีกำหนดค่าให้ตัวแปรธรรมดากันก่อน คำสั่งข้างล่างบอกให้คอมพิวเตอร์คัดลอกข้อมูลในหน่วยความจำของ foo ไปใส่ในหน่วยความจำของ oldFoo

oldFoo = foo; 

คำสั่งนี้ระบุเป็นนัยว่า เราต้องการทำงานกับข้อมูลที่อยู่ในตัวแปร ไม่ใช่กับเลข address ของมัน แต่ถ้าเราใส่เครื่องหมาย & นำหน้า เท่ากับเราบอกคอมพิวเตอร์ว่า เราต้องการทำงานกับเลข address ของมัน ไม่ใช่ข้อมูลของมัน
ตัวอย่างต่อไปนี้แสดงวิธีใช้เครื่องหมาย & เพื่อบอกคอมพิวเตอร์ให้คัดลอกเลข address ของตัวแปรไปใส่ pointer โดยเราจะสั่งให้นำเลขตำแหน่งของตัวแปร foo ไปใส่ใน pointer ptFoo และบอกให้นำเลข address ของตัวแปร productNumber ไปใส่ไว้ใน pointer ptProductNumber

    ptFoo = &foo;
    ptProductNumber = &productNumber; 

 

การเข้าถึงข้อมูลที่ pointer ชี้อยู่

ปรกติเราใช้ pointer ชี้หน่วยความจำ แต่บางครั้งเราก็ต้องการคัดลอก address จาก pointer ตัวหนึ่ง ไปใส่ pointer อีกตัวหนึ่ง ซึ่งทำได้โดยใช้เครื่องหมาย = ดังนี้

ptOldfoo = ptNewfoo; 

โปรดสังเกตว่ารูปแบบคำสั่ง ก็เหมือนการกระทำกับตัวแปรธรรมดา เพราะคำสั่งนี้บอกคอมพิวเตอร์ให้คัดลอกข้อมูลจากตัวแปรตัวหนึ่งไปใส่ตัวแปรอีกตัวหนึ่ง โดยไม่สนใจว่าข้อมูลนั้นจะเป็นข้อมูลธรรมดาหรือเป็น address

บางครั้งนักเขียนโปรแกรมอาจต้องการเข้าถึงข้อมูล ณ address ที่ pointer ชี้อยู่ เรื่องนี้อาจเข้าใจยากสักหน่อย ดังนั้นจะอธิบายโดยยกตัวอย่างให้ชัดเจน โปรดพิจารณาตัวอย่างโค้ดต่อไปนี้

char oldFoo;
char foo = "A";
char *ptFoo;
char *ptOldFoo;
ptFoo = &foo; 

บรรทัดแรกประกาศตัวแปร บรรทัดที่สองประกาศตัวแปร และกำหนดค่าไปพร้อมๆ กันในบรรทัดเดียว บรรทัดที่สามและสี่ประกาศตัวแปรแบบ pointer และบรรทัดสุดท้าย เป็นการคัดลอก address ของตัวแปร foo ไปเก็บไว้ใน pointer ชื่อ ptFoo

สมมุติว่านักเขียนโค้ดต้องการอ่านค่าจากตัวแปร grade เพื่อนำมาแสดงบนหน้าจอ แต่ต้องการทำด้วยการใช้ pointer เท่านั้นก็ทำได้โดยใช้เครื่องหมายดอกจัน (*) นำหน้า pointer เพื่อบอกคอมพิวเตอร์ว่าจะอ่านข้อมูลจากหน่วยความจำที่ pointer ตัวนั้นเก็บ address หากไม่ใส่เครื่องหมายดอกจัน จะเป็นการบอกคอมพิวเตอร์ว่าต้องการอ่านเลข address ที่ pointer ตัวนั้นเก็บอยู่

สมมุติว่าท่านต้องการคัดลอกเลขตำแหน่งที่เก็บอยู่ใน pointer ชื่อ ptFoo ไปใส่ไว้ใน pointer ชื่อ ptOldFoo จะทำได้ดังนี้

ptOldFoo = ptFoo;

ต่อไปสมมุติว่าท่านต้องการคัดลอกข้อมูลจากตัวแปร foo ไปใส่ยังตัวแปรตัวใหม่ชื่อ oldFoo แต่ท่านต้องการทำโดยใช้ pointer ชื่อ ptFoo และใช้เครื่องหมาย *เท่านั้นก็สามารถทำได้ดังนี้

char oldFoo = *ptFoo;

คำสั่งนี้บอกคอมพิวเตอร์ให้นำข้อมูลจากหน่วยความจำตำแหน่งที่ pointer ชื่อ ptFoo เก็บ address ไว้ มาใส่ในตัวแปรชื่อ oldFoo จงใช้ pointer ร่วมกับเครื่องหมาย *เมื่อใดก็ตามที่ท่านต้องการข้อมูล ณ address ที่ pointer ชี้อยู่ และใช้ pointer ร่วมกับเครื่องหมาย *ได้ทุกแห่งที่ใช้ตัวแปรธรรมดาได้

 

 

Pointer to pointer

ภาษา C# นอกจากจะมี pointer ที่ชี้ไปยังข้อมูลที่มี data type ทั่วไปแล้ว ภาษา C# ยังมี pointer แบบพิเศษ ซึ่งเป็น pointer ที่ชี้ไปยัง pointer (pointer to pointer หรือ Pointer Reference ต่อไปจะเรียกว่า PTP) เช่นเดียวกับภาษา C++

วิธีประกาศ PTP เป็นดังนี้

int foo = 12;              // foo คือตัวแปรธรรมดา
int* ptBar = &foo;         // ptBar คือ pointer ธรรมดา
int** ptptFooBar = &ptBar; // ptptFooBar คือ PTP

ไม่เหมือนกับตัวแปรแบบ pointer ธรรมดาที่เราใช้เก็บเลขตำแหน่งหน่วยความจำ (memory address) ของตัวแปรธรรมดา เพราะสิ่งที่ PTP เก็บคือ memory address ของตัวแปรแบบ pointer

 

 

pointer กับ array

ในภาษา C# pointer และ array มันถูกนำมาอธิบายไว้ด้วยกัน เพราะ pointer กับ array มีหลายอย่างที่คล้ายๆ กัน และอันที่จริงเราสามารถสร้าง array จาก pointer ได้ ซึ่งแม้จะมีข้อเสียที่ใช้งานได้ยากกว่า แต่ก็มีข้อดีที่ทำงานได้เร็วกว่า
Pointer และ array มักถูกนำมาใช้ร่วมกันอยู่เสมอเนื่องจาก array เป็นข้อมูลในหน่วยความจำที่เรียงติดกันไป เราจึงอาจใช้ pointer เพื่อวนเข้าถึงข้อมูลเหล่านั้น โปรดพิจารณาโค้ดต่อไปนี้

    int[] myArray = { 1, 2, 3, 4 };
    unsafe
    {
        fixed (int* ptArray = myArray)
        {
            for (int i = 0; i < myArray.Length; i++)
            {
                Console.Write(ptArray[i]);
            }
        }
    } 

โค้ดที่เห็นข้างบนนี้สาทิตการใช้ pointer เข้าถึงข้อมูลใน array (array element) โดยตอนแรกเราสร้าง array ชื่อ myArray จากนั้นสร้าง pointer ที่ชี้ไปยัง array ชื่อ ptArray คำสั่ง fixed ทำหน้าที่ตั้งให้ pointer ชี้ไปยังตัวแปรแบบ managed และตรึงค่าของตัวแปรไว้ไม่ให้เปลี่ยนตำแหน่งระหว่างโปรแกรมทำงาน

ผลลัพธ์เมื่อโปรแกรมทำงานคือ
1234

 

array of pointer

เนื่องจาก pointer ก็คือตัวแปรชนิดหนึ่ง ดังนั้นเราจึงสามารถเก็บ pointer ไว้ใน array ได้เช่นกัน วิธีสร้าง array of pointer (ต่อไปจะเรียกย่อว่า AOP) คล้ายคลึงกับการสร้าง array สามัญ ผลลัพธ์ที่ได้คือ array ที่มี array element เป็น pointer เราจะสร้าง AOP ให้มีกี่มิติก็ได้ และจะสร้าง AOP เป็นแบบ rectangular หรือแบบ non-rectangular (jagged array ดูบทที่ 3) ก็ได้เช่นเดียวกับ array สามัญ

วิธีประกาศ AOP เป็นดังนี้

    int a = 1, b = 2, c = 3;
    int*[] ptArray = { &a, &b, &c }; 

เมื่อรันโค้ดสองบรรทัดข้างบนนี้ ผลลัพธ์ที่ได้คือ AOP ชื่อ ptArray ซึ่งมี array element เป็นค่าตำแหน่งในหน่วยความจำ (memory address) ของตัวแปรแบบ int สามตัวคือ a, b และ c ตามลำดับ

 

array of pointer to pointer

โดยใช้หลักการเดียวกับ AOP เราสามารถสร้าง array เพื่อใช้เก็บ PTP ได้เช่นกัน เราเรียก array ชนิดนี้ว่า array of pointer to pointer (ต่อไปจะเรียกย่อย่า APTP) ซึ่งเป็น array ที่มี array element เป็น PTP ทั้งหมด ตัวอย่างวิธีประกาศ APTP เป็นดังนี้

    int* ptA = &a, ptB = &b, ptC = &c;
    int** pt2ptA = &ptA, pt2ptB = &ptB, pt2ptC = &ptC;
    int**[] arrayOfpt2pt = { pt2ptA, pt2ptA, pt2ptA };

แม้การประกาศ APTP จะดูเรียบง่าย คล้ายการประกาศ array ตามปรกติ แต่การนำ APTP ไปประยุกต์ใช้กลับเป็นเรื่องยากที่สุดในศาสตร์คอมพิวเตอร์ เพราะการทำความเข้าใจกับผลลัพธ์ที่ได้จาก array ที่อ้างถึง pointer ที่ชี้ไปยังตำแหน่งข้อมูลของ pointer อีกต่อหนึ่ง (ซึ่ง pointer อีกตัวนั้นเก็บค่าอ้างอิงที่ชี้ไปยังตำแหน่งข้อมูลของของตัวแปรสามัญอีกทอดหนึ่ง) นับเป็นเรื่องซับซ้อนอย่างยิ่ง การเขียนโค้ดเพื่อประยุกต์ใช้ APTP จึงต้องใช้สมาธิมากกว่าปรกติ

APTP มีประโยชน์เมื่อเราต้องเขียนโปรแกรมจัดการกับโครงสร้างข้อมูลขนาดใหญ่ ที่มีข้อมูลจำนวนมาก
การจัดเรียงหรือการประมวลผลต่อข้อมูลโดยใช้ pointer และ array แม้จะทำได้รวดเร็ว (เพราะ CLR จะจองเนื้อที่ในหน่วยความจำไว้เป็นชิ้นเดียวเรียงต่อเนื่องไป) แต่ในกรณีที่มีข้อมูลจำนวนมหาศาล (หลายร้อยล้านรายการ) การจัดเรียงหรือประมวลผลหากกระทำต่อตัวข้อมูลใน array โดยตรงจะยังช้าเกินไป

ดังนั้นแทนที่เราจะใช้ arry เก็บตัวข้อมูลจริง เราจึงต้องเลี่ยงไปใช้ arry เพื่อเก็บ PTP เมื่อต้องการจัดเรียงหรือประมวลผลกับข้อมูล เราจะทำทางอ้อมโดยจัดเรียงหรือประมวลผลกับค่าของ pointer ที่ถูกชี้โดย PTP ที่อยู่ใน APTP แทน ซึ่งทำได้รวดเร็วกว่าการกระทำกับข้อมูลโดยตรงมาก ทำให้การใช้ APTP จัดการกับข้อมูลในโครงสร้างข้อมูลที่มีข้อมูลจำนวนมาก สามารถทำได้ด้วยความเร็วสูง

ข้อสรุปเรื่อง pointer
• ทำหน้าที่ชี้ไปยังตำแหน่งเก็บข้อมูลในหน่วยความจำ
• การประกาศ pointer ต้องกำหนด data type ด้วย
• ใช้ pointer ชี้ไปยัง pointer หรือชี้ไปยัง array หรือ array ของ pointer ก็ได้
• pointer ที่ชี้ไปยัง pointer ใช้ดอกจันสองตัว เช่น int** p
• pointer arithmetic เป็นไปตาม data type
• ใช้งานได้เฉพาะในบล็อก unsafe

 

 

Unsafe Code

ก่อนจะใช้ตัวแปร pointer ในภาษา C# ได้ท่านต้องประกาศโค้ดบล็อกนั้นให้เป็นแบบ unsafe code โดยใช้คำสั่งดังนี้

unsafe
{
     // โค้ดภายใน block นี้เป็น unsafe code
}

แม้คำว่า unsafe code จะแปลว่า “โค้ดที่ไม่ปลอดภัย” แต่ความหมายจริงๆ แล้วไม่ใช่เช่นนั้น โค้ดส่วนที่เป็น unsafe code ไม่ใช่โค้ดที่อันตราย หรือสุ่มเสี่ยงต่อระบบรักษาความปลอดภัยแต่อย่างใด มันเป็นเพียงโค้ดที่ไม่ได้ถูกตรวจสอบการทำงานเท่านั้น เพราะ CLR เพียงแค่ปล่อยให้มันทำงานไปโดยไม่ข้องแวะ หากคุณเขียน unsafe code คุณจะต้องรับหน้าที่ดูแลเรื่องความปลอดภัยและป้องกันความผิดพลาดต่างๆ ที่อาจเกิดขึ้น (เช่น ความผิดพลาดที่อาจเกิดจากการใช้งาน pointer หรือ array bound) ด้วยตนเอง

ข้อสรุปเรื่อง unsafe code
• กำหนดให้กับ block หรือ method หรือ type ได้
• บางสถานการณ์อาจทำให้การทำงานเร็วขึ้น (เพราะไม่มีการตรวจ array bound)
• อาจทำให้เสี่ยงแต่ความเสถียรของระบบ
• ควรใช้เฉพาะเมื่อต้องการใช้ pointer
• ต้องกำหนด option /unsafe ให้คอมไพเลอร์จึงจะคอมไพล์ได้

คำถามประจำบทที่ 4

  1. Statement คืออะไร
  2. สมาชิกของคลาสและ struct คืออะไร
  3. access modifier คืออะไร
  4. type modifier คืออะไร
  5. type modifier volatile ทำหน้าที่อะไร
  6. คำว่า assembly ในภาษา C# คืออะไร
  7. metadata คืออะไร
  8. field คืออะไร
  9. derived class สามารถมองเห็นและใช้งาน field แบบ private ที่นิยามไว้ใน base class ได้หรือไม่
  10. ฟังค์ชันในภาษา C# คืออะไร
  11. property คืออะไร
  12. access modifier ของ property จะเป็นอะไรเสมอ
  13. method คืออะไร
  14. การนิยาม method ชื่อเดียวกัน ภายในคลาสเดียวกันหลายๆ ชุดเรียกว่าอะไร
  15. การนิยาม method ใน derived class ซ้ำกับ method ใน base class ได้หากใช้ร่วมกับ keyword new จะเรียกว่าอะไร
  16. การทำ method overriding คืออะไร
  17. constructor คืออะไร
  18. default constructor คืออะไร
  19. destructor คืออะไร
  20. หากไม่ระบุ modifier ของพารามิเตอร์ CLR จะถือว่าเป็นการส่งค่าแบบใด
  21. ref parameter คืออะไร
  22. parameter array คืออะไร
  23. method signature คืออะไร
  24. การคอมไพล์โปรแกรมคืออะไร

เฉลยคำถาม

ตอนต่อไป : Inheritance และ Versioning ในภาษา C#

Post a comment or leave a trackback: Trackback URL.

ความเห็น

  • มัสยา  On พฤศจิกายน 14, 2007 at 9:08 pm

    ขอคุณมากเลยนะคะ ได้ความรู้เยอะเลย
     

ใส่ความเห็น

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / เปลี่ยนแปลง )

Twitter picture

You are commenting using your Twitter account. Log Out / เปลี่ยนแปลง )

Facebook photo

You are commenting using your Facebook account. Log Out / เปลี่ยนแปลง )

Google+ photo

You are commenting using your Google+ account. Log Out / เปลี่ยนแปลง )

Connecting to %s

%d bloggers like this: