Skip to main content

Pointer

Pointer คืออะไร

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

  • เมื่อประกาศตัวแปรใน C++ ตัวแปรจะถูกเก็บไว้ในหน่วยความจำ แต่ละตัวแปรจะมีที่อยู่ (address) เฉพาะตัวของตัวเอง
  • pointer เก็บค่าที่อยู่ของตัวแปรอื่น เปรียบเสมือน "ลูกศร" ที่ชี้ไปยังตำแหน่งของข้อมูลนั้นได้

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

int num = 10;
int* ptrNum = # // ptrNum ชี้ไปที่ num

// เข้าถึงค่าของ num ผ่าน ptrNum
cout << *ptrNum << endl; // แสดง 10

// เปลี่ยนแปลงค่าของ num ผ่าน ptrNum
*ptrNum = 20;

// num จะมีค่า 20
cout << num << endl; // แสดง 20

ประโยชน์ของ pointer

  1. Direct Memory Access Pointer ช่วยให้เข้าถึงหน่วยความจำได้โดยตรงและเปลี่ยนแปลงค่าตรงนั้นได้เลย สำคัญมากๆในงานเขียนโปรแกรมระดับลึกๆ ที่เราต้องควบคุมการใช้หน่วยความจำได้แม่นยำ
  2. Dynamic Memory Allocation ด้วยตัว pointer เราสามารถสั่งจัดการหน่วยความจำเพิ่มตอนที่โปรแกรมทำงานโดยใช้คำสั่งอย่าง new และ delete ทำให้สร้าง data structure ที่ต้องการความยืดหยุ่น สามารถเพิ่มหรือลดขนาดพื้นที่การใช้ได้ เช่น linked list ต้นไม้ (tree) และ กราฟ (graph)
  3. Efficiency in Passing Large Structures เวลาต้องส่งข้อมูลโครงสร้างขนาดใหญ่หรือ class ให้กับ function การใช้ pointer มีประสิทธิภาพกว่าส่งค่าปกติ (pass by value) เพราะ pointer ทำให้ function สามารถเข้าถึงข้อมูลต้นฉบับได้โดยไม่ต้องสร้างสำเนาขึ้นมาใหม่ จึงประหยัดทั้งความจำและเวลาประมวลผลได้
  4. Function Pointers and Callbacks ตัว Pointer อาจจะชี้ไปที่ function เองก็ได้ สิ่งนี้ทำให้เราส่ง ดีืแะรนื ต่างๆ เข้าไปยังฟังก์ชันอื่น เช่น ใช้ในการส่ง callback หรือใช้เลียนแบบ polymorphism ในภาษา C
  5. Facilitating Complex Data Structures Pointer สำคัญมากในการสร้าง data structure ที่ซับซ้อนอย่าง linked list, trees, และ graph เพราะตัว pointer สามารถใช้เชื่อมข้อมูลที่เกี่ยวข้องกันภายใน data structure ได้
  6. Array Manipulation ตัว Pointer ช่วยให้ทำงานกับ array ได้อย่างมีประสิทธิภาพ เพิ่มความยืดหยุ่นกว่าการใช้ index ใน array โดยการสามารถวนค่ากับ value ใน array และสามารถเป็นตัวแทนในการจัดการค่าได้

ประเภทของ Pointer และ Operator

ประเภทของ Pointer เราจะแยกออกจากกัน ตามการใช้งานราวๆนี้ (อันนี้เป็นการแยกประเภทจากผู้สอนเอง)

  1. Basic Pointer เป็นการใช้ pointer อ้างอิงไปยังตัวแปรโดยตรง
int var = 10;
int* ptr = &var; // Pointer to an integer variable
  1. Pointer to Pointer เป็นการใช้ pointer เก็บที่อยู่ของ pointer อีกตัวเอาไว้
int var = 10;
int* ptr = &var;
int** ptrToPtr = &ptr; // Pointer to a pointer to an integer
  1. Array pointer เป็นการใช้ pointer ชี้ไปยัง array หรือ element แรกของ array
int arr[5] = {1, 2, 3, 4, 5};
int* arrPtr = arr; // Pointer to the first element of the array
  1. Function pointer ใช้ pointer ชี้ไปยัง function
