หน่วยที่ 6  พอยน์เตอร์

สำหรับเนื้อหาในบทนี้กล่าวถึงพอยน์เตอร์ซึ่งเป็นตัวแปรชนิดหนึ่งที่ใช้สำหรับเก็บตำแหน่งข้อมูล (data address) ที่มีอยู่ในภาษา C สำหรับผู้ที่เคยเขียนภาษาเบสิก ฟอร์แทรน หรือ โคบอลมาแล้วจะเห็นว่าไม่มีพอยน์เตอร์ในภาษาเหล่านี้ ดั้งนั้นพอยน์เตอร์จึงเป็นหลักการใหม่ที่สำคัญอย่างหนึ่งของภาษา C ที่ควรทำความเข้าใจและสามารถนำไปใช้ประโยชน์ได้อย่างมีประสิทธิภาพ

6.1 ความหมายและประเภทของพอยน์เตอร์

6.1.1 ความหมายของพอยน์เตอร์

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

6.1.2 ประเภทของพอยน์เตอร์

ประเภทของพอยน์เตอร์ สามารถแบ่งออกเป็น 2 ชนิด ดังนี้

1) direct pointer คือ ตัวแปรที่เก็บตำแหน่งของข้อมูลภายในหน่วยความจำโดยตรง (ดูรูปที่ 6.1 ประกอบ )

รูปที่ 6.1 แสดง direct pointer

2) indirect pointer คือ ตัวแปรที่เก็บตำแหน่งของพอยน์เตอร์อีกตัวหนึ่ง บางครั้งอาจ เรียกว่า pointer to pointer ก็ได้ (ดูรูปที่ 6.2 ประกอบ)

รูปที่ 6.2 แสดง indirect pointer หรือ pointer to pointer

6.2 ประโยชน์ของการใช้พอยน์เตอร์

การนำพอยน์เตอร์มาใช้งานในโปรแกรมขึ้นอยู่กับวัตถุประสงค์ของการใช้งาน โดยส่วนมากมักนิยมนำพอยน์เตอร์มาช่วยงานดังนี้

ใช้รับค่า address ของตัวแปรชุด (arrays) หรือตัวแปรสตริง (strings variables) จากฟังก์ชันหนึ่งไปยังอีกฟังก์ชันหนึ่ง และใช้ในการส่งค่ากลับมายังฟังก์ชัน

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

ใช้พอยน์เตอร์ช่วยในการจัดการโครงสร้างข้อมูล เช่น ลิงก์ลิสต์ (linked lists), ไบนารีทรี (binary tree), การจัดเรียงข้อมูล (sort) ชนิดต่าง ๆ เป็นต้น

6.3 การประกาศตัวแปรพอยน์เตอร์ (declaration pointer variables)

ก่อนที่จะนำตัวแปรพอยน์เตอร์ไปใช้งาน ต้องมีการประกาศตัวแปรพอยน์เตอร์ดังนี้

รูปแบบการประกาศพอยน์เตอร์ในภาษา C

โดยที่

type คือ ชนิดของตัวแปรพอยน์เตอร์ซึ่งจะต้องเป็นชนิดเดียวกับข้อมูล นั่นหมายความว่า ถ้าข้อมูลที่เก็บไว้ตรงตำแหน่งที่ตัวแปรพอยน์เตอร์ชี้อยู่เป็นข้อมูลชนิด int ตัวแปรพอยน์เตอร์จะต้องมีชนิด int ด้วย สำหรับขนาดของตัวแปรพอยน์เตอร์ก็ขึ้นอยู่กับชนิดของตัวแปรพอยน์เตอร์

* คือ เครื่องหมาย asterick ที่แสดงให้ทราบว่าตัวแปรที่ตามหลังเครื่องหมายนี้เป็นตัวแปรพอยน์เตอร์

ptr_name คือ ชื่อตัวแปรพอยน์เตอร์ โดยจะต้องมีเครื่องหมาย * (asterisk) นำหน้าชื่อเพื่อบอกให้ compiler รู้ว่าเป็นตัวแปรพอยน์เตอร์

ptr1_name,ptr2_name, … คือ ชื่อตัวแปรพอยน์เตอร์ตัวที่ 1, 2, … ตามลำดับ (กรณีมากกว่า 1 ตัว)

ตัวอย่างที่ 6.1 แสดงการประกาศตัวแปรพอยน์เตอร์

int *ptr;

float *pone, *ptwo, *pthree;

char *ptrx, *ptry , *ptrz;

6.4 กำหนดค่าตำแหน่งข้อมูลให้ตัวแปรพอยน์เตอร์

เมื่อต้องการกำหนดค่า address แรกของข้อมูลให้กับตัวแปรพอยน์เตอร์ ในภาษา C สามารถใช้รูปแบบได้ดังนี้

รูปแบบการกำหนดค่า address

โดยที่

ptr_name คือ ชื่อตัวแปรพอยน์เตอร์

variable_name คือ ชื่อตัวแปรที่ต้องการกำหนดค่า address แรกให้ตัวแปรพอยน์เตอร์ในกรณีที่เป็นตัวแปรชุด (arrays variables) หรือตัวแปรสตริง (string variables) ไม่ต้องใส่เครื่องหมาย & (ampersand) นำหน้า เช่น char s1[80]=”computer”; char *ptrs1; ptrs1=s1;

ตัวอย่างที่ 6.2 แสดงการกำหนด address ให้กับตัวแปรพอยน์เตอร์

int p, q, *pp, *qq; /* ประกาศตัวแปร p, q และตัวแปรพอยน์เตอร์ pp และ qq */

pp=&p /* กำหนดค่า address แรกของตัวแปร p ไปเก็บไว้ที่พอยน์เตอร์ pp */

qq=&q /* กำหนดค่า address แรกของตัวแปร q ไปเก็บไว้ที่พอยน์เตอร์ qq */

 

 

6.5 ตัวดำเนินการที่ใช้กับพอยน์เตอร์ (pointer operator)

6.5.1 ตัวดำเนินการ * (asterisk) 

บางครั้งเรียกว่า เครื่องหมายดอกจัน เป็นเครื่องหมายที่ใช้บ่งบอกถึงค่าข้อมูลที่พอยน์เตอร์ชี้อยู่ 

เพื่อความเข้าใจเกี่ยวกับการใช้ตัวดำเนินการ * กับพอยน์เตอร์มากยิ่งขึ้น ให้ศึกษาโปรแกรมตัวอย่างที่ 6.1 ดังต่อไปนี้

โปรแกรมตัวอย่างที่ 6.1 แสดงการใช้ตัวดำเนินการ * เพื่อบอกถึงค่าข้อมูลที่พอยน์เตอร์ชี้อยู่

/* asterisk.c */

#include<stdio.h> /* บรรทัดที่ 1 */

#include<conio.h> /* บรรทัดที่ 2 */

void main (void) /* บรรทัดที่ 3 */

