อธิบาย Pointers ภาษาคนธรรมดา
Pointers คืออะไร อธิบายแบบภาษาคนธรรมดา อ่านแล้วไม่ตาลอย (หวังว่านะ)

อ่านแล้วไม่ตาลอย หวังว่านะ
Memory Address
ใน memory ของคอมพิวเตอร์เรา ประกอบด้วย block ซึ่งเราจะแทนมันด้วยถัง ถังเยอะ ๆ เลย แต่ละถังจะแปะเลข address เอาไว้อยู่ เอาไว้ใช้ระบุความแตกต่าง และแต่ละถังเก็บ value ได้ก้อนเดียว
เวลาเราสร้างตัวแปรแล้วใส่ value ให้มัน จะเหมือนเราเอา value ไปเก็บลงในถัง แล้วจดไว้ว่า ถ้าอยากได้ค่าของตัวแปรชื่อนี้ ต้องไปหาที่ถังเลขนี้นะ
ตัวอย่างเช่น เวลาประกาศ i = 1 มันก็จะไปหยิบถังมาใบนึง ใส่เลข 1 เข้าไป แล้วก็จดใส่กระดาษไว้ว่า ค่าของตัวแปรชื่อ i จะเก็บไว้กับถังที่มี address นี้นะ

เวลาเราอยากได้ค่าจากตัวแปร iเราก็จะหยิบกระดาษมาดู ว่าเราจะต้องไปหาถังเลขไหน แล้วหยิบ value ในถังมาดูเลย เช่น ถ้าตั้งไว้ว่า i = 1เวลา print i ออกมา ก็ได้ค่าเป็น 1 อันนี้ปกติ
เหมือนกันแต่ไม่ใช่
ถ้าสมมติเราเขียนว่า j = iแล้วเอามาเทียบ value กัน มันจะบอกว่าค่าเท่ากัน แต่ถ้าถามว่ามันคือตัวเดียวกันไหม อันนี้ไม่ใช่
เพราะสิ่งที่เกิดขึ้นเมื่อประกาศตัวแปร j คือ หยิบค่าในถัง i มาดูว่ามันเป็นเท่าไร แล้วจำค่านั้นไว้ เอามาใส่ในถังใหม่อีกถังนึง
ทำให้ตอนนี้เรามี 2 ถัง ที่ของข้างในหน้าตาเหมือนกัน ถามว่า i “เท่ากับ” j ไหม ใช่

แต่ว่าใน 2 ถังนี้ มันกำลังหมายถึง ของก้อนเดียวกันไหม ไม่ ถ้าเราแก้ค่าของในถัง i ค่าในถัง j จะไม่เปลี่ยนตาม
ถ้าอยากให้เรียกถัง j แล้วสามารถพาไปดูของในถัง i ได้ ต้องทำยังไงดี งั้นเราต้องใช้ address เพื่อให้มันนำทางไปหาถังที่เก็บค่าของ i ให้ได้
สิ่งนี้แหละ คือ pointer
Pointers
Pointers เป็นตัวแปรที่จะเก็บ address ใน memory ในที่นี้คือ เลขบนถัง แทนที่ปกติจะเก็บ value ทั่วไป
พอเรารู้ address แล้ว มันก็พาเราไปหาถังที่เราต้องการ และหยิบของข้างในดูได้ ว่ามันเก็บ value อะไรไว้
ที่เราต้องทำก็แค่ไปหา address ของตัวแปร i ออกมาใส่ใน j ให้ได้ แล้วทีนี้ทำยังไง
ถ้าในภาษา C หรือ Golang เราใส่ & เติมไปข้างหน้าตัวแปรได้เลย จะได้ค่า address บน memory ของตัวแปรนั้น ๆ มา อย่างเช่น j = &i
ทีนี้ตัวแปร j จะแปลงร่างเป็น pointer เรียบร้อย พร้อมเอาไปใช้งาน ถ้า print ออกมา จะได้ค่าเป็นเลข address เลย