void myFunction(int a) {
// Function implementation
}
void (*functionPtr)(int) = myFunction; // Pointer to a function that takes an int and returns void

Operator ใน Pointer

โดย Operation ที่สามารถทำได้ใน Pointer นั้นก็จะสามารถใช้งาน Operation แบบ Arithmetic (การดำเนินการคณิตศาสตร์) แบบทั่วๆไปได้ แต่ก็จะมีหลักแนวคิดที่แตกต่างกับตัวแปรทั่วไปคือ มันคือตัวแปรที่เก็บไว้ทั้ง “ที่อยู่” และ “ข้อมูล” ดังนั้นมันจึงสามารถเปรียบเทียบของที่นอกเหนือจากข้อมูลได้ โดย operator ก็จะมีตั้งแต่

  1. Address-of Operator (&) ใช้สำหรับรับ memory address จากตัวแปรที่ใส่ไว้
int var = 10;
int* ptr = &var; // ptr holds the address of var
  1. Dereference Operator (*) ใช้สำหรับเข้าถึงหรือแก้ไข value ของตัวแปรที่ pointer กำลังชี้ไปยัง address นั้น
int var = 10;
*ptr = 20; // Changes the value of var to 20

** อะไรก็ตามที่ใช้ผ่าน Dereference Operator = จะเหมือนกับการเรียกใช้ตัวแปรปกติ Operator ใดๆที่เคยใช้งานร่วมกับตัวแปรประเภทนั้นได้ก็จะสามารถใช้งานได้เหมือนเดิม

  1. Pointer Arithmetic Operators ก็จะเป็นการใช้งานสัญลักษณ์คณิตศาสตร์ทั่วไปอย่าง +, -, ++, -- โดย สัญลักษณ์แต่ละตัวเมื่อใช้งานร่วมกับ Address ก็จะมีความหมายแตกต่างกันไปจากเดิมคือ จะเป็นการจัดการกับ “Address” แทน หากใช้กับตัวแปร pointer โดยตรง

- Addition, Increment (+, ++) เป็นการชี้ไปยัง address ตัวถัดไป

ptr + 1; // Points to the next memory location of the type ptr is pointing to
ptr++; // Moves the pointer to the next memory location
  • Subtraction, Decrement (-, --) เป็นการถอย address ไปยังตัวก่อนหน้า
ptr - 1; // Points to the previous memory location of the type ptr is pointing to
ptr--; // Moves the pointer to the previous memory location

4. Comparison Operators (==, !=, <, >, <=, >=) ใช้สำหรับการเปรียบเทียบ address ที่อยู่ใน pointer (หากเท่ากับ = เป็นการอ้างอิงถึง address ตำแหน่งเดียวกัน = เป็นการพูดถึงตัวแปรตัวเดียวกัน)

if (ptr1 == ptr2) {
// Executes if ptr1 and ptr2 point to the same address
}
  1. Assignment Operator (=) ใช้สำหรับการ assign address เข้ากับตัวแปร pointer เพื่อใช้สำหรับ copy address จากตัวหนึ่งไปยังตัวหนึ่งได้
ptr1 = ptr2; // ptr1 now holds the same address as ptr2

6. The nullptr Keyword (C++11 and above) ใช้สำหรับพูดถึง null pointer ที่ทำการชี้ pointer ไปยังตำแหน่งที่ไม่มี object (no object) ได้

int* ptr = nullptr; // ptr is a null pointer
  1. The Arrow Operator (->) ใช้สำหรับเข้าถึง member ที่อยู่ภายใน Struct หรือ Class ผ่าน pointer
struct MyStruct {
int field;
};
MyStruct* ptr = new MyStruct;
ptr->field = 10; // Accesses field of object pointed to by ptr

(เดี๋ยวเราเพิ่มเติมกันในเรื่อง Struct และ Class อีกที)

Pointer และ Array

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

นี่คือการประกาศ pointer ไปยัง array

  • ประกาศ pointer ชนิดเดียวกับ element ของ array และใช้ & หาที่อยู่ของ array
int arr[5] = {1, 2, 3, 4, 5};
int* ptr = arr; // ptr ชี้ไปที่ arr[0]