{ /* บรรทัดที่ 4 */

int a=10,b=25; /* บรรทัดที่ 5 */

int *pa, *pb; /* บรรทัดที่ 6 */

clrscr( ); /* บรรทัดที่ 7 */

pa = &a; /* บรรทัดที่ 8 */

pb = &b; /* บรรทัดที่ 9 */

printf("a = %d, b = %d", *pa, *pb); /* บรรทัดที่ 10 */

printf("\n\nPress any key back to program ..."); /* บรรทัดที่ 11 */

getch(); /* บรรทัดที่ 12 */

} /* บรรทัดที่ 1 3 */

ผลลัพธ์ที่ได้จากโปรแกรม

คำอธิบายโปรแกรม 

จากโปรแกรมตัวอย่างที่ 6.1 สามารถอธิบายการทำงานของโปรแกรมที่สำคัญ ๆ ได้ดังนี้

บรรทัดที่ 6 คำสั่ง int *pa, *pb; เป็นการประกาศตัวแปรพอยเตอร์ pa และ pb เป็นชนิด int

บรรทัดที่ 8 คำสั่ง pa = &a; เป็นการกำหนดค่า address แรกของ a ให้ตัวแปรพอยเตอร์ pa

บรรทัดที่ 9 คำสั่ง pb = &a; เป็นการกำหนดค่า address แรกของ b ให้ตัวแปรพอยเตอร์ pb

บรรทัดที่ 10 พิมพ์ค่าที่ตัวแปรพอยเตอร์ pa และ pb ชี้อยู่ แล้วออกจอภาพ นั่นคือชี้ค่าตัวแปร a และ b ตามลำดับ

บรรทัดที่ 11 และ 12 พิมพ์ข้อความให้กดคีย์ใด ๆ เพื่อกลับเข้าสู่โปรแกรม และหยุดรอรับค่าใด ๆ จากคีย์บอร์ด เช่น กด enter จะกลับเข้าสู่โปรแกรมตามลำดับ

6.5.2 ตัวดำเนินการ & (ampersand) 

เป็นเครื่องหมายที่ใช้บ่งบอกถึงค่า address ของข้อมูล

เพื่อความเข้าใจเกี่ยวกับการใช้ตัวดำเนินการ & กับพอยน์เตอร์มากยิ่งขึ้น ให้ศึกษาโปรแกรมตัวอย่างที่ 6.2 ดังต่อไปนี้

โปรแกรมตัวอย่างที่ 6.2 แสดงการใช้ตัวดำเนินการ & เพื่อบอกถึงค่า address ของข้อมูล

/* ampersan.c */

#include<stdio.h> /* บรรทัดที่ 1 */

#include<conio.h> /* บรรทัดที่ 2 */

void main(void) /* บรรทัดที่ 3 */

{ /* บรรทัดที่ 4 */

int m=25,n=60; /* บรรทัดที่ 5 */

int *pm,*pn; /* บรรทัดที่ 6 */

clrscr( ); /* บรรทัดที่ 7 */

pm=&m; /* บรรทัดที่ 8 */

pn=&n; /* บรรทัดที่ 9 */

printf("M1 = %d, N1 = %d\n", m, n); /* บรรทัดที่ 10 */

printf("M2 = %d, N2 = %d\n", *pm, *pn); /* บรรทัดที่ 11*/

printf("\nAddress of m,n are %p %p \n", &pm, &pn); /* บรรทัดที่ 12 */

printf("\nPress any key back to program ..."); /* บรรทัดที่ 13 */

getch(); /* บรรทัดที่ 14 */

} /* บรรทัดที่ 15 */

ผลลัพธ์ที่ได้จากโปรแกรม

คำอธิบายโปรแกรม 

จากโปรแกรมตัวอย่างที่ 6.2 สามารถอธิบายการทำงานของโปรแกรมที่สำคัญ ๆ ได้ดังนี้

บรรทัดที่ 6 คำสั่ง int *pm,*pn; คำสั่งประกาศตัวแปรพอยน์เตอร์ pm และ pn เป็นชนิด int

บรรทัดที่ 8 คำสั่ง pm=&m; เป็นการกำหนดค่า address แรกของ m ให้ตัวแปรพอยน์เตอร์ pm

บรรทัดที่ 9 คำสั่ง pn=&n; เป็นการกำหนดค่า address แรกของ n ให้ตัวแปรพอยน์เตอร์ pn

บรรทัดที่ 10 พิมพ์ค่าตัวแปร m และ n แสดงที่จอภาพ

บรรทัดที่ 11 พิมพ์ค่าตัวแปรที่ตัวแปรพอยน์เตอร์ pm และ pn ชี้อยู่แสดงที่จอภาพ

บรรทัดที่ 12 พิมพ์ค่า address ของตัวแปร m และ n ที่ตัวแปรพอยน์เตอร์ pm และ pn ชี้อยู่ โดยใช้รหัสรูปแบบข้อมูลเป็น %p แสดงที่จอภาพ

บรรทัดที่ 13 และ 14 พิมพ์ข้อความให้กดคีย์ใด ๆ เพื่อกลับเข้าสู่โปรแกรม และหยุดรอรับค่าใด ๆ จากคีย์บอร์ด เช่น กด enter จะกลับเข้าสู่โปรแกรมตามลำดับ

 

6.6 พอยน์เตอร์กับฟังก์ชันที่เขียนขึ้นใช้งานเอง (pointer and user defined functions)

เราสามารถใช้ตัวแปรพอยน์เตอร์มาช่วยในการรับค่าและส่งคืนค่ากลับในฟังก์ชันที่เขียนขึ้นได้ดังนี้

6.6.1 การส่งค่าไปยังฟังก์ชัน (passing address to function) สามารถทำได้ 2 วิธี

1) การส่งค่าข้อมูลไปยังฟังก์ชันที่ต้องการ (passing data values to function)

การส่งค่าข้อมูล 1 ค่าหรือหลายค่าจากฟังก์ชันหนึ่งไปยังอีกฟังก์ชันหนึ่ง คือการคัดลอกค่าข้อมูล (duplicated value) จากที่หนึ่งไปยังอีกที่หนึ่ง

2) การส่งตำแหน่งของข้อมูลไปยังฟังก์ชัน (passing address to a function)

การส่งตำแหน่งของข้อมูลไปยังฟังก์ชันที่ต้องการจะต้องใช้ตัวแปรพอยน์เตอร์มาช่วยในการเก็บตำแหน่งของข้อมูลที่ส่งมา

เพื่อความเข้าใจเกี่ยวกับการส่งค่าข้อมูลและตำแหน่งของข้อมูลไปยังฟังก์ชันที่ต้องการ ให้ศึกษาโปรแกรมตัวอย่างดังต่อไปนี้

โปรแกรมตัวอย่างที่ 6.3 แสดงการส่งค่าข้อมูลและตำแหน่งของข้อมูลไปยังฟังก์ชันที่ต้องการ

/* passdata.c */

#include<stdio.h> /* บรรทัดที่ 1 */

#include<conio.h> /* บรรทัดที่ 2 */

void f1(int, int); /* function prototype f1 */ /* บรรทัดที่ 3 */

void f2(int*, int*); /* function prototype f2 */ /* บรรทัดที่ 4 */

void main(void) /* บรรทัดที่ 5 */

