พอยเตอร์(Pointer)
พอยเตอร์คือต้นฉบับของชนิดข้อมูล เป็นชนิดข้อมูลที่สร้างจากข้อมูลมาตรฐานขนิดหนึ่งค่าขงอมันก็คือตำแหน่ง (Address) ที่อยู่ในหน่วยความจำของคอมพิวเตอร์ ซึ่งจะใช้สำหรับกำหนดค่าหรือเข้าถึงข้อมูล พอยเตอร์นั้นสร้างจากแนวความคิดพื้นฐานของ Pointer Constants

Pointer Values
Pointer Values คือ ค่าตำแหน่ง Address ของตัวแปรนั้น ถ้าต้องการค่าของ Address ของตำแหน่งของตัวแปรใด หรือจะกำหนดค่าที่รับเข้ามาทางคีย์บอร์ดให้ไปเก็บไว้ที่ตัวแปรนั้นจะต้องใช้ ดเครื่องหมาย Address หรือ & ดังตัวอย่างด้านล่างแสดงการใช้ตัวแปร aChar


&aChar
รูปที่ 9-1 แสดงตำแหน่ง Address ของตัวแปร

ตัวแปรพอยเตอร


ถ้าผู้ใช้มี Pointer Constant และ Pointer Value ผู้ใช้ก็สามารถมี Pointer Variable หรือตัวแปรพอยเตอร์ได้ และผู้ใช้ก็สามารถบรรจุ Address ของตัวแปรตัวหนึ่งให้กับตัวแปรอีกตัวหนึ่งได้ ซึ่งแสดงในรูปที่ 9-2
รูปที่ 9-2 แสดงลักษณะของตัวแปรพอยเตอร์
ผู้ใช้จะต้องแบ่งระหว่างตัวแปรกับค่าของมัน รูปที่ 9-2 แสดงรายละเอียดที่แตกต่างกันในรูปแสดงให้เห็นว่า ตัวแปร a มีค่า –123 และตัวแปร a นั้นตั้งอยู่ในตำแหน่งที่ 234560 ในหน่วยความจำ แม้ว่าชื่อขงองตัวแปรแบะตำแหน่งจะเป็นค่าคงที่ แต่ค่าเหล่านั้นก็สามารถเปลี่ยนแปลงได้ เมื่อโปรแกรมทำไปแล้ว ในรูปนี้มีตัวแปรพอยเตอร์ p อยู่ด้วยพอยเตอร์จะมีชื่อและตำแหน่งอยู่ด้วย ซึ่งทั้งคู่ก็เป็นค่าคงที่ด้วยเช่นกัน ค่าของมันในตำแหน่งนี้คือ ตำแหน่งของหน่วยความจำที่ 234560 ความหมายคือ p ชี้ไปยังตำแหน่งที่ a อยู่ในรูปที่ 9-2 ลักษณะทางกายภาพได้แสดงถึวข้อมูลและตัวแปรพอยเตอร์ที่อยู๋ในหน่วยความจำ ส่วนในลักษณะทางความคิดแสดงให้เห็นความสัมพันธ์ระหว่างสิ่งเหล่านั้น
ผู้ใช้สามารถที่กำหนดตำแหน่ง Address ของตัวแปรให้กับตัวแปรพอยเตอร์ได้มากกว่าหนึ่งตัว ซึ่งแสดงตัวอย่างในรูปที่ 9-3 ในรูปนี้จะมีตัวแปร a และตัวแปรพอยเตอร์ p และ q ซึ่งแต่ละพอยเตอร์ทั้งสองจะมีชื่อและตำแหน่งที่เป็นค่าคงที่ และทั้งคู่มีค่าที่ชี้ไปยังตำแหน่งหน่วยความจำที่ 234560 หมายความว่าทั้ง p และ q ชี้ไปยังที่ตัวแปร a และตัวแปรพอยเตอร์ที่จะชี้ไปยังตำแหน่ง Address ของตัวแปรตัวเดียวกันนั้นสามารถมีได้ไม่จำกัดจำนวน



รูปที่ 9-3 แสดงการใช้ตัวแปรพอยเตอร์หลายตัวชี้ไปที่ตัวแปรเดียวกัน

