Friday, July 17, 2015

พอยน์เตอร์ คืออะไร ?

พอยน์เตอร์ (Pointer) คือตัวชี้ไปยังตำแหน่งในเมมโมรี พูดถึงตัวชี้ (หนังสือบางเล่มใช้คำว่า ดัชนี) คงจะนึกภาพไม่ออกว่าคืออะไรในคอมพิวเตอร์ พอยน์เตอร์คือรีจิสเตอร์ (register) ตัวหนึ่งซึ่งถูกใช้เพื่ออ้างอิงตำแหน่งในเมมโมรี ในคอมพิวเตอร์มีรีจิสเตอร์จำนวนมากมาย เวลาที่โปรแกรมทำงานทุกๆอย่างในโปรแกรมเช่น คำสั่ง ตัวแปร ค่าของตัวแปร ค่าคงที่ของโปรแกรมจะถูกโหลดเข้าไปไว้ในเมมโมรี   ทั้งนี้เนื่องจากสถาปัตยกรรมคอมพิวเตอร์ในปัจจุบันส่วนใหญ่ทำงานตามสถาปัตยกรรม von Neumann  (เจ้าของชื่อเต็มๆว่า John von Neumann) ซึ่งคอมพิวเตอร์มีองค์ประกอบหลัก ส่วน คือ Input, Output, Processor (มี ALU และ Control Unit เป็นองค์ประกอบ) และ Memory ในระหว่างที่คอมพิวเตอร์ทำการประมวลผลจะมีการเรียกใช้งานรีจิสเตอร์ตลอดเวลา
                 
จากภาพด้านบน  พอยน์เตอร์เก็บตำแหน่งในเมมโมรีคือ #100  ข้อมูลที่เก็บในตำแหน่งนั้นอาจเป็นค่าข้อมูล  หรือค่าตำแหน่งก็ได้ ขึ้นกับว่าคำสั่งที่เกี่ยวข้องกับการใช้งาน Pointer นั้นมี Addressing Mode อย่างไร (ศึกษาต่อเรื่อง Memory Addressing Mode)


การใช้งานพอยน์เตอร์ในภาษาการโปรแกรมต่างๆ  เกี่ยวข้องกับการกำหนดค่าโดยเอาตำแหน่งในเมมโมรีของตัวแปรหนึ่งให้อีกตัวแปรหนึ่ง ซึ่งสิ่งที่จะตามมาคือ หากการใช้งานตัวแปรทั้งสองอยู่ในขอบเขต (scope) การทำงานเดียวกัน  ดังนั้นจะเกิดปัญหา Aliasing คือ การอ้างอิงไปยังตำแหน่งในเมมโมรีหนึ่งๆ ซึ่งสามารถทำได้โดยผ่านตัวแปรมากกว่า ตัวแปร  ผลที่ต้องระวังตามมาคือ หากมีการแก้ไขค่าผ่านตัวแปรตัวใดตัวหนึ่ง ตัวแปรทั้งสองนั้นจะมีค่าเดียวกันทันที (โปรแกรมเมอร์ต้องจำเพิ่มว่าโดนแก้ในตำแหน่งไหนในโปรแกรม ไล่กันยาวถ้าใช้ตัวแปรทั้งสองตัวโดยไม่ระวัง)  เช่น ในภาษา C
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
void main()
{
  int *p;
  int  q;
  q =10;
  p = &q;
  printf("p = %d, q = %d",*p, q);
  *p = 20;
  printf("p = %d, q = %d",*p, q);
}

สมมติว่าโค้ดดังกล่าวอยู่ในฟังก์ชั่น main( ) เราจะถือว่าคำสั่งทั้งหลายนั้นทำงานภายในขอบเขตเดียวกัน ซึ่งก็คือฟังก์ชั่น main นั่นเอง 
ในบรรทัดที่ 7 พอยน์เตอร์ p จะเก็บตำแหน่งที่อยู่ของตัวแปร q  สมมติอยู่ที่ตำแหน่งที่ 100 


ในบรรทัดที่ ค่าของ และ ที่แสดงผลจะมีค่าเท่ากับ 10 
ในบรรทัดที่ การกำหนด *p หมายถึงการแก้ไขค่าข้อมูลที่พอยน์เตอร์ ชี้อยู่  ซึ่งค่าข้อมูลจะถูกแก้ไขเป็น 20 ดังนั้นบรรทัดที่ 10 จะแสดงค่าของ และ ซึ่งเท่ากับ 20 
ข้อดีในการใช้งานพอยน์เตอร์คืออะไร ?