{ /* บรรทัดที่ 6 */

int p=15, q=30; /* บรรทัดที่ 7 */

clrscr( ); /* บรรทัดที่ 8 */

f1(p,q); /* called f1() */ /* บรรทัดที่ 9 */

f2(&p,&q); /* called f2() */ /* บรรทัดที่ 10 */

printf("\nPress any key back to program ..."); /* บรรทัดที่ 11 */

getch(); /* บรรทัดที่ 12 */

} /* end main */ /* บรรทัดที่ 13 */

void f1( int pp, int qq) { /* บรรทัดที่ 14 */

printf("P1 = %d\tQ1 = %d\n",pp,qq); /* บรรทัดที่ 15 */

} /* บรรทัดที่ 16 */

void f2( int *pp, int *qq) { /* บรรทัดที่ 17 */

*pp = *pp +20; /* บรรทัดที่ 18 */

*qq = *qq +20; /* บรรทัดที่ 19 */

printf("P2 = %d\tQ2 = %d\n",*pp,*qq); /* บรรทัดที่ 20 */

} /* บรรทัดที่ 21 */

ผลลัพธ์ที่ได้จากโปรแกรม

คำอธิบายโปรแกรม 

จากโปรแกรมตัวอย่างที่ 6.3 สามารถอธิบายการทำงานของโปรแกรมที่สำคัญ ๆ ได้ดังนี้

บรรทัดที่ 3 คำสั่ง void f1(int, int); เป็นการประกาศรูปแบบฟังก์ชัน f1

บรรทัดที่ 4 คำสั่ง void f2(int*, int*); เป็นการประกาศรูปแบบฟังก์ชัน f2 

บรรทัดที่ 9 คำสั่ง f1(p,q); การเรียกใช้งานฟังก์ชัน f1 และส่งข้อมูลของตัวแปร p กับ q ไปยังฟังก์ชัน f1( ) ซึ่งฟังก์ชัน f1( ) อยู่คำสั่งบรรทัดที่ 14 ถึง 16 

บรรทัดที่ 10 คำสั่ง f2(&p,&q); การเรียกใช้งานฟังก์ชัน f2 และส่งข้อมูลของตัวแปร p กับ q ไปยังฟังก์ชัน f2( ) ซึ่งฟังก์ชัน f2( ) อยู่คำสั่งบรรทัดที่ 17 ถึง 21 

บรรทัดที่ 14 ถึง 16 เป็นฟังก์ชันที่ตัวแปรพอยน์เตอร์ pp,qq จะรับค่าข้อมูลจากตัวแปร p และ q ที่ส่งมาให้จากจุดที่เรียกใช้งานในฟังก์ชัน main( ) ตามลำดับ และแสดงค่าตัวแปรที่ตัวแปรพอยน์เตอร์ pp และ qq รับค่ามาจากตัวแปร p และ q ออกที่จอภาพ

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

บรรทัดที่ 11 ถึง 12 ภายหลังจากฟังก์ชัน f1( ) และ f2( ) ทำงานเสร็จแล้วพิมพ์ข้อความให้กดคีย์ใด ๆ เพื่อกลับเข้าสู่โปรแกรม และหยุดรอรับค่าใด ๆ จากคีย์บอร์ด เช่น กด enter จะกลับเข้าสู่โปรแกรมตามลำดับ

6.6.2 การคืนค่ากลับของฟังก์ชัน (returning data from functions)

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

ขั้นตอนแรก ในโปรแกรมที่ใช้เรียกฟังก์ชัน (calling program) จะต้องใช้วิธีการส่งตำแหน่งของข้อมูลไปยังฟังก์ชัน โดยใช้เครื่องหมาย & นำหน้าชื่อตัวแปรที่ต้องการส่งค่า address ไป

ขั้นตอนที่สอง ในฟังก์ชันที่ถูกเรียกใช้ จะต้องใช้ตัวแปรพอยน์เตอร์มารับค่า address ที่ส่งมาเมื่อต้องการคืนค่ากลับให้ใช้เครื่องหมาย * นำหน้าชื่อตัวแปรพอยน์เตอร์ เพื่อคืนค่ากลับมายังตัวแปรของฟังก์ชัน

เพื่อความเข้าใจเกี่ยวกับการคืนค่ากลับของฟังก์ชัน ให้ศึกษาโปรแกรมตัวอย่างดังต่อไปนี้

โปรแกรมตัวอย่างที่ 6.4 แสดงการคืนค่ากลับของฟังก์ชันที่มากกว่า 1 ค่า

/* retudata.c */

#include<stdio.h> /* บรรทัดที่ 1 */

#include<conio.h> /* บรรทัดที่ 2 */

void back(int* , int* ); /* function prototype back() */ /* บรรทัดที่ 3 */

void main(void) /* บรรทัดที่ 4 */

{ /* บรรทัดที่ 5 */

int a, b; /* บรรทัดที่ 6 */

clrscr( ); /* บรรทัดที่ 7 */

back(&a,&b); /* called back() */ /* บรรทัดที่ 8 */

printf("A = %d, B = %d\n", a, b); /* บรรทัดที่ 9 */

printf("\nPress any key back to program ..."); /* บรรทัดที่ 10 */

getch(); /* บรรทัดที่ 11 */

} /* end main */ /* บรรทัดที่ 12 */

void back(int *aa, int *bb) /* บรรทัดที่ 13 */

{ /* บรรทัดที่ 14 */

*aa=300; /* assigned 300 passthru aa to a *//* บรรทัดที่ 15 */

*bb=500; /* assigned 500 passthru bb to b *//* บรรทัดที่ 16 */

} /* บรรทัดที่ 17 */

ผลลัพธ์ที่ได้จากโปรแกรม

คำอธิบายโปรแกรม 

จากโปรแกรมตัวอย่างที่ 6.4 สามารถอธิบายการทำงานของโปรแกรมที่สำคัญ ๆ ได้ดังนี้

บรรทัดที่ 3 คำสั่ง void back(int*,int*); เป็นการประกาศรูปแบบฟังก์ชัน back

บรรทัดที่ 8 ในฟังก์ชัน main( ) มีการเรียกใช้ฟังก์ชัน back(&a,&b); หมายถึงมีการส่งค่า address ของตัวแปร a และ b ไปยังตัวแปรพอยน์เตอร์ aa และ bb ของฟังก์ชัน back( ) ตามลำดับ ซึ่งฟังก์ชัน back( ) แสดงอยู่คำสั่งบรรทัดที่ 13 ถึง 16 ซึ่งมีการใช้เครื่องหมาย * อยู่หน้าตัวแปรพอยน์เตอร์ aa และ bb เพื่อบอกให้กำหนดค่าตัวเลข 300 และ 500 ให้กับตัวแปร a และ b เนื่องจากภายในตัวแปรพอยน์เตอร์ทั้งสองตัวได้เก็บค่า address แรกของตัวแปร a และ b ไว้แล้ว จึงเหมือนกับการส่งค่ากลับ 2 ค่า พร้อมกัน

บรรทัดที่ 10 และ 11 ภายหลังจากทำงานฟังก์ชัน back( ) เสร็จแล้ว 