// เข้าถึงค่าของ arr[0] ผ่าน ptr
cout << *ptr << endl; // 1

Loop กับ Array ด้วย pointer

Array โดยใช้ pointer ใน C++ จะอาศัย "การคำนวณทางคณิตศาสตร์บน pointer" เพื่อเลื่อนตำแหน่งที่ชี้ไปตามข้อมูลภายใน Array วิธีนี้ใช้ประโยชน์จากการที่ข้อมูลแต่ละอย่างภายใน Array จะถูกเก็บเป็นลำดับใน address ที่ติดกันของหน่วยความจำ ดังนั้นเราสามารถขยับเพิ่ม (increment) หรือ ลด (decrement) pointer ให้เลื่อนไปยังข้อมูลถัดไปได้ เช่นตามตัวอย่างนี้ที่จะทำการวน loop สมาชิกทุกตัวของ Array ด้วย pointer ออกมา

#include <iostream>

int main() {
int arr[] = {10, 20, 30, 40, 50};
int *ptr = arr; // Pointer to the first element of the array

int length = sizeof(arr) /
sizeof(arr[0]); // Calculate the number of elements in the array

std::cout << "Array elements: ";
for (int i = 0; i < length; ++i) {
std::cout << *(ptr + i) << " "; // Access the array element and print it
}

return 0;
}

จากตัวอย่าง code ด้านบน

  • ptr คือ pointer ที่ถูกกำหนดให้ชี้ไปยังข้อมูลตัวแรกของ Array arr
  • ขนาดของ Array หาได้ด้วยการคิด sizeof(arr)/sizeof(arr[0]) ซึ่งจะได้จำนวนข้อมูลทั้งหมดใน Array
  • for loop ใช้สำหรับวน loop ไปทีละ item ใน Array ภายใน loop จะคำนวณที่อยู่หน่วยความจำของข้อมูลลำดับที่ i (เริ่มนับจาก 0) โดยใช้ ptr + i และใช้ *(ptr + i) ในการเข้าถึงข้อมูลที่ตำแหน่งนั้นๆ จริงๆออกมา
  • ในแต่ละรอบของการวน loop จะสั่งพิมพ์ข้อมูลที่กำลังดูออกมาด้วย โดยเลื่อน pointer ทีละตำแหน่งไปเรื่อยๆด้วยคำสั่งที่อยู่ใน for loop นั่นเอง

อธิบายเพิ่มเติมเรื่อง sizeof

  • คำสั่ง sizeof ใช้สำหรับการหาขนาดของตัวแปรที่ใช้ในหน่วยความจำ (ออกมาเป็นหน่วย bytes)
  • sizeof(arr) คำสั่งนี้จะบอกขนาดรวมของ Array arr เป็นหน่วยไบต์ (byte) ขนาดนี้ขึ้นอยู่กับชนิดข้อมูลที่เก็บใน Array และจำนวนข้อมูลทั้งหมด เช่น ถ้า arr เป็น Array ที่เก็บข้อมูลเลขจำนวนเต็ม (integer) 10 ตัว และในเครื่องที่ใช้เลขจำนวนเต็มแต่ละตัวใช้พื้นที่ 4 ไบต์ sizeof(arr) จะได้ค่า 10 * 4 = 40 ไบต์
  • sizeof(arr[0]) คำสั่งนี้จะบอกขนาดของข้อมูลหนึ่งตัวใดๆ ภายในอาร์เรย์ ในหน่วยไบต์ ตามตัวอย่าง ถ้าข้อมูลแต่ละตัวเป็นเลขจำนวนเต็มซึ่งใช้พื้นที่ 4 ไบต์ต่อตัว sizeof(arr[0]) ก็จะได้ค่า 4 ไบต์
  • การหารกัน (sizeof(arr) / sizeof(arr[0])) เป็นการหารขนาดรวมของ Array ด้วยขนาดของข้อมูลแต่ละตัวข้างใน จะทำให้เราได้จำนวนข้อมูลทั้งหมดที่มีอยู่ใน Array นั้นออกมาได้ ยกตัวอย่างเช่น Array ขนาด 40 ไบต์ บรรจุข้อมูลที่ใช้พื้นที่ตัวละ 4 ไบต์ จำนวนข้อมูลทั้งหมดคือ 40 / 4 = 10 ตัว นั่นเอง

