/ 365วันแห่งโปรแกรม

[365 วันแห่งโปรแกรม #day16] Pointer

วันที่สิบหกของ ‪#‎365วันแห่งโปรแกรม‬ วันนี้เราจะมีคุยกันเรื่อง Pointer


Pointer คืออะไร?

คนที่เคยเขียนโปรแกรมในภาษาเก่าๆ หน่อย ก็อาจจะเคยได้ยินคำว่า Pointer มาบ้าง แล้วมันคืออะไรล่ะ? Pointer เป็น programming language object ชนิดหนึ่งที่ใช้ในการชี้ไปยังค่าอื่นที่อยุ่บน memory Pointer สามารถชี้ไปยังตำแหน่งต่างๆ ของ memory และอ่านค่าที่ตำแหน่งนั้นขึ้นมาได้ กระบวนการนี้เรียกว่า dereferencing

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

ใช้ Pointer แล้วดียังไง?

ในการเขียนโปรแกรมทั่วๆ ไปแล้ว เมื่อเราสั่งให้ตัวแปรหนึ่งมีค่าเท่ากับอีกตัวแปรหนึ่ง โปรแกรมจะคัดลอกค่าเดิมไปให้ตัวแปรอีกตัว ซึ่งเมื่อเราเปลี่ยนไปใช้ Pointer แทนที่โปรแกรมจะคัดลอกค่าเดิม โปรแกรมจะกำหนดให้ตัวแปร Pointer ของเรา ชี้ยังยังค่าของตัวแปรเดิมแทน ซึ่งทำให้ Performance ดีกว่าเดิมมาก ดังนั้น Pointer จึงเหมาะที่จะใช้ในการ Browse ไปในกลุ่มของข้อมูล เช่น อ่านค่าใน list หรือ tree

Pointer มี Type เหมือนตัวแปรอื่นหรือเปล่า?

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

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

int a = 5;
int* b = &a;

cout << a << endl; //5
cout << *b << endl; //5

cout << &a << endl; //001BF7C0
cout << b << endl; //001BF7C0

*b = 10;

cout << a << endl; //10
cout << *b << endl; //10

cout << &a << endl; //001BF7C0
cout << b << endl; //001BF7C0

int c = *b;

cout << a << endl; //10
cout << *b << endl; //10
cout << c << endl; //10

cout << &a << endl; //001BF7C0
cout << b << endl; //001BF7C0
cout << &c << endl; //001BF7A8

c = c + 5;

cout << a << endl; //10
cout << *b << endl; //10
cout << c << endl; //15

cout << &a << endl; //001BF7C0
cout << b << endl; //001BF7C0
cout << &c << endl; //001BF7A8

==output==
5
5
001BF7C0
001BF7C0
10
10
001BF7C0
001BF7C0
10
10
10
001BF7C0
001BF7C0
001BF7A8
10
10
15
001BF7C0
001BF7C0
001BF7A8

ตัวอย่างด้านบนเป็นโค้ดของภาษา C++ ในตัวอย่างนั้น เรามีตัวแปร a ชนิด int และมีค่าเท่ากับ 5 ต่อมาแล้วสร้าง pointer ของ int ชื่อ b และกำหนดใช้ชี้ไปยังตำแหน่งของค่าของ a (ใน C++ เราสามารถประกาศตัวแปรแบบ Pointer โดยการใช้เครื่องหมาย * หลัง type ของตัวแปร และในการอ้างถึงตำแหน่งบน memory ของตัวแปรนั้นให้ใส่เครื่องหมาย & หน้าชื่อตัวแปร) เมื่อเราลองพิมพ์ค่าของทั้ง a และ b ดู ก็พบว่าเท่ากับ 5 ทั้งคู่ และตำแหน่งบน memory เป็น 001BF7C0 หมายความว่าทั้งสองตัวแปรอ้างอยู่ที่ตำแหน่งบน memory เดียวกัน ต่อมาลองแก้ค่าของ b เป็น 10 แทน แล้วลองพิมพ์ออกมาอีกครั้ง ก็พบว่าได้ 10 เท่ากัน และยังอ้างที่ตำแหน่งเดียวกนอยู่ ต่อมาเราสร้างตัวแปร c เป็น int ปกติ แล้วบอกให้มีค่าเท่ากับค่าที่ b อ้างอยู่ แล้วลองพิมพ์ดูก็พบว่าได้ 10 เท่ากันหมด แต่ c อ้างอยู่ที่ตำแหน่งบน memory ต่างออกไป หลังจากนั้นเราลองเพิ่มค่า c เป็น 15 แล้วพิมพ์ค่าทั้งหมดอีกครั้ง ซึ่งพบว่า a และ b ยังคงเท่ากับ 10 แต่ c เท่ากับ 15 a และ b อ้างในตำแหน่ง 001BF7C0 ส่วน c อ้างที่ตำแหน่ง 001BF7A8

ในภาษา OO สมัยใหม่มี Pointer ไหม

ในภาษาสมัยใหม่ส่วนใหญ่ไม่อนุญาตให้เราสร้าง Pointer ขึ้นมาตรงๆ แบบที่มีใน C/C++ แต่ใช้วิธีบังคับให้ตัวแปรที่ complex ทุกตัวเป็นตัวแปรแบบ Reference-Type เสมอ ซึ่งก็ทำตัวเหมือนเป็น type safe pointer เช่นกัน

‪#‎day16 #365วันแห่งโปรแกรม ‪#‎โครงการ365วันแห่ง‬...