พิมพ์ข้อความให้กดคีย์ใด ๆ เพื่อกลับเข้าสู่โปรแกรม และหยุดรอรับค่าใด ๆ จากคีย์บอร์ด เช่น กด enter จะกลับเข้าสู่โปรแกรมตามลำดับ

6.7 พอยน์เตอร์กับตัวแปรชุด (pointers and arrays)

พอยน์เตอร์สามารถนำมาช่วยในการจัดการข้อมูลที่เก็บอยู่ในตัวแปรชุดได้ ซึ่งจะช่วยทำให้การจัดเก็บและการเรียกใช้ข้อมูลในตัวแปรชุดมีประสิทธิภาพมากขึ้น

เพื่อความเข้าใจเกี่ยวกับการใช้งานพอยน์เตอร์กับตัวแปรชุด ให้ศึกษาโปรแกรมตัวอย่าง 6.5 และ 6.6 ดังต่อไปนี้

โปรแกรมตัวอย่างที่ 6.5 แสดงการใช้พอยน์เตอร์กับตัวแปรชุด

/* ptrarr1.c */

#include<stdio.h> /* บรรทัดที่ 1 */

#include<conio.h> /* บรรทัดที่ 2 */

void main (void) /* บรรทัดที่ 3 */

{ /* บรรทัดที่ 4 */

int num[10] = {10,20,30,40,50,60,70,80,90,100}; /* บรรทัดที่ 5 */

int *ptr; /* declaration pointer ptr */ /* บรรทัดที่ 6 */

int i; /* บรรทัดที่ 7 */

clrscr( ); /* บรรทัดที่ 8 */

ptr=&num[0]; /* บรรทัดที่ 9 */

for (i=0; i<=9; i++) /* บรรทัดที่ 10 */

printf( "%5d",*(ptr+i) ); /* บรรทัดที่ 11 */

printf("\n\nPress any key back to program ..."); /* บรรทัดที่ 12 */

getch(); /* บรรทัดที่ 13 */

} /* บรรทัดที่ 14 */

ผลลัพธ์ที่ได้จากโปรแกรม

คำอธิบายโปรแกรม 

จากโปรแกรมตัวอย่างที่ 6.5 สามารถอธิบายการทำงานของโปรแกรมที่สำคัญ ๆ ได้ดังนี้

บรรทัดที่ 6 คำสั่ง int *ptr; การประกาศตัวแปรพอยเตอร์ชื่อ ptr ชนิด int

บรรทัดที่ 9 คำสั่ง ptr=&num[0]; เป็นการกำหนด address แรกของตัวแปร num[0] ให้กับตัวแปร ptr หรือใช้คำสั่ง ptr=num; ก็ได้

บรรทัดที่ 10 คำสั่ง for เพื่อช่วยวนลูปนำค่าที่ตัวแปรอะเรย์ชี้อยู่ออกมาแสดง

บรรทัดที่ 11 คำสั่ง printf(“%5d”,*(ptr+i)); เป็นการพิมพ์ค่าในตัวแปรอะเรย์ num โดยใช้ตัวแปรพอยน์เตอร์ซึ่งนิพจน์ *(ptr+i) หมายถึงการพิมพ์ค่าที่ตัวแปรพอยน์เตอร์ชี้อยู่คือ num[i]

บรรทัดที่ 12 และ 13 พิมพ์ข้อความให้กดคีย์ใด ๆ เพื่อกลับเข้าสู่โปรแกรม และหยุดรอ รับค่าใด ๆ จากคีย์บอร์ด เช่น กด enter จะกลับเข้าสู่โปรแกรมตามลำดับ

โปรแกรมตัวอย่างที่ 6.6 แสดงการใช้พอยน์เตอร์กับตัวแปรชุดควบคู่กับการเรียกใช้ฟังก์ชันที่มีการส่งตำแหน่งข้อมูล

/* ptrarr2.c */

#include<stdio.h> /* บรรทัดที่ 1 */

#include<conio.h> /* บรรทัดที่ 2 */

void add(int*); /* function prototype add() */ /* บรรทัดที่ 3 */

void main(void) /* บรรทัดที่ 4 */

{ /* บรรทัดที่ 5 */

int array[10] = {2,4,6,8,10,12,14,16,18,20}; /* บรรทัดที่ 6 */

int i; /* บรรทัดที่ 7 */

clrscr(); /* บรรทัดที่ 8 */

for(i=0; i<=9; i++) /* บรรทัดที่ 9 */

printf( "%5d", array[i] ); /* บรรทัดที่ 10 */

add(array); /* บรรทัดที่ 11 */

for(i=0; i<=9; i++) /* บรรทัดที่ 12 */

printf( "\n%25d", *(array+i) ); /* บรรทัดที่ 13 */

printf("\n\nPress any key back to program ..."); /* บรรทัดที่ 14 */

getch(); /* บรรทัดที่ 15 */

} /* end main */ /* บรรทัดที่ 16 */

/**** add function ****/ /* บรรทัดที่ 17 */

void add(int *ptr) /* บรรทัดที่ 18 */

{ /* บรรทัดที่ 19 */

int j; /* บรรทัดที่ 20 */

for(j=0; j<=9; j++) /* บรรทัดที่ 21 */

*(ptr+j) = *(ptr+j) + 20; /* บรรทัดที่ 22 */

} /* บรรทัดที่ 23 */

ผลลัพธ์ที่ได้จากโปรแกรม

คำอธิบายโปรแกรม 

จากโปรแกรมตัวอย่างที่ 6.6 สามารถอธิบายการทำงานของโปรแกรมที่สำคัญ ๆ ได้ดังนี้

บรรทัดที่ 3 คำสั่ง void add(int*); ประกาศรูปแบบฟังก์ชันชื่อ add( )

บรรทัดที่ 9 และ 10 คำสั่ง for(i=0; i<=9; i++) printf(“%5d”,array[i]); เป็นคำสั่งวนลูปให้พิมพ์ค่าจากตัวแปร array[0], array[1], array[2], array[3], array[4] ถึง array[9] ตามลำดับ

บรรทัดที่ 11 คำสั่ง add(array); เป็นคำสั่งเรียกใช้ฟังก์ชัน add โดยส่งค่า address แรกของตัวแปร array[0] ไปให้ตัวแปรพอยน์เตอร์ ptr ในฟังก์ชัน add( ) 

บรรทัดที่ 12 และ 13 คำสั่ง for(i=0; i<=9;i++) printf(“\n%25d”,*(array+i)); ทำงานเหมือนบรรทัดที่ 9 และ 10 

บรรทัดที่ 14 และ 15 พิมพ์ข้อความให้กดคีย์ใด ๆ เพื่อกลับเข้าสู่โปรแกรม และหยุดรอรับค่าใด ๆ จากคีย์บอร์ด เช่น กด enter จะกลับเข้าสู่โปรแกรมตามลำดับ 

บรรทัดที่ 21 และ 22 คำสั่ง for(j=0; j<=9; j++) *(ptr+j) = *(ptr+j) + 20; เป็นคำสั่งที่เหมือนกับคำสั่ง array[j]=array[j]+20; ดังนั้นเมื่อใช้คำสั่ง for มาช่วย จึงทำให้สมาชิกทุกตัวของตัวแปรชุด ได้แก่ array[0], array[1], array[2], array[3], array[4] ถึง array[9] ถูกเพิ่มค่าเข้าไปตัวละ 20 จึงได้ผลลัพธ์ตามที่ได้แสดงมาแล้วข้างต้น