การเข้าถึงตัวแปรพอยเตอร์

          ในขณะนี้ผู้ใช้มีตัวแปรและมีพอยเตอร์ที่ชี้ไปยังตัวแปรตัวนั้น เมื่อไรที่ผู้ใช้ต้องการพอยเตอร์และต้องการเข้าถึงค่าที่พอยเตอร์ตัวนั้นชี้ อยู่ จะต้องใช้ตัวดำเนินการ Indirection หรือ * ยกตัวอย่างเช่น ถ้าต้องการเข้าถึงค่าของตัวแปรที่มีพอยเตอร์ p ชี้อยู่ ก็สามารถเขียนได้ดังนี้
*p
อีกตัวอย่างหนึ่ง ถ้าผู้ใช้ต้องการที่จะบวก 1 ให้กับตัวแปร a ผู้ใช้สามารถทำได้ อย่างเช่นใช้ชุดคำสั่งปกติ หรือสมมุติว่ามีพอยเตอร์ p และกำหนดให้ p = &a จะเขียนชุดคำสั่งได้ดังนี้
a++; a=a+1; *p=p+1; (*p)++;
ในตัวอย่างชุดท้าย (*p)++ ผู้ใช้ต้องใช้วงเล็บตามตัวอย่าง ไม่เช่นนั้นโปรแกรมจะผิดพลาดขึ้นมาทันที เพราะนิพจน์แบบ Postfix แบบเพิ่มค่า มีลำดับความสำคัญอยู่ที่ 16 แต่เครื่องหมาย * มีลำดับความสำคัญอยู่ที่ 15 ฉะนั้นการทำงานโดยไม่ใส่วงเล็บจะเป้ฯการเพิ่มค่าของตำแหน่งที่อยู่ที่ p เก็บอยู่ไปอีก 1 ก่อน แล้วจึงไปนำค่าในตำแหน่งที่อยู่ใหม่ออกมาแทน
รูปที่ 9-4 จะแสดงตัวอย่างการเข้าถึงต่างๆ ซึ่งมีตัวแปร x และมีตัวแปรพอยเตอร์ p และq ที่ชี้ไปยังตัวแปร a

รูปที่ 9-4 แสดงตัวอย่างการเข้าถึงค่าที่พอยเตอร์ชี้ในแบบต่างๆ

เครื่องหมาย Indirection (*) และ address(&) จะเป็นเครื่องหมายที่มีความหามายตรงกันข้าม และเมื่อนำมารวมกัน เช่น *&x ก็จะมีความหมายเท่ากับ x นั่นเอง
รูปที่ 9-5 เครื่องหมาย Indirection และ Address

การประกาศและกำหนดลักษณะของพอยเตอร์

          รูปที่ 9-6 ผู้ใช้จะใช้เครื่องหมาย Indirection ในการประกาศและกำหนดลักษณะของตัวแปรพอยเตอร์ เมื่อทำตามนี้แล้วพอยเตอร์ก็จะยังไม่ชี้ไปยังตัวแปรใด จะทำการกำหนดค่าให้ก่อนเสมอเหมือนตัวแปรทั่วๆไป


รูปที่ 9-6 การประกาศตัวแปรแบบพอยเตอร์

ในรูปที่ 9-7 แสดงการประกาศตัวแปรพอยเตอร์แบบต่างๆ ซึ่งจะมีข้อมูลที่ตรงตามชนิดข้อมูล และพอยเตอร์ที่ประกาศจะมีชนิดข้อมูลเป็นดังนี้ p เป็นพอยเตอร์ชนิดตัวอักษร (Character),q เป็นพอยเตอร์ชนิดตัวเลขจำนวนเต็ม(Integer) และ r เป็นพอยเตอร์ชนิดตัวเลขทศนิยม (Floating – point)
รูปที่ 9-7 การประกาศตัวแปรพอยเตอร์
ในโปรแกรมที่ 9-1 เป็นการบรรจุ Address ของตัวแปรให้กับพอยเตอร์ และพิมพ์คำเหล่านั้นออกมาโดยใช้ทั้งตัวแปรและพอยเตอร์
โปรแกรมที่ 9-1 แสดงการใช้พอยเตอร์

#include<stdio.h>
#include<conio.h>
int main (void)
{
int a;
int *p;
clrscr();
a=14;
p=&a;
printf("%d\n",*p);
printf("Value of 'a' is %d and Address of 'a' is %p\n",a,&a);
printf("Address of 'p' is %p Value of '*p' os %d and Value of 'a' is %d\n",p,*p,a);
getch();
return 0;
}
ผลลัพธ์ที่ได้:
  1. 000135790