และนี่คือตัวอย่างของการใช้งานระหว่าง Loop, Array และ pointer

Subtraction

ในภาษา C++ การลบตำแหน่งหน่วยความจำของสอง pointer ที่ชี้ไปยังตำแหน่งใน Array เดียวกัน ช่วยให้เรารู้ระยะห่างระหว่างสองสมาชิก (element) นั้น นอกจากนี้ยังใช้ในการเลื่อนตำแหน่งการชี้ไปข้างหน้าและถอยหลังภายในอาร์เรย์ได้ด้วย

ตัวอย่างที่ 1 คำนวนจำนวนของ element ระหว่าง pointer 2 ตัว

#include <iostream>

int main() {
int arr[] = {10, 20, 30, 40, 50};
int *startPtr = &arr[1]; // Pointer to the second element
int *endPtr = &arr[4]; // Pointer to the fifth element

// Calculate the distance between the pointers
int distance = endPtr - startPtr;

std::cout << "The number of elements between startPtr and endPtr is: "
<< distance << std::endl;

return 0;
}

ตัวอย่างที่ 2 ตัวอย่างนี้แสดงให้เห็นถึงการย้อนกลับไปยังข้อมูลก่อนหน้าภายใน Array โดยใช้การลบ pointer

#include <iostream>

int main() {
int arr[] = {10, 20, 30, 40, 50};
int *ptr = &arr[4]; // Pointer to the last element of the array

std::cout << "Traversing backwards: ";
for (int i = 4; i >= 0; --i) {
std::cout << *ptr << " ";
ptr--; // Move the pointer to the previous element
}

return 0;
}

และนี่ก็คือการใช้งาน pointer และ Array โดยประมาณ

Pointer และ Functions

ในภาษา C++ function สามารถทำงานร่วมกับ pointer ได้หลายวิธี ไม่ว่าจะเป็นการรับ pointer เป็นค่าสำหรับคำนวณ (argument) การคืนค่าออกมาเป็น pointer หรือแม้กระทั่งการใช้ pointer ที่ทำงานแทน function (function pointer) ก็สามารถทำได้เช่นกัน

Functions Taking Pointers as Arguments

Function สามารถรับ pointer เป็น argument ได้ ทำให้ function สามารถเข้าถึง และเปลี่ยนแปลงข้อมูลที่ตัวชี้นั้นชี้ไปได้ (รวมถึงการทำงานกับข้อมูลใน Array ได้ด้วย)

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

#include<iostream>

using namespace std;

void increment(int *value) {
(*value)++;
}

int main() {
int a = 5;
increment(&a); // Pass address of a
cout << a; // a is now 6
return 0;
}

ซึ่งสิ่งนี้คือ concept ที่ชื่อว่า Pass by reference หรือก็คือการส่ง reference ของตัวแปรเข้าไปแทน ทางผมขอเจาะลึกเพิ่มเติมไปยัง 2 concepts คือ Pass by Value และ Pass by reference

Pass by Value ค่าของตัวแปรจะถูกคัดลอกไปยัง parameter ของ function การเปลี่ยนแปลงค่า parameter ใน function ไม่ส่งผลต่อค่าของตัวแปรต้นฉบับ เช่นจากตัวอย่างนี้ที่จะไม่เปลี่ยนแปลงค่า a และ b ที่ส่งเข้า function ไป

void addNumbers(int a, int b) {
a = a + b;
}

int main() {
int num1 = 10, num2 = 20;
addNumbers(num1, num2);

// num1 ยังมีค่า 10
cout << num1 << endl;
}

Pass by Reference ตัวแปรจะถูกส่งผ่าน reference ไปยัง function การเปลี่ยนแปลงค่า parameter ใน function ส่งผลต่อค่าของตัวแปรต้นฉบับ เช่นจากตัวอย่างนี้ที่จะไม่เปลี่ยนแปลงค่า a และ b ที่ส่งเข้า function ไป แต่เปลี่ยนจากรับค่าตัวแปรเป็น “รับค่า address ของตัวแปร” เมื่อ run function จนจบ ตัวแปร num1 จึงโดนเปลี่ยนแปลงได้จากการเปลี่ยนแปลงค่า a ใน function addNumbers()