ดังนั้น

*(ptr+0) หมายถึง ค่าตัวแปร array[0] หรือ *(array+0)

*(ptr+1) หมายถึง ค่าตัวแปร array[1] หรือ *(array+1)

*(ptr+2) หมายถึง ค่าตัวแปร array[2] หรือ *(array+2)

*(ptr+3) หมายถึง ค่าตัวแปร array[3] หรือ *(array+3)

*(ptr+4) หมายถึง ค่าตัวแปร array[4] หรือ *(array+4)

*(ptr+5) หมายถึง ค่าตัวแปร array[5] หรือ *(array+5)

*(ptr+6) หมายถึง ค่าตัวแปร array[6] หรือ *(array+6)

*(ptr+7) หมายถึง ค่าตัวแปร array[7] หรือ *(array+7)

*(ptr+8) หมายถึง ค่าตัวแปร array[8] หรือ *(array+8)

*(ptr+9) หมายถึง ค่าตัวแปร array[9] หรือ *(array+9)

6.8 พอยน์เตอร์กับสตริง (pointers and string)

เนื่องจากการเก็บค่าคงที่ชนิดสตริงจะเก็บไว้ในตัวแปรสตริง ดังนั้นเมื่อเราสามารถใช้พอยน์เตอร์กับตัวแปรชุดได้ ก็ย่อมสามารถใช้พอยน์เตอร์มาจัดการกับค่าคงที่ชนิดสตริงได้เช่นกัน

เพื่อความเข้าใจเกี่ยวกับการใช้พอยน์เตอร์กับสตริง ให้ศึกษาโปรแกรมตัวอย่าง 6.7 และ 6.8 ดังต่อไปนี้

โปรแกรมตัวอย่างที่ 6.7 แสดงการใช้พอยน์เตอร์กับสตริงในการตั้งค่าสตริงและนำออกมาแสดงที่จอภาพ

/* ptrstr1.c */

#include<stdio.h> /* บรรทัดที่ 1 */

#include<conio.h> /* บรรทัดที่ 2 */

void main(void) /* บรรทัดที่ 3 */

{ /* บรรทัดที่ 4 */

char *ptr = "Hello"; /* บรรทัดที่ 5 */

char name[80]; /* บรรทัดที่ 6 */

clrscr( ); /* บรรทัดที่ 7 */

printf("Enter your name : "); /* บรรทัดที่ 8 */

gets(name); /* บรรทัดที่ 9 */

printf("\n%s, %s", ptr, name); /* บรรทัดที่ 10 */

printf("\n\nPress any key back to program ..."); /* บรรทัดที่ 11 */

getch(); /* บรรทัดที่ 12 */

} /* บรรทัดที่ 13 */

ผลลัพธ์ที่ได้จากโปรแกรม

คำอธิบายโปรแกรม 

จากโปรแกรมตัวอย่างที่ 6.7 สามารถอธิบายการทำงานของโปรแกรมที่สำคัญ ๆ ได้ดังนี้

บรรทัดที่ 5 คำสั่ง char *ptr = “Hello”; มีผลทำให้ภายในหน่วยความจำมีลักษณะดังนี้

รูปที่ 6.3 แสดงคำสั่ง char *ptr = “Hello”; ในหน่วยความจำ

บรรทัดที่ 8 ถึง 10 รับค่าสตริงที่ผู้ใช้ป้อนเก็บไว้ที่ตัวแปร name แล้วนำค่าที่เก็บไว้ในตัวแปรพอยเตอร์ ptr ชี้อยู่ และตัวแปร name แสดงออกที่จอภาพ

บรรทัดที่ 11 ถึง 12 พิมพ์ข้อความให้กดคีย์ใด ๆ เพื่อกลับเข้าสู่โปรแกรม และหยุดรอรับค่าใด ๆ จากคีย์บอร์ด เช่น กด enter จะกลับเข้าสู่โปรแกรมตามลำดับ

โปรแกรมตัวอย่างที่ 6.8 แสดงการใช้พอยน์เตอร์ ในการเก็บและแสดงสตริงทางจอภาพในลักษณะพิมพ์ย้อนกลับ

/* ptrstr2.c */

#include<stdio.h> /* บรรทัดที่ 1 */

#include<conio.h> /* บรรทัดที่ 2 */

void main(void) /* บรรทัดที่ 3 */

{ /* บรรทัดที่ 4 */

char string[81]; /* บรรทัดที่ 5 */

char *pstr; /*declaration pointer pstr */ /* บรรทัดที่ 6 */

int j=0; /* บรรทัดที่ 7 */

clrscr( ); /* บรรทัดที่ 8 */

printf("Enter your string : "); /* บรรทัดที่ 9 */

gets(string); /* บรรทัดที่ 10 */

pstr=string; /* บรรทัดที่ 11 */

while(*pstr) /* บรรทัดที่ 12 */

{ /* บรรทัดที่ 13 */

j++; /* บรรทัดที่ 14 */

pstr++; /* บรรทัดที่ 15 */

} /* บรรทัดที่ 16 */

printf("\nLength of String is...%d\n", j); /* บรรทัดที่ 17*/

pstr--; /* บรรทัดที่ 18 */

printf("\nReverse String is..."); /* บรรทัดที่ 19 */

while(j>0) /* บรรทัดที่ 20 */

{ /* บรรทัดที่ 21 */

printf("%c", *pstr); /* บรรทัดที่ 22 */

pstr--; /* บรรทัดที่ 23 */

j--; /* บรรทัดที่ 24 */

} /* บรรทัดที่ 25 */

printf("\n\nPress any key back to program ..."); /* บรรทัดที่ 26 */

getch(); /* บรรทัดที่ 27 */

} /* บรรทัดที่ 28 */

ผลลัพธ์ที่ได้จากโปรแกรม

คำอธิบายโปรแกรม 

จากโปรแกรมตัวอย่างที่ 6.8 สามารถอธิบายการทำงานของโปรแกรมที่สำคัญ ๆ ได้ดังนี้

บรรทัดที่ 6 คำสั่ง char *pstr; ประกาศตัวแปรพอยน์เตอร์ ชื่อ pstr ชนิด char

บรรทัดที่ 9 และ 10 รับค่าสตริงที่ผู้ใช้ป้อนกลับมาเก็บไว้ในตัวแปร string

บรรทัดที่ 11 คำสั่ง pstr=string; เป็นการกำหนดตำแหน่งแรกของตัวแปร string ให้กับ พอยน์เตอร์ ptr 

บรรทัดที่ 12 ถึง 16 คำสั่ง while(*pstr) { j++; pstr++; } เป็นการทำงานตามเงื่อนไขในคำสั่ง while คือ *pstr เป็นจริงให้ทำงานในคำสั่ง j++; และ pstr++; ตามลำดับ ในกรณีนี้ค่า *pstr จะเป็นเท็จก็ต่อเมื่อเจอค่า \0 (null character) ซึ่งอยู่ตรงท้ายสุดของข้อมูลสตริง จึงจะทำให้ออกจากคำสั่ง while ได้

