พอยเตอร์(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; } |
ผลลัพธ์ที่ได้:
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 |
Design by Pratya |