ตอนนี้เราหาถังเจอแล้ว แล้วทำยังไงถึงจะหยิบของในถังออกมาดูได้ เราสามารถทำได้โดยใส่ * ด้านหน้า pointer จะได้เป็น *j พอเอาไป print เราจะได้ของที่เก็บไว้ใน i แล้ว เย่
ด้วยสิ่งนี้ เวลาเราแก้ไข value ผ่าน pointer j ค่าในตัวแปร i จะเปลี่ยนไปโดยปริยาย เพราะทุกคนกำลังมองมาที่ถังเดียวกัน
ทำทำไม?
แล้วทำไมต้องทำขนาดนี้ด้วยล่ะ ถ้าอยากเรียกใช้ หรือแก้ไขค่าใน i เราไม่เรียกตรง ๆ เลยไม่ดีกว่าเหรอ
มันจะมีบางเคส ที่เราเรียกตรง ๆ ไม่ได้ เช่น ตัวแปรเรามันเป็นตัวแปรแบบ global scope แล้วเราเรียก function ที่จะให้มันไปแก้ไขค่าในตัวแปร ถ้าเราโยนตัวแปรจากข้างนอก เข้าไปแบบปกติตรง ๆ เลย มันก็จะแก้ไขแค่ใน function scope แต่ตัวที่อยู่ข้างนอก ไม่รับรู้อะไรด้วย
เพราะเราไม่ได้ไปแก้ถังนั้น มันสร้างถังใหม่ตั้งแต่ตอนเราโยนตัวแปรเข้าไปใน function แล้ว
เราเลยต้องโยน address ของตัวแปรข้างนอกเข้าไปแทน เพื่อบอกให้ function รู้ ว่านายต้องไปแก้ไขค่าที่ถังนี้นะ
เอาแบบเห็นเป็นโค้ดเลย จะได้แบบนี้ (ผมดัดแปลงมาจากโค้ดของ BornToDev นะครับ)
void addFiveByValue(int number)
{
number += 5;
}
void addFiveByPointer(int * number)
{
* number += 5;
}
int main()
{
int myNum = 1;
int * myPointer = &myNum; // หยิบ address ของ myNum มาเก็บไว้ที่ myPointer
addFiveByValue(myNum); // เรียก function ที่ใช้ตัวแปรปกติ
printf("myNum (not using pointer): %d\n", myNum);
// myNum (not using pointer): 1
addFiveByPointer(myPointer); // เรียก function ที่ใช้ pointer
printf("myNum (using pointer): %d\n", myNum);
// myNum (using pointer): 6
return 0;
}
อย่าสับสน
สิ่งหนึ่งที่ทำให้ผมสับสนเรื่อง pointer โดยไม่จำเป็น คือ หน้าตาของ type มันนี่แหละ เพราะถ้าเราจะประกาศ pointer ที่จะพาเราไปหาค่า integer ถ้าเป็นภาษา C จะเขียนว่า int * ดูแค่นี้จะไม่ค่อยสับสน แต่ถ้าเป็นหน้าตาเต็ม ๆ มันจะเป็นแบบนี้ เขียนได้ 3 แบบ
int * j;
int* j;
int *j;
ตัวที่พาผมงง คือ int *j เพราะหน้าตามันเหมือนเวลาเรากำลังหยิบ value ออกมาจาก address แต่เอ๊ะตอนนี้เราเพิ่งประกาศตัวแปรนะ มันใช้ยังไงกันแน่เนี่ย
ถีงหน้าตาจะเหมือนกัน แต่เวลาเราเขียน อยากให้ดูดี ๆ ว่าเรากำลังประกาศตัวแปรอยู่ หรือกำลังไปหยิบ value ออกมา จะได้ไม่สับสนแบบผมครับ
จบแล้ว
Pointer จะเป็นเรื่องแรก ๆ เลย ที่เราจะได้เรียนเวลาศึกษาภาษา C และด้วยความที่มันลงไประดับ low level มาก ๆ ไปถึง memory เลย จึงอาจจะยาก และ mind blow ไปมาก ๆ สำหรับมือใหม่ รวมถึงผมตอนที่กำลังหัดด้วย
คิดว่าน่าจะดี ถ้าเราสามารถเล่าสิ่งนี้เป็นด้วยภาษามนุษย์คุยกัน เลยอยากลองเอามาเล่าให้ทุกคนฟังครับ ไม่รู้ว่าจะเข้าใจขึ้น หรืองงกว่าเดิม ฮ่าาาา
อ่านต่อ
- Pointers in C Explained - They're Not as Difficult as You Think
- Pointer คืออะไร ? - BorntoDev เริ่มต้นเรียน เขียนโปรแกรม ขั้นเทพ !
อธิบาย Pointers ภาษาคนธรรมดา was originally published in odds.team on Medium, where people are continuing the conversation by highlighting and responding to this story.