1. บทนำ
ตัวชี้ (Pointer) และตัวชี้ฟังก์ชันในภาษา C เป็นองค์ประกอบสำคัญสำหรับการเขียนโปรแกรมที่มีประสิทธิภาพและยืดหยุ่น ตัวชี้ช่วยให้สามารถเข้าถึงที่อยู่ของหน่วยความจำโดยตรง ส่วนตัวชี้ฟังก์ชันช่วยจัดเก็บที่อยู่ของฟังก์ชันและเรียกใช้งานฟังก์ชันทางอ้อมได้ บทความนี้จะอธิบายตั้งแต่พื้นฐานจนถึงการประยุกต์ใช้งานของตัวชี้และตัวชี้ฟังก์ชัน พร้อมทั้งกล่าวถึงด้านความปลอดภัยและตัวอย่างการใช้งานจริง
2. พื้นฐานของ Pointer
2.1 Pointer คืออะไร
Pointer คือ ตัวแปรชนิดพิเศษที่เก็บที่อยู่ของตัวแปรอื่นในหน่วยความจำ การใช้ Pointer ทำให้สามารถเข้าถึงค่าของตัวแปรแบบทางอ้อม ส่งผลให้โปรแกรมมีความยืดหยุ่นมากขึ้น เช่น สามารถแชร์ข้อมูลระหว่างฟังก์ชัน หรือจัดการโครงสร้างข้อมูลขนาดใหญ่ได้อย่างมีประสิทธิภาพ
2.2 การประกาศและใช้งาน Pointer
การประกาศ Pointer ให้ใส่เครื่องหมายดอกจัน (*
) ไว้หน้าชนิดข้อมูล ตัวอย่างเช่น
int x = 5;
int* p = &x; // เก็บที่อยู่ของ x ไว้ในตัวชี้ p
เครื่องหมาย &
ใช้สำหรับดึงที่อยู่ของตัวแปร ส่วน *
ใช้สำหรับอ้างอิงค่าที่ Pointer ชี้อยู่
printf("%d", *p); // ผลลัพธ์: 5
p
ชี้ไปยังที่อยู่ของ x
ดังนั้น *p
จะได้ค่าของ x
3. พื้นฐานของตัวชี้ฟังก์ชัน
3.1 การนิยามและประกาศตัวชี้ฟังก์ชัน
ตัวชี้ฟังก์ชันคือ Pointer ที่ใช้เก็บที่อยู่ของฟังก์ชัน มีประโยชน์เมื่อเรียกใช้ฟังก์ชันแบบไดนามิก การประกาศจะระบุชนิดของค่าที่คืนและพารามิเตอร์ของฟังก์ชัน
int (*funcPtr)(int);
ตัวอย่างนี้หมายถึง Pointer ที่ชี้ไปยังฟังก์ชันที่รับ int
และคืนค่าเป็น int
3.2 วิธีใช้งานตัวชี้ฟังก์ชัน
การเรียกใช้ฟังก์ชันผ่านตัวชี้ฟังก์ชัน ให้กำหนดที่อยู่ของฟังก์ชันให้กับ Pointer และเรียกผ่าน Pointer นั้น
int square(int x) {
return x * x;
}
int main() {
int (*funcPtr)(int) = square;
printf("%d", funcPtr(5)); // ผลลัพธ์: 25
return 0;
}
ตัวอย่างนี้ funcPtr
เก็บที่อยู่ของฟังก์ชัน square
และเรียกใช้งานผ่าน funcPtr(5)
4. ตัวอย่างการใช้งานตัวชี้ฟังก์ชัน
4.1 การเรียกใช้ฟังก์ชันด้วยตัวชี้ฟังก์ชัน
ตัวชี้ฟังก์ชันมีประโยชน์เมื่อใช้กับอาเรย์ของฟังก์ชัน สามารถเลือกเรียกฟังก์ชันที่แตกต่างกันในขณะรันโปรแกรมเพื่อเพิ่มความยืดหยุ่น
void hello() {
printf("Hellon");
}
void goodbye() {
printf("Goodbyen");
}
int main() {
void (*funcs[2])() = {hello, goodbye};
funcs[0](); // ผลลัพธ์: Hello
funcs[1](); // ผลลัพธ์: Goodbye
return 0;
}
ตัวอย่างนี้ funcs
เป็นอาเรย์ที่เก็บฟังก์ชันต่าง ๆ และเลือกเรียกใช้งานตามสถานการณ์ได้
4.2 Callback Function
Callback Function คือฟังก์ชันที่กำหนดให้ถูกเรียกเมื่อเกิดเหตุการณ์บางอย่าง สามารถเปลี่ยนแปลงพฤติกรรมของโปรแกรมแบบไดนามิกได้
void executeCallback(void (*callback)()) {
callback();
}
void onEvent() {
printf("Event occurred!n");
}
int main() {
executeCallback(onEvent); // ผลลัพธ์: Event occurred!
return 0;
}
สามารถส่งฟังก์ชันต่าง ๆ เข้าไปใน executeCallback
เพื่อเรียกใช้งานแบบไดนามิกได้