00135760 14 14
การกำหนดค่าเริ่มต้นของพอยเตอร์
ในภาษา C ถ้าไม่มีการกำหนดค่าเริ่มต้นให้กับตัวแปร เหมือนโปรแกรมเริ่มทำงานหน่วยความจำของตัวแปรนั้นจะมีค่าบางอย่างที่ไม่อาจ จะทราบได้
พอยเตอร์ก็เหมือนกับตัวแปร คือ เมื่อโปรแกรมเริ่มทำงานแล้ว ไม่ได้ทำการกำหนดค่าเริ่มต้นให้กับพอยเตอร์ ในหน่วยความจำของพอยเตอร์ตัวนั้นจะมีค่าบางอย่างที่ไม่อาจจะทราบได้ค่า บางอย่างนั้นคอมพิวเตอร์อาจจะนำไปใช้ไม่ได้ และถ้านำไปใช้อาจจะทำให้โปรแกรมเกิดการผิดพลาดขึ้นได้ ดังรูปที่ 9-8 จะแสดงตัวแปรและพอยเตอร์ที่ไม่มีการกำหนดค่า

รูปที่ 9-8 การประกาศตัวแปรพอยเตอร์
ปัญหาที่แสดงในรูปที่ 9-8 คือ ผู้ใช้ทำการกำหนดค่าให้ตัวแปรหรือพอยเตอร์เหล่านั้น
เช่น
int x;                                                     /*ตัวแปรชนิด int*/
                int p=&a;                                            /*pมีค่าของAddress*/
                p=89                                                      /*กำหนดค่า 89 ให้ a*/
จากตัวอย่างด้านบนในบรรทัดที่ 2 จะพบว่า มีการทำ 2 คำสั่งในบรรทัดเดียวกัน ซึ่งคำสั่งแสดงในรูปที่ 9-9



รูปที่ 9-9 การประกาศตัวแปรพอยเตอร์
และถ้าต้องการให้พอยเตอร์ชี้ไปที่ค่า NULL ก็สามารถทำได้ดังนี้
Int*p=NULL
เมื่อได้กำหนดพอยเตอร์ให้เป็น NULL ก็เท่ากับผู้ใช้ได้ใช้ Address ที่ 0
โปรแกรมที่ 9-2 แสดงการทำงานของพอยเตอร์

#include<stdio.h>
#include<conio.h>
int main (void)
{
int a;
int b;
int c;
int *p;
int *q;
int *r;
clrscr();
a = 6;                     //'p' =address of 'b'
b = 12;  //'q'=address of 'b'
p = &b; // 'r'=address of 'c'
q = p; //p = address of 'a'
r = &c; // Value of 'q' =8
p = &a; //Value of 'r' =6
*q = 8;
*r = *p;
*r= a + *q + *&c;
printf("%d %d %d\n",a,b,c);
printf("%d %d %d\n",*p,*q,*r);
getch();
return 0;
}
ผลลัพธ์ที่ได้:
6 8 20
6 8 20
ในโปรแกรมที่ 9-3 นี้จะเป็นการใช้พอยเตอร์ในการบวกเลขสองตัว ซึ่งจะมีตัวแปรต่างๆ ดังรูปที่ 9-10


รูปที่ 9-10 การบวกเลข 2 ตัว โดยใช้พอยเตอร์
โปรแกรมที่ 9-3 การบวกเลข 2 ตัวโดยใช้พอยเตอร์

#include<stdio.h>
#include<conio.h>
int main (void)
{
int a;
int b;
int c;
int *pa = &a;
int *pb = &b;
int *pc = &c;
clrscr();
printf("Enter the first number :");
scanf("%d",pa);
printf("Emter the second number :");
scanf("%d",pb);
*pc=*pa + *pb;
printf("\n%d+%d is %d",*pa,*pb,*pc);
getch();
return 0;
}
ผลลัพธ์ที่ได้:
Enter the first number :15
Enter the second number:51
15+51 is 66
พอยเตอร์กับฟังก์ชัน
ในการใช้พอยเตอร์กับฟังก์ชัน จะมีการใช้อยู่ 2 แบบ คือ