จากโค้ดที่ผ่านมาถ้าพอยน์เตอร์ถูกใช้งานภายในฟังก์ชั่นเดียวกันจะเกิดปัญหา Aliasing แล้วทำไมเราเลือกใช้พอยน์เตอร์  คำตอบคือมันดีสำหรับการสำเนาข้อมูลในเมมโมรีขนาดใหญ่  ไปไว้ในพื้นที่ที่ต้องการประมวลผลข้อมูลเป็นพิเศษเพียงชั่วคราว  จะขอยกตัวอย่างการใช้งานพอยน์เตอร์ในฟังก์ชั่น เมื่อมีการส่งผ่านค่าเออร์กูเมนต์  (Argument: ตัวแปรที่เป็นอินพุตที่ถูกส่งให้ฟังก์ชั่น ) ให้กับพารามิเตอร์ (Parameter: ตัวแปรที่รับค่าภายในฟังก์ชั่นในฟังก์ชั่น 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
void main()
{
   int  q, returnresult;
  q =10;
  printf("q = %d ", q);
  myfunction(&q);
  printf("q = %d ", q);
}
void myfunction(int *p){
   printf("p = %d ",*p);
  *p = 20;
   printf("p = %d", *p);
}

จากโค้ดข้างต้น  และ ถือว่าทำงานภายในขอบเขตที่แตกต่างกัน จะไม่เกิดปัญหา Aliasing ตัวแปร ทำงานในฟังก์ชั่น main ขณะที่ตัวแปร ทำงานภายในฟังก์ชั่น  การส่งค่าคือตำแหน่งในเมมโมรีของ คือ การทำสำเนาค่าข้อมูลในตำแหน่งนั้นให้กับตัวแปรของฟังก์ชั่น     เมื่อโปรแกรมรันมาถึงบรรทัดที่ จะเกิดการจองพื้นที่ (memory allocation) ในเมมโมรีสำหรับเก็บตัวแปร ค่าของตัวแปร และคำสั่งของฟังก์ชั่น  แต่พื้นที่นี้จะอยู่ชั่วขณะจนกระทั่งออกจากฟังก์ชั่น (กลับไปทำงานต่อที่บรรทัดที่ 9 ) พื้นที่จะหายไป แต่ค่าที่ถูกแก้ไขจะถูกสำเนากลับให้กับตัวแปรเออร์กูเมนต์ต้นทาง ดังนั้นการใช้งานพอยน์เตอร์ ในฟังก์ชั่น จะเป็นการทำสำเนาค่าของตัวแปร มาไว้ในพื้นที่ส่วนของฟังก์ชั่นและค่าข้อมูลที่ถูกปรับปรุงจะถูกสำเนากลับไปยังเออร์กูเมนต์ต้นทาง 
ถ้าเรานึกถึงการส่งตัวแปรพารามิเตอร์ที่เป็นชนิด struct นั่นก็หมายถึงการสำเนาข้อมูลที่มีโครงสร้าง (ซึ่งมักจะมีข้อมูลมากๆ) และในกรณีนี้เรานำข้อมูลใหญ่ๆนั้นมาประมวลผล  โดยที่ต้นฉบับ (เออร์กูเมนต์) ที่ส่งมาถูกแก้ไขด้วยพารามิเตอร์ภายในฟังก์ชั่น 
การใช้งานพอยน์เตอร์จึงมีประโยชน์แทนการส่งเออร์กูเมนต์หลายๆตัวเข้าสู่ฟังก์ชั่นและการใช้งานเสมือนการรีเทิร์นค่ากลับไปยังเออร์กูเมนต์  (การใช้พารามิเตอร์ของฟังก์ชั่นทำงานในโหมด in-out parameter mode)  
       
จากโค้ดตัวอย่างพอยน์เตอร์ p ในฟังก์ชั่นถูกแก้ไขให้มีค่าเป็น 20 และค่านั้นจะถูกสำเนากลับไปยังตำแหน่งของตัวแปร q ให้เป็น 20 ก่อนที่จะออกจากฟังก์ชั่น 

สรุป สิ่งที่เราจะต้องเข้าใจ
  1.   ถ้าใช้พอยน์เตอร์ภายใน Scope เดียวกันกับตัวแปรที่ถูกอ้างอิงจะเกิด Aliasing การเข้าถึงเมมโมรีในตำแหน่งหนึ่งๆ ที่สามารถเข้าถึงได้จากตัวแปรมากกว่า ตัวแปร
  2.  ถ้าใช้พอยน์เตอร์เพื่อรับค่าที่ส่งมาในฟังก์ชั่น เป็นการสำเนาค่าข้อมูลในตำแหน่งที่พารามิเตอร์ชี้อยู่  ไม่เกิด Aliasing แต่มีการสำเนาค่าที่ถูกปรับปรุงกลับไปก่อนออกจากการทำงานของฟังก์ชั่น

No comments:

Post a Comment