5. ตัวชี้กับโครงสร้างข้อมูล (struct)
5.1 การใช้งานตัวชี้กับ struct
การใช้ Pointer กับ struct ช่วยให้จัดการโครงสร้างข้อมูลขนาดใหญ่ได้อย่างมีประสิทธิภาพ การเข้าถึงสมาชิกของ struct ผ่าน Pointer ใช้โอเปอเรเตอร์ “->
“
typedef struct {
int x;
int y;
} Point;
int main() {
Point p = {10, 20};
Point *pPtr = &p;
printf("%d, %d", pPtr->x, pPtr->y); // ผลลัพธ์: 10, 20
return 0;
}
pPtr->x
คือการเข้าถึงสมาชิก x
ของ struct p
5.2 ส่ง struct Pointer เข้าไปในฟังก์ชัน
เมื่อส่ง Pointer ของ struct เข้าไปในฟังก์ชัน จะสามารถแก้ไขสมาชิกของ struct นั้นได้โดยตรงในฟังก์ชัน
void updatePoint(Point *p) {
p->x += 10;
p->y += 20;
}
int main() {
Point p = {10, 20};
updatePoint(&p);
printf("%d, %d", p.x, p.y); // ผลลัพธ์: 20, 40
return 0;
}
ตัวอย่างนี้ updatePoint
ทำการเปลี่ยนแปลงค่าใน struct Point
โดยตรง
6. ข้อดีและข้อควรระวังของตัวชี้ฟังก์ชัน
6.1 ข้อดี
การใช้ตัวชี้ฟังก์ชันช่วยเพิ่มความยืดหยุ่นและขยายขอบเขตการใช้งานโปรแกรม เช่น การทำระบบปลั๊กอิน หรือ Event-driven Programming ที่สามารถเปลี่ยนฟังก์ชันได้แบบไดนามิก รวมถึงการใช้อาเรย์ของตัวชี้ฟังก์ชันแทน switch
ที่ซับซ้อนได้
6.2 ข้อควรระวัง
ควรระวังประเด็นดังต่อไปนี้เมื่อใช้งานตัวชี้ฟังก์ชัน
- ชนิดข้อมูลต้องตรงกัน: หากชนิดของตัวชี้ฟังก์ชันไม่ตรงกับฟังก์ชันที่ชี้อยู่ อาจเกิดการทำงานผิดพลาดได้ ควรตรวจสอบให้ตรงกับ prototype
- ความเสี่ยงด้านความปลอดภัย: หากเรียกใช้ตัวชี้ฟังก์ชันที่ไม่ได้ถูกกำหนดค่า อาจเกิด segmentation fault หรือข้อผิดพลาดอื่น ๆ ควรตรวจสอบและกำหนดค่า
NULL
เมื่อเหมาะสม - ความเสี่ยงจาก Dereference: การ Dereference ตัวชี้ที่ไม่ชี้ไปยังตำแหน่งที่ถูกต้อง อาจทำให้โปรแกรมล่ม
7. สรุป
ความเข้าใจเกี่ยวกับ Pointer และตัวชี้ฟังก์ชันในภาษา C เป็นทักษะสำคัญสำหรับการเขียนโปรแกรมที่มีประสิทธิภาพและยืดหยุ่น การใช้ตัวชี้ฟังก์ชันจะช่วยให้สามารถเขียนโปรแกรมแบบ dynamic function call และ event-driven programming ได้อย่างหลากหลาย ควรศึกษาและฝึกฝนการใช้ Pointer ตั้งแต่พื้นฐานจนถึงการใช้งานจริงอย่างปลอดภัย