1.การใช้พอยเตอร์เป็นพารามิเตอร์(Pointer ass Formal Parameters) รูปที่ 9-11 และ 9-12 เป็นการสาธิตการใช้พอยเตอร์ ในรูปที่ 9-12 นั้น มีการเรียกใช้ฟังก์ชัน Exchange ซึ่งฟังก์ชัน Exchange นี้ต้องการตัวแปร 2 ตัว ส่งไปให้เมื่อผู้ใช้ใช้การส่งค่าแบบ Pass-by-value ข้อมูลที่แท้จริงในฟังกืชันทีเรียกจะไม่ถูกเปลี่ยนในฟังก์ชันที่ถูกเรียก
รูปที่ 9-11 แสดงการเปลี่ยนค่าที่ไม่ได้เปลี่ยนในตัวแปรจริง
ถ้าต้องการจะให้ค่าของตัวแปรตัวจริงสลับกัน จะต้องใช้พอยเตอร์เข้ามาช่วย หรือไม่ก็ประกาศตัวแปรเหล่านั้นแบบ Global
ในรูปที่ 9-12 แสดงการสลับค่าโดยใช้พอยเตอร์ให้สร้างพอยเตอร์ขึ้นมา แล้วเครื่องหมาย Address ในเวลาที่ส่งค่าไปให้กับฟังก์ชั่นอื่น ซึ่งแสดงดังตัวอย่างข้างล่าง จะส่งค่าตำแหน่ง Address ของตัวแปร a และ b ไปให้
exchange(&a,&b);
ในการใช้การส่งค่าโดย Address นี้ พารามิเตอร์ในฟังก็ชั่นที่ถูกเรียก จะต้องกำหนดเป็นตัวแปรพอยเตอร์ ดังตัวอย่างที่แสดงด้านล่าง

          void exchange(int *x,int *y);
รูปที่ 9-12 แสดงการเปลี่ยนค่าโดยใช้พอยเตอร์


2.ฟังก์ชันที่มีการส่งค่ากลับเป็นพอยเตอร์ (Functions Returning Parameters) ถ้า ผู้ใช้มีฟังก์ชันที่ใช้หาค่าที่น้อยที่สุดระหว่างตัวเลข 2 ตัว ในกรณีนี้ผู้ใช้จะต้องกำหนดให้พอยเตอร์ที่ชี้ไปตัวแปรทั้ง 2 ตัวนั้น โดยให้เป็น a และ b โดยในฟังก์ชันมีเงื่อนไขที่ใช้หาค่าที่น้อยกว่า และถ้าตัวเลขตัวไหนน้อยกว่าก็ส่งค่า Address ของตัวเลขตัวนั้นกลับมา ตัวอย่างการส่งค่ากลับโดยใช้พอยเตอร์ แสดงในรูปที่ 9-13
รูปที่ 9-13 การส่งค่ากลับโดยใช้พอยเตอร์

Pointers To Pointers

          Pointers To Pointers คือ การใช้พอยเตอร์ตัวหนึ่งชี้ไปยังพอยเตอร์อีกตัวหนึ่ง ซึ่งพอยเตอร์นั้นชี้ไปยังตัวแปร ซึ่งในรูปที่ 9-14 แสดงการชี้ 2 ระดับ ซึ่งการทำแบบนี้สามารถทำได้ไม่จำกัดระดับ
ในแต่ละระดับนั้นต้องมีเครื่องหมาย Indirection 1 ตัว ดังรูปที่ 9-17 ให้ p ชี้ไปยัง a ก็สามารถ เขียนคำสั่งได้ดังนี้
*P
และถ้าต้องการให้ q ชี้ไปยัง a โดยผ่าน p ก็จะเป็น 2 ระดับ ก็จะเขียนคำสั่งได้ดังนี้
**q
ซึ่งผลลัพธ์ของโปรแกรมที่แสดงในรูปที่ 9-17 จะได้ดังนี้

58 58 58
รูปที่ 9-14 แสดง Pointers To Pointers

ในโปรแกรมที่ 9-4 แสดงการใช้ Pointers To Pointers ซึ่งจะโปรแกรมตามรูปที่ 9-15
รูปที่ 9-15 แสดงการใช้ Pointers To Pointers

โปรแกรมที่ 9-4 แสดงการใช้ Pointers To Pointers

#include<stdio.h>
#include<conio.h>
int main (void)
{
int a;
int *p;
int **q;
int ***r;
p = &a;
q = &p;
r = &q;
clrscr();
printf("Enter a number:");
scanf("%d",&a);
printf("The number is :%d\n",a);
printf("Enter a number:");
scanf("%d",p);
printf("The number is :%d\n",a);
printf("Enter a number:");
scanf("%d",*q);
printf("The number is :%d\n",a);
printf("Enter a number:");
scanf("%d",**r);
printf("The number is :%d\n",a);
getch();
return 0;
}
ผลลัพธ์ที่ได้:
Enter a number:1
The number is :1
Enter a number:2
The number is:2
Enter a number:3
The number is:3
Enter a number:4
The number is:4
 

Leave a Reply