#include <iostream>
using namespace std;

void addNumbers(int &a, int &b) { a = a + b; }

int main() {
int num1 = 10, num2 = 20;
addNumbers(num1, num2);

// num1 จะมีค่า 30
cout << num1 << endl;

และสำหรับ pointer นั้นเนื่องจากเป็นตัวแปร ที่เก็บ “address ของตัวแปร” เอาไว้ ดังนั้นตัวมันเองหากเป็นการส่งตัวแปร pointer เข้าไปใช้งานภายใน function จึงมีคุณสมบัติเป็น “Pass by reference ต่อตัวแปรที่ reference” อยู่แล้ว

Functions Returning Pointers

Functions นั้นสามารถ return เป็น pointer ออกมาได้เช่นเดียวกัน โดยปกติจะมีประโยชน์มากสำหรับการ return array จาก function ออกมาได้

เราต้องเข้าใจก่อนว่าภาษา C++ นั้นเป็นภาษาที่จะ return array ออกมาไม่ได้ ดังนั้น pointer จึงมีประโยชน์สำหรับกรณีที่เรามีความจำเป็นต้องให้ function คืน array ออกมา

เช่นตัวอย่างนี้

#include <iostream>
using namespace std;

int *createArray(int size) {
int *arr = new int[size]; // Dynamically allocate memory for the array

// Initialize the array
for (int i = 0; i < size; ++i) {
arr[i] = i * i; // Example initialization: store square of index
}

return arr; // Return the pointer to the dynamically allocated array
}

int main() {
int size = 5;
int *myArray = createArray(size); // Calls the function

// Print the array elements
cout << "Array elements: ";
for (int i = 0; i < size; ++i) {
cout << myArray[i] << " ";
}
cout << endl;

delete[] myArray; // Delete the dynamically allocated array to avoid memory
// leak

return 0;
}

จากตัวอย่างนี้

  • createArray จะรับขนาดของ Array ที่ต้องการเป็น argument เข้าไป ต่อมาจะสั่งให้เครื่องจองพื้นที่ในหน่วยความจำสำหรับ Array ขนาดที่ส่งมา กรอกข้อมูลเริ่มต้น และคืนค่า pointer ที่ชี้มาที่ข้อมูลตัวแรกของ Array กลับคืนไป
  • ส่วนของ code หลัก ที่เรียก function นี้ (ในตัวอย่างคือ main function) จะเก็บ pointer ที่ได้รับมา และใช้งานผ่าน poointer เพื่อเข้าถึงข้อมูลใน Array
  • สุดท้ายก็จะสั่งลบ Array นี้ด้วย delete[] เพื่อปล่อยพื้นที่หน่วยความจำกลับคืนมา

Function Pointers

Function pointer คือตัวแปรชนิดพิเศษที่ใช้เก็บที่อยู่หน่วยความจำของ function ประโยชน์ก็คือทำให้เรียกใช้งาน function ทางอ้อมได้ หรือจะส่ง function เป็น argument ให้ function อื่นๆก็ทำได้ หรือแม้แต่เก็บ list ของ function ไว้หลายๆ function ก็ทำได้เช่นกัน

ตัวอย่างที่ 1

#include <iostream>
using namespace std;

void greeting() { cout << "Hello, World!" << endl; }

int main() {
void (*funcPtr)() = greeting; // Declare a function pointer and initialize it
(*funcPtr)(); // Call the function using the pointer
return 0;
}

จาก code ด้านบน

  • funcPtr เป็น pointer ที่ชี้ไปยัง function ที่ไม่รับค่า argument ใดๆเข้ามา และไม่มีค่าที่คืนกลับมา (return value เป็น void)
  • โดย funcPtr เก็บที่อยู่ของ function greeting() เอาไว้ หลังจากนั้น funcPtr ก็ถูกใช้เพื่อเรียกฟังก์ชัน greeting ได้

ซึ่งสิ่งนี้เองเป็นการเพิ่มคุณสมบัติให้ C++ สามารถทำ Callback function ออกมาได้

  • callback function คือ function ที่ถูกส่งให้กับ function อื่นในฐานะ argument โดยเราตั้งใจให้เจ้าตัวที่รับไป "เรียก function นั้นกลับมา" ใช้ภายหลังตอนถึงช่วงเวลาที่เหมาะสมของ function ปลายทาง
  • กลไกนี้ช่วยให้เราเขียน code ที่มีความยืดหยุ่น เพราะสามารถส่ง function ไปมาให้กันเรียกใช้งานตามเงื่อนไขบางอย่างหรือเมื่อมีเหตุการณ์เกิดขึ้นได้
  • Function pointer เหมาะมากที่จะใช้สร้าง callback เพราะ function pointer สามารถเก็บที่อยู่ของ function และเราก็สั่งเรียกใช้โดยอาศัยที่อยู่นั้นได้
  • เทคนิคนี้มีประโยชน์มากในการเขียนโปรแกรมที่รับเหตุการณ์ต่างๆ (event-driven programming) อย่างพวกโปรแกรมที่มีหน้าจอผู้ใช้ (GUI) หรือ ใน algorithm ที่เราต้องการความเฉพาะ เช่น การเรียงลำดับ (sort) หรือ ค้นหา (search) ที่เราได้กำหนดเงื่อนไขเองได้ (ใน javascript ใช้ concept นี้บ่อยมาก และเดี๋ยวจะมีการพูดถึงสิ่งเหล่านี้ใน c++ ภายหลังอีกที)

ตัวอย่างที่ 2 นี่คือตัวอย่างของ Callback function

#include <iostream>
using namespace std;

// Callback function that squares a number
void square(int n) { cout << n * n << " "; }

// Callback function that doubles a number
void doubleNumber(int n) { cout << n * 2 << " "; }

// Function that takes an array, its size, and a callback function as parameters
// It applies the callback function to each element of the array
void processArray(int *array, int size, void (*callback)(int)) {
for (int i = 0; i < size; ++i) {
callback(array[i]); // Calling the callback function on each array element
}
cout << endl; // End the line after processing the array
}

int main() {
int myArray[] = {1, 2, 3, 4, 5};
int size = sizeof(myArray) / sizeof(myArray[0]);

cout << "Squaring array elements: ";
processArray(myArray, size,
square); // Pass the 'square' function as a callback

cout << "Doubling array elements: ";
processArray(myArray, size,
doubleNumber); // Pass the 'doubleNumber' function as a callback

return 0;
}

จากตัวอย่าง code ด้านบน

  • เริ่มด้วยการสร้าง function callback อย่างง่าย 2 function ชื่อ square และ doubleNumber โดยแต่ละ function รับตัวเลขมาตัวนึง และทำหน้าที่ง่ายๆ คือ คูณด้วยตัวเอง และคูณด้วย 2 ตามลำดับ
  • ฟังก์ชัน processArray จะรับ array และ function pointer เข้ามา function นี้จะทำงานวน loop ไปแต่ละตัวใน Array และจะเอา function ที่ชี้มาจาก function pointer ไปใช้กับแต่ละตัวภายใน Array
  • ภายในฟังก์ชัน main เราจะเรียกใช้ processArray สองครั้งแต่ใส่ callback คนละตัวกัน เพื่อเป็นการโชว์ว่า Array เดียวกันสามารถถูก "จัดการ" ด้วยวิธีต่างกันได้ ขึ้นอยู่กับ function callback ที่เราส่งไปให้

จากตัวอย่างนี้ นี่คือประโยชน์ของ callback function ที่มอบความยืดหยุ่นให้ code C++ โดยทำให้เราสร้างชุดคำสั่งเดียว และใช้งานกับ function ต่างๆ ได้ด้วยการใส่ callback เข้าไปเป็น argument แทนได้นั่นเอง

และนี่ก็คือ Pointer และตัวอย่างของการใช้งาน Pointer โดยประมาณ หัวข้อต่อๆไป เราจะมีโอกาสหยิบมาใช้อีกแน่นอน ดังนั้น concept Pointer จะอยู่กับหัวข้อเราไปตลอดเช่นกัน