บรรทัดที่ 17 แสดงค่าความยาวของสริงที่ผู้ใช้ป้อนซึ่งนับเก็บไว้ที่ตัวแปร j ออกทางจอภาพ

บรรทัดที่ 18 คำสั่ง pstr- -; เป็นคำสั่งให้พอยน์เตอร์เคลื่อนกลับมา 1 ตัวอักขระ ทำให้พอยน์เตอร์ pstr ย้ายจากการชี้ที่ \0 มาอยู่ที่ตัวอักขระตัวสุดท้ายในกรณีที่เติมข้อความว่า nakhonphanom ตัวอักขระตัวสุดท้ายคือ ตัวอักษร m

บรรทัดที่ 19 แสดงสตริงที่ผู้ใช้เติมในลักษณะพิมพ์กลับ 

บรรทัดที่ 20 ถึง 25 คำสั่ง while(j>0) { printf(“%c”,*pstr); pstr- -; j- -; } เป็นการตรวจสอบเงื่อนไขในคำสั่ง while คือค่าตัวแปร j ถ้ามีค่ามากกว่า 0 (ศูนย์) แสดงว่าเป็นจริงให้พิมพ์ค่าที่ตัวแปรพอยน์เตอร์ชี้อยู่ออกทางจอภาพ แล้วเคลื่อนที่พอยน์เตอร์จากด้านหลังของตัวแปรสตริงมาทางด้านหน้าทีละ 1 ตัวอักขระ จากนั้นลดค่าในตัวแปร j ลงครั้งละ 1 ทำซ้ำ ๆ เช่นนี้จนกว่าค่าตัวแปร j มีค่าเท่ากับ 0 จึงออกจากคำสั่ง while ได้ 

บรรทัดที่ 26 ถึง 27 พิมพ์ข้อความให้กดคีย์ใด ๆ เพื่อกลับเข้าสู่โปรแกรม และหยุดรอรับค่าใด ๆ จากคีย์บอร์ด เช่น กด enter จะกลับเข้าสู่โปรแกรมตามลำดับ

 

6.9 อะเรย์ของพอยน์เตอร์ (array of pointer)

ในกรณีที่เรามีความต้องการใช้ตัวแปรพอยน์เตอร์เหมือนกับตัวแปรชุดก็สามารถกำหนดได้ตามรูปแบบดังนี้

รูปแบบการประกาศ array แบบ pointers

โดยที่

type คือ ชนิดของข้อมูลซึ่งอาจจะเป็น int, float, double หรือ char ก็ได้ ในกรณีที่เป็น char ค่าที่เก็บจะต้องเป็นค่าคงที่ชนิดสตริง

valuelist คือ ค่าตัวเลข หรือค่าคงที่ชนิดสตริงขึ้นอยู่กับว่า type เป็น int, float, double หรือ char ถ้า type เป็น char จะทำให้ valuelist เป็นค่าคงที่ชนิดสตริง ซึ่งต้องเขียนอยู่ภายใต้เครื่องหมาย “ “ (double quotation)

ptrname คือ ชื่อตัวแปรพอยน์เตอร์ ต้องใช้เครื่องหมาย * (asterisk) นำหน้าชื่อเสมอ

SIZE คือ ขนาดของตัวแปรชุดพอยน์เตอร์มีค่าตั้งแต่ 0, 1, 2, …, SIZE-1

ตัวอย่างที่ 6.3 แสดงการประกาศตัวแปรชุดแบบพอยน์เตอร์

เช่น int *px[10];

ภายในหน่วยความจำจะมีลักษณะดังนี้

รูปที่ 6.4 แสดงการประกาศตัวแปรชุดแบบพอยน์เตอร์ในหน่วยความจำ

เพื่อความเข้าใจเกี่ยวกับการใช้อะเรย์ของพอยน์เตอร์ ให้ศึกษาโปรแกรมตัวอย่าง 6.9 และ 6.10 ดังต่อไปนี้

โปรแกรมตัวอย่างที่ 6.9 แสดงการใช้อะเรย์แบบพอยน์เตอร์กับตัวแปรจำนวนเต็ม

/* arrptr1.c */

#include<stdio.h> /* บรรทัดที่ 1 */

#include<conio.h> /* บรรทัดที่ 2 */

void main(void) /* บรรทัดที่ 3 */

{ /* บรรทัดที่ 4 */

int j; /* บรรทัดที่ 5 */

int *ptr[10]; /* declaration array of pointer ptr */ /* บรรทัดที่ 6 */

int y[10] = {10,20,30,40,50,60,70,80,90,100}; /* บรรทัดที่ 7 */

clrscr( ); /* บรรทัดที่ 8 */

for(j=0; j<=9; j++) /* บรรทัดที่ 9 */

ptr[j] = &y[j]; /* บรรทัดที่ 10 */

for(j=0; j<=9; j++) { /* บรรทัดที่ 11 */

*ptr[j] = *ptr[j]+30; /* บรรทัดที่ 12 */

printf("y[%d] = %d\n",j,*ptr[j]); /* บรรทัดที่ 13 */

} /* บรรทัดที่ 14 */

printf("\nPress any key back to program ..."); /* บรรทัดที่ 15 */

getch(); /* บรรทัดที่ 16 */

} /* บรรทัดที่ 17 */

ผลลัพธ์ที่ได้จากโปรแกรม

คำอธิบายโปรแกรม 

จากโปรแกรมตัวอย่างที่ 6.9 สามารถอธิบายการทำงานของโปรแกรมที่สำคัญ ๆ ได้ดังนี้

บรรทัดที่ 6 คำสั่ง int *ptr[10]; ประกาศตัวแปรอะเรย์แบบพอยน์เตอร์ชื่อ ptr ชนิด int

บรรทัดที่ 9 และ 10 คำสั่ง for(j=0; j<=9; j++) ptr[j] = &y[j]; เป็นคำสั่งที่กำหนดค่า address ของตัวแปรชุด y[j] ให้กับตัวแปรชุดของพอยน์เตอร์ ptr[j] ดังนั้นจากคำสั่งนี้จะได้ว่า

รอบที่ 1 j=0 ทำงานคำสั่ง ptr[0]=&y[0];

รอบที่ 2 j=1 ทำงานคำสั่ง ptr[1]=&y[1];

รอบที่ 3 j=2 ทำงานคำสั่ง ptr[2]=&y[2];

รอบที่ 4 j=3 ทำงานคำสั่ง ptr[3]=&y[3];

รอบที่ 5 j=4 ทำงานคำสั่ง ptr[4]=&y[4];

รอบที่ 6 j=5 ทำงานคำสั่ง ptr[5]=&y[5];

รอบที่ 7 j=6 ทำงานคำสั่ง ptr[6]=&y[6];

รอบที่ 8 j=7 ทำงานคำสั่ง ptr[7]=&y[7];

รอบที่ 9 j=8 ทำงานคำสั่ง ptr[8]=&y[8];

รอบที่ 10 j=9 ทำงานคำสั่ง ptr[9]=&y9];

