360 likes | 676 Views
บทที่ 5 พอยน์เตอร์ ( Pointer). พอยน์เตอร์ เป็นชนิดข้อมูลชนิดหนึ่งของภาษาซี มีความเร็วในการทำงานสูง ช่วยให้ การเขียน ภาษาซี มีความยืดหยุ่น การใช้งานพอยน์เตอร์ ค่อนข้างซับ ซ้อน พอยน์เตอร์เป็นจุดเด่นอย่างหนึ่งในการเขียนภาษาซี. 5.1 พอยน์เตอร์กับแอดเดรส (Pointers and Addresses).
E N D
พอยน์เตอร์เป็นชนิดข้อมูลชนิดหนึ่งของภาษาซี มีความเร็วในการทำงานสูง ช่วยให้การเขียนภาษาซี มีความยืดหยุ่น การใช้งานพอยน์เตอร์ค่อนข้างซับซ้อน พอยน์เตอร์เป็นจุดเด่นอย่างหนึ่งในการเขียนภาษาซี
5.1 พอยน์เตอร์กับแอดเดรส (Pointers and Addresses) ตัวแปร คือชื่อที่ใช้แทนข้อมูล เราประกาศตัวแปรเป็นการกำหนดชื่อเพื่อใช้แทนข้อมูล เมื่อเราประกาศตัวแปร จะมีการจองเนื้อที่ในหน่วยความจำเพื่อเก็บข้อมูล เราสามารถเข้าถึงข้อมูลได้โดยอ้างถึงตัวแปร การประกาศตัวแปร เช่น int i; เป็นการประกาศ (Declaration) ตัวแปรชื่อ i เป็นตัวแปรประเภท int
int i; i 400 402 404 i = 10; 10 ภาพจำลองการแทนข้อมูลในหน่วยความจำ
แต่มีอีกวิธีที่จะเข้าถึงตัวแปร คือเราจะอ้างถึงตำแหน่งที่เก็บข้อมูล พอยน์เตอร์ เป็นชนิดข้อมูลชนิดหนึ่งของภาษาซี แตกต่างจากชนิดข้อมูลพื้นฐานอื่น ๆ ตัวแปรพอยน์เตอร์เป็นตัวแปรที่ใช้เก็บค่าแอดเดรสของตัวแปรอื่น ๆ
p p i 360 400 400 10 i 10 10 หากมี ตัวแปร i เป็นตัวแปรประเภท int และ ตัวแปร p เป็นตัวแปรประเภทพอยน์เตอร์ p เก็บค่าแอดเดรสของตัวแปร i (หรือ p ชี้ไปที่ตัวแปร i) สามารถจำลองการแทนข้อมูลในหน่วยความจำดังรูป
5.2 การประกาศตัวแปรพอยน์เตอร์ ใช้การดำเนินการชนิดเอกภาค (Unary Operator) * ชื่อเรียกเป็นภาษาอังกฤษว่า Indirection หรือ Dereferencing Operator รูปแบบคำสั่งType *Variable-name; Type ชนิดของตัวแปร * เป็นเครื่องหมายที่แสดงว่า ตัวแปรที่ตามหลัง เครื่องหมายนี้เป็นตัวแปรชนิดพอยน์เตอร์ Variable-nameชื่อตัวแปรที่เป็นตัวแปรพอยน์เตอร์
ประกาศตัวแปร prt ให้เป็นตัวแปรพอยน์เตอร์ ที่ชี้ไปยังตัวแปรชนิด chr ประกาศตัวแปร ip และ ตัวแปร temp เป็นตัวแปรพอยน์เตอร์ที่ชี้ไปยังตัวแปรชนิด int ตัวแปรพอยน์เตอร์ เป็นตัวชี้ไปยังตัวแปรชนิดอื่นๆ การประกาศชนิดของตัวแปรพอยน์เตอร์ ต้องสอดคล้องกับชนิดของตัวแปรนั้นๆ เช่น char *prt; int *ip , *temp; double *dp; ประกาศตัวแปร ip และ ตัวแปร temp เป็นตัวแปรพอยน์เตอร์ที่ชี้ไปยังตัว
5.3 การกำหนดค่าและการอ่านค่าตัวแปรพอยน์เตอร์ • การกำหนดค่าให้กับตัวแปรพอยน์เตอร์ เป็นการกำหนด แอดเดรสของตัวแปรที่มีชนิดข้อมูลสอดคล้องกับชนิดข้อมูลของตัวแปรพอยน์เตอร์ • ใช้ ตัวดำเนินการชนิดเอกภาค (Unary Operator) & เป็นตัวดำเนินการที่อ้างถึงแอดเดรส • ตัวดำเนินการ & เป็นเครื่องหมายที่ใช้เมื่อต้องการให้เอาค่าตำแหน่งที่อยู่(address) ของตัวแปรที่เก็บในหน่วยความจำออกมาใช้ • ตัวดำเนินการ * เป็นเครื่องหมายที่ใช้เมื่อต้องการให้นำค่าที่อยู่ในตำแหน่งที่ตัวแปรพอยน์เตอร์นั้นชี้อยู่ออกมาแสดง
int count , val ,* ptr; count =100; ptr = &count; val = *ptr; ตัวอย่าง1 int x=10,*y; y = &x; ตัวอย่าง 2
ตัวอย่าง 3 int a , *prt , b , c ,*d; a = 25; prt = &a; b = a; c = *prt; d= prt;
ตัวอย่าง int x = 1, y = 2; int *ip, *iq; ip = &x; y = *ip; *ip = 0; y = 5; ip = &y; *ip = 3; iq = ip;
int x =1, y =2; 1 1 x y 400 402 500 502 int *ip, *iq; 2 2 ip iq กำหนดให้ x และ เป็นตัวแปรชนิด int เก็บค่า 1 และ 2 ตามลำดับ ip และ iq เป็นตัวแปรพอยน์เตอร์ ซึ่งชี้ไปที่ชนิดข้อมูล int
ip = &x; 3 1 x y 400 402 500 502 2 400 ip iq ให้ ip ชี้ไปที่ x ดังนั้น ที่ ip เก็บaddress ที่ ip ชี้ไป address ที่ ip ชี้ไปคือ 400
4 y = *ip; 1 1 x y 400 402 500 502 2 400 ip iq y = ค่า ที่ addrerss นี้ point ไป นั่นคือ ip ชี้ที่ 400 ค่าที่ตำแหน่ง 400 คือ 1
5 *ip = 0; 0 1 x y 400 402 500 502 1 400 ip iq กำหนดให้ ค่า ที่ addrerss นี้ point ไป มีค่า เท่ากับ 0 นั่นคือ ip ชี้ที่ 400 ค่าที่ตำแหน่ง 400 คือ 1 เปลี่ยนเป็น 0
6 y = 5; 5 0 x y 400 402 500 502 1 400 ip iq
7 ip = &y; 0 x y 400 402 500 502 5 402 400 ip iq ให้ ipชี้ ไปที่ y ดังนั้น ที่ ip จึงเก็บ address ของ y คือ 402
*ip = 3; 3 0 x y 400 402 500 502 5 402 ip iq กำหนดให้ ค่า ที่ addrerss นี้ point ไป มีค่า เท่ากับ 3 นั่นคือ ip ชี้ที่ 402 ค่าที่ตำแหน่ง 402 คือ 5 เปลี่ยนเป็น 3 8
iq = ip; 0 x y 400 402 500 502 3 402 ip iq 402 เป็นนำค่าaddress ที่เก็บใน ip ให้กับ iq ดังนั้น iq จึงมีค่า 402 หมายความว่า iq ชี้ ไปที่ y 9
5.4 พอยน์เตอร์และอาร์กิวเมนท์ของฟังก์ชัน (Pointers and Function Arguments) ภาษาซีมีการส่งอาร์กิวเมนท์ให้กับฟังก์ชันแบบ By Value และฟังก์ชันสามารถคืนค่า (return) ค่าได้เพียงหนึ่งค่า หากต้องการให้ฟังก์ชันมีการเปลี่ยนแปลงค่าและคืนค่ากลับมายังฟังก์ชันที่เรียกใช้มากกว่าหนึ่งค่า จะต้องนำพอยน์เตอร์เข้ามาช่วย เช่น หากต้องการเขียนฟังก์ชันเพื่อสลับค่าของตัวแปร 2 ตัว ผลลัพธ์ที่ต้องการได้จากฟังก์ชันนี้จะมีค่าของตัวแปร 2 ตัวที่ทำการสลับค่ากัน
void swap (int *px, int *py) { int temp; temp = *px; /* Keep x value to temp */ *px = *py; /* Assign y value to x */ *py = temp; /* Assign old x value to y */ } ตัวอย่างที่ 5.1 โปรแกรมตัวอย่างการสลับค่าตัวแปร 2 ตัวโดยผ่านฟังก์ชัน จะแสดงการรับพารามิเตอร์เป็นตัวแปรชนิดพอยน์เตอร์ #include <stdio.h> void swap (int *, int *); void main ( ) { int x = 5, y = 10; printf(“Before swap : x = %d y = %d\n”, x, y); swap ( &x, &y); /* Pass address of x and y to swap( ) */ printf(“After swap : x = %d y = %d\n”, x, y); }
ตัวอย่างที่ 5.4 เขียนโปรแกรมเพื่อรับข้อมูลจำนวนจริง 3 จำนวนจากผู้ใช้และหาค่าเฉลี่ยของค่าที่รับเข้ามาทั้งหมด โดยเขียนในลักษณะการส่งอาร์กิวเมนท์แบบพอยน์เตอร์ วิเคราะห์ input-process-output มี 3 งานย่อย - รับข้อมูล 3 จำนวน - หาค่าเฉลี่ย - แสดงผลลัพธ์
#include <stdio.h> void readData(int, double *); void calAverage(double, double, double, double *); void printData(double, double, double, double);
void main( ) { double x1, x2, x3, average; readData(1, &x1); readData(2, &x2); readData(3, &x3); calAverage(x1, x2, x3, &average); printData(x1, x2, x3, average); }
void readData(int seq, double *px) { printf("Enter value %d : ", seq); scanf("%lf", px); } void calAverage(double a1, double a2, double a3, double *pAvg) { *pAvg = (a1 + a2 + a3)/3.0; } void printData(double b1, double b2, double b3, double avg) { printf("Average of %.2lf, %.2lf, %.2lf is %.2lf", b1, b2, b3, avg); }
ตัวอย่างที่ 5.5 โจทย์เดียวกับตัวอย่างที่ 5.4 คือ เขียนโปรแกรมเพื่อรับข้อมูลจำนวนจริง 3 จำนวนจากผู้ใช้และหาค่าเฉลี่ยของค่าที่รับเข้ามาทั้งหมด โดยเขียนในลักษณะพอยน์เตอร์ แต่เขียนในอีกลักษณะหนึ่ง #include <stdio.h> void readData(double *, double *, double *); void calAverage(double *, double *, double *, double *); void printData(double *, double *, double *, double *);
void main( ) { double x1, x2, x3, average; readData(&x1, &x2, &x3); calAverage(&x1, &x2, &x3, &average); printData(&x1, &x2, &x3, &average); }
void readData(double *px1, double *px2, double *px3) { printf("Enter value 1 : "); scanf("%lf", px1); printf("Enter value 2 : "); scanf("%lf", px2); printf("Enter value 3 : "); scanf("%lf", px3); }
void calAverage(double *pa1, double *pa2, double *pa3, double *pAvg) { *pAvg = (*pa1 + *pa2 + *pa3)/3.0; } void printData(double *pb1, double *pb2, double *pb3, double *pAvg) { printf("Average of %.2lf, %.2lf, %.2lf is %.2lf", *pb1, *pb2, *pb3, *pAvg); }
ตัวอย่างที่ 5.6 เขียนโปรแกรมเพื่อคำนวณพื้นที่ของสี่เหลี่ยมรูปหนึ่ง โดยรับข้อมูลความกว้างและความยาวของรูปสี่เหลี่ยมจากผู้ใช้ กำหนดให้ใช้ฟังก์ชันเพื่อคำนวณพื้นที่ของรูปสี่เหลี่ยม ดังโปรโตไทป์ void calRecArea(float, float, float *); โดยที่ พารามิเตอร์ตัวแรกคือความกว้าง พารามิเตอร์ตัวที่ 2 คือความยาว และพารามิเตอร์ตัวที่ 3 คือพื้นที่ของรูปสี่เหลี่ยม
void calRecArea(float w, float l, float *pArea) { *pArea = w * l; } #include <stdio.h> void main( ) { float width, length, area; printf("Enter width : "); scanf("%f", &width); printf("Enter length : "); scanf("%f", &length); calRecArea(width, length, &area); printf("Rectangle area is %.2f", area); }