บรรทัดที่ 11ถึง 14 คำสั่ง for (j=0; j<=9; j++){*ptr[j] = *ptr[j]+30; printf("y[%d]=%d\n",j,*ptr[j]); } เป็นคำสั่งที่คำนวณค่าของตัวแปรชุด y[j] โดยบวกเพิ่มตัวละ 30 ผ่านทางตัวแปรชุดของพอยน์เตอร์ ptr[j] จากนั้นก็ใช้คำสั่ง printf( ) พิมพ์ค่าออกทางจอภาพ

บรรทัดที่ 15 และ 16 พิมพ์ข้อความให้กดคีย์ใด ๆ เพื่อกลับเข้าสู่โปรแกรม และหยุดรอ รับค่าใด ๆ จากคีย์บอร์ด เช่น กด enter จะกลับเข้าสู่โปรแกรมตามลำดับ

โปรแกรมตัวอย่างที่ 6.10 แสดงการใช้อะเรย์แบบพอยเตอร์กับตัวแปรตัวอักษร

/* arrptr2.c */

#include<stdio.h> /* บรรทัดที่ 1 */

#include<conio.h> /* บรรทัดที่ 2 */

void main(void) /* บรรทัดที่ 3 */

{ /* บรรทัดที่ 4 */

int i; /* บรรทัดที่ 5 */

static char *ptr[4] = { /* บรรทัดที่ 6 */

"NAKHONPHANOM", /* บรรทัดที่ 7 */

"SAKON NAKHON", /* บรรทัดที่ 8 */

"MOOKDAHAN", /* บรรทัดที่ 9 */

"NONGKHAI" }; /* บรรทัดที่ 10 */

clrscr(); /* บรรทัดที่ 11 */

for(i=3; i>=0; i--) /* บรรทัดที่ 12 */

printf("%s\n", ptr[i]); /* บรรทัดที่ 13 */

printf("\nPress any key back to program ..."); /* บรรทัดที่ 14 */

getch(); /* บรรทัดที่ 15 */

} /* บรรทัดที่ 16 */

ผลลัพธ์ที่ได้จากโปรแกรม

คำอธิบายโปรแกรม 

จากโปรแกรมตัวอย่างที่ 6.10 สามารถอธิบายการทำงานของโปรแกรมที่สำคัญ ๆ ได้ดังนี้

บรรทัดที่ 6 ถึง 10 คำสั่ง static char *ptr[4] = {

"NAKHONPHANOM",

"SAKON NAKHON",

"MOOKDAHAN",

"NONGKHAI" };

ประกาศตัวแปรอะเรย์แบบพอยน์เตอร์ ให้เป็นแบบ static ชื่อ ptr มีขนาด 4 ตัว เก็บชื่อจังหวัด 4 จังหวัด คือตัวที่ 0 ถึง ตัวที่ 3

บรรทัดที่ 12 และ 13 คำสั่ง for(i=3; i>=0; i--) printf("%s\n", ptr[i]); คำสั่ง for เพื่อช่วยวนลูปนำชื่อจังหวัดออกมาแสดง โดยแสดงจังหวัดสุดท้ายย้อนกลับมาจังหวัดแรก และแต่ละจังหวัดแสดงแล้วขึ้นบรรทัดใหม่ด้วย

บรรทัดที่ 14 และ 15 พิมพ์ข้อความให้กดคีย์ใด ๆ เพื่อกลับเข้าสู่โปรแกรม และหยุดรอ รับค่าใด ๆ จากคีย์บอร์ด เช่น กด enter จะกลับเข้าสู่โปรแกรมตามลำดับ

6.10 พอยน์เตอร์ทูพอยน์เตอร์ (indirect pointer หรือ pointer to pointer) 

indirect pointer คือ ตัวแปรพอยน์เตอร์ที่เก็บตำแหน่งของตัวแปรพอยน์เตอร์อีกตัวหนึ่งเอาไว้

การประกาศตัวแปรพอยน์เตอร์ทูพอยน์เตอร์ มีรูปแบบดังนี้

โดยที่

type คือ ชนิดของตัวแปรพอยน์เตอร์ทูพอยน์เตอร์ ซึ่งอาจจะเป็นชนิด int, char, float, double ก็ได้

pptrname คือ ชื่อตัวแปรพอยน์เตอร์ทูพอยน์เตอร์ ต้องใช้เครื่องหมาย ** (double asterisk) นำหน้าชื่อเสมอ หากตัวแปรพอยน์เตอร์ทูพอยน์เตอร์มากกว่า 1 ตัว ให้คั่นด้วยเครื่องหมาย , (comma) ระหว่างชื่อตัวแปรแต่ละตัว

ตัวอย่างที่ 6.4 แสดงการประกาศ pointer to pointer

int **pptrx;

float **ppx, **ppy, **ppz;

เพื่อความเข้าใจเกี่ยวกับการใช้พอยน์เตอร์ทูพอยน์เตอร์ ศึกษาโปรแกรมตัวอย่าง 6.11 และ 6.12 ดังต่อไปนี้

โปรแกรมตัวอย่างที่ 6.11 แสดงการใช้ pointer to pointer กับตัวแปรชนิดจำนวนเต็ม

/* pptr1.c */

#include<stdio.h> /* บรรทัดที่ 1 */

#include<conio.h> /* บรรทัดที่ 2 */

void main(void) /* บรรทัดที่ 3 */

{ /* บรรทัดที่ 4 */

int a=50, b=80; /* บรรทัดที่ 5 */

int *pa, *pb; /* บรรทัดที่ 6 */

int **ppa, **ppb; /* บรรทัดที่ 7 */

clrscr( ); /* บรรทัดที่ 8 */

pa=&a; pb=&b; /* บรรทัดที่ 9 */

ppa=&pa; ppb=&pb; /* บรรทัดที่ 10 */

printf("A = %d, B = %d\n", **ppa, **ppb); /* บรรทัดที่ 11 */

printf("\nPress any key back to program ..."); /* บรรทัดที่ 12 */

getch(); /* บรรทัดที่ 13 */

} /* บรรทัดที่ 14 */

ผลลัพธ์ที่ได้จากโปรแกรม

คำอธิบายโปรแกรม

บรรทัดที่ 6 คำสั่ง int *pa, *pb; ประกาศตัวแปรพอยน์เตอร์ชนิด int ชื่อ pa และ pb

บรรทัดที่ 7คำสั่ง int **ppa, **ppb; ประกาศตัวแปร indirect pointer ชื่อ ppa และ ppb

บรรทัดที่ 9 และ 10 สามารถอธิบายการทำงานได้ดังรูปที่ 6.5 

รูปที่ 6.5 แสดงการทำงานของตัวแปร pointer และ indirect pointer

บรรทัดที่ 11 พิมพ์ค่าที่ตัวแปร ppa และ ppb ชี้อยู่แสดงออกจอภาพ

บรรทัดที่ 12 ถึง 13 พิมพ์ข้อความให้กดคีย์ใด ๆ เพื่อกลับเข้าสู่โปรแกรม และหยุดรอ รับค่าใด ๆ จากคีย์บอร์ด เช่น กด enter จะกลับเข้าสู่โปรแกรมตามลำดับ

ข้อสังเกต ในการพิมพ์ค่าตัวแปร indirect pointer ชี้อยู่

1) ถ้าตัวแปร indirect pointer ชี้อยู่ที่ตัวแปร int, float, char(sigle character) ต้องใช้เครื่องหมาย ** นำหน้าชื่อ indirect pointer เสมอ จึงจะได้ค่าออกมา เช่น คำสั่ง printf(“%c”,**pptr); เมื่อ pptr เป็นตัวแปร indirect pointer

2) แต่ถ้า indirect pointer ชี้ไปที่ตัวแปรสตริง ให้ใช้เครื่องหมาย * นำหน้าชื่อก็เพียงพอแล้ว เช่น คำสั่ง printf(“%s”,*pptr); 

โปรแกรมตัวอย่างที่ 6.12 แสดงการใช้ pointer to pointer กับตัวแปรชนิดสตริง

/* pptr2.c */

#include<stdio.h> /* บรรทัดที่ 1 */

#include<conio.h> /* บรรทัดที่ 2 */

void main(void) /* บรรทัดที่ 3 */

{ /* บรรทัดที่ 4 */

char str[80], *ps, **ptps; /* บรรทัดที่ 5 */

clrscr( ); /* บรรทัดที่ 6 */

ps=&str[0]; /* บรรทัดที่ 7 */

ptps=&ps; /* บรรทัดที่ 8 */

printf("Enter your string : "); /* บรรทัดที่ 9 */

gets(str); /* บรรทัดที่ 10 */

printf("%s\n", *ptps); /* บรรทัดที่ 11 */

printf("\nPress any key back to program ..."); /* บรรทัดที่ 12 */

getch(); /* บรรทัดที่ 13 */

} /* บรรทัดที่ 14 */

ผลลัพธ์ที่ได้จากโปรแกรม

คำอธิบายโปรแกรม

บรรทัดที่ 5 คำสั่ง char str[80], *ps, **ptps; ประกาศตัวแปรอะเรย์ชื่อ str, ตัวแปรพอยน์เตอร์ชื่อ ps และตัวแปร indirect pointer ชื่อ ptps ซึ่งทั้งหมดเป็นชนิด char

บรรทัดที่ 7 คำสั่ง ps=&str[0]; กำหนด address แรกของตัวแปร str[0] ให้กับตัวแปร ps หรือใช้คำสั่ง ps = str; ก็ได้

บรรทัดที่ 8 คำสั่ง ptps = &ps; ทำงานเหมือนกับคำสั่งบรรทัดที่ 10 ในโปรแกรมตัว อย่างที่ 6.11 คือ ให้ ptps ชี้ไปยัง address ของตัวแปรพอยน์เตอร์ ps

บรรทัดที่ 9 และ 10 รับข้อความที่ผู้ใช้เติมมาเก็บไว้ที่ตัวแปร str

บรรทัดที่ 11 แสดงข้อความ ที่ตัวแปร ptps ชี้อยู่ออกจอภาพ

บรรทัดที่ 12 และ 13 พิมพ์ข้อความให้กดคีย์ใด ๆ เพื่อกลับเข้าสู่โปรแกรม และหยุดรอ รับค่าใด ๆ จากคีย์บอร์ด เช่น กด enter จะกลับเข้าสู่โปรแกรมตามลำดับ

6.11 สรุปท้ายบท

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

direct pointer คือ ตัวแปรที่เก็บตำแหน่งของข้อมูลภายในหน่วยความจำโดยตรง

indirect pointer คือ ตัวแปรที่เก็บตำแหน่งของพอยน์เตอร์อีกตัวหนึ่ง บางครั้งอาจ เรียกว่า pointer to pointer ก็ได้

ประโยชน์ของการใช้พอยน์เตอร์ พอสรุปได้ดังนี้

ใช้รับค่า address ของตัวแปรชุด (arrays) หรือตัวแปรสตริง (strings variables) จากฟังก์ชันหนึ่งไปยังอีกฟังก์ชันหนึ่ง และใช้ในการส่งค่ากลับมายังฟังก์ชัน

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

ใช้พอยน์เตอร์ช่วยในการจัดการโครงสร้างข้อมูล เช่น ลิงก์ลิสต์ (linked lists), ไบนารีทรี (binary tree), การจัดเรียงข้อมูล (sort) ชนิดต่าง ๆ เป็นต้น

นอกจากประโยนช์ที่กล่าวมาข้างต้นแล้ว เรายังสามารถใช้ตัวแปรพอยน์เตอร์กับฟังก์ชันที่เขียนขึ้นใช้งานเอง (pointer and user defined functions)

เราสามารถใช้ตัวแปรพอยน์เตอร์มาช่วยในการรับค่าและส่งคืนค่ากลับในฟังก์ชันที่เขียนขึ้นเองได้ดังนี้

การส่งค่าไปยังฟังก์ชัน (passing address to function) สามารถทำได้ 2 วิธี

การส่งค่าข้อมูลไปยังฟังก์ชันที่ต้องการ (passing data values to function) เป็นการส่งค่าข้อมูล 1 ค่าหรือหลายค่าจากฟังก์ชันหนึ่งไปยังอีกฟังก์ชันหนึ่ง คือการคัดลอกค่าข้อมูล (duplicated value) จากที่หนึ่งไปยังอีกที่หนึ่ง

การส่งตำแหน่งของข้อมูลไปยังฟังก์ชัน (passing address to a function) เป็น การส่งตำแหน่งของข้อมูลไปยังฟังก์ชันที่ต้องการจะต้องใช้ตัวแปรพอยน์เตอร์มาช่วยในการเก็บตำแหน่งของข้อมูลที่ส่งมา

การคืนค่ากลับของฟังก์ชัน (returning data from functions)

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

ขั้นตอนแรก ในโปรแกรมที่ใช้เรียกฟังก์ชัน (calling program) จะต้องใช้วิธีการส่งตำแหน่งของข้อมูลไปยังฟังก์ชัน โดยใช้เครื่องหมาย & นำหน้าชื่อตัวแปรที่ต้องการส่งค่า address ไป

ขั้นตอนที่สอง ในฟังก์ชันที่ถูกเรียกใช้ จะต้องใช้ตัวแปรพอยน์เตอร์มารับค่า address ที่ส่งมาเมื่อต้องการคืนค่ากลับให้ใช้เครื่องหมาย * นำหน้าชื่อตัวแปรพอยน์เตอร์ เพื่อคืนค่ากลับมายังตัวแปรของฟังก์ชัน

นอกจากนำตัวแปรพอยน์เตอร์มาใช้งานกับฟังก์ชันแล้ว เรายังสามารถนำพอยน์เตอร์ใช้งานกับตัวแปรชุด (pointers and arrays) และตัวแปรสตริง (pointers and string) ได้ เพื่อช่วยในการจัดการข้อมูลที่เก็บอยู่ในตัวแปรชุดและตัวแปรสตริงได้ ซึ่งจะช่วยทำให้การจัดเก็บและการเรียกใช้ข้อมูลในตัวแปรชุดและตัวแปรสตริงมีประสิทธิภาพมากขึ้น