310 likes | 468 Views
Department of Computer Engineering Faculty of Engineering Prince of Songkla University. 240-101 Introduction to Computer Programming. Email: introcom@coe.psu.ac.th. คณาจารย์ภาควิชาวิศวกรรมคอมพิวเตอร์. Department of Computer Engineering Faculty of Engineering
E N D
Department of Computer Engineering Faculty of Engineering Prince of Songkla University 240-101Introduction to Computer Programming Email: introcom@coe.psu.ac.th คณาจารย์ภาควิชาวิศวกรรมคอมพิวเตอร์
Department of Computer Engineering Faculty of Engineering Prince of Songkla University บทที่ 6พอยน์เตอร์ (Pointer)
หัวข้อศึกษา • พอยน์เตอร์คืออะไร • สัญญลักษณ์ที่ใช้กับพอยน์เตอร์ • การเรียกฟังก์ชันแบบ Call-by-Reference • การกระทำทางคณิตศาสตร์กับพอยน์เตอร์ • การจองหน่วยความจำ • อาร์เรย์ของพอยน์เตอร์
พอยน์เตอร์คืออะไร • เมื่อมีการประกาศตัวแปร ค่าของตัวแปรจะถูกเก็บอยู่ในหน่วยความจำ • แอดเดรสของตัวแปร คือ ตำแหน่งในหน่วยความจำที่ใช้เก็บตัวแปรตัวนั้น เขียนแทนด้วยเครื่องหมาย & • เช่น แอดเดรสของตัวแปร x เขียนแทนด้วย &x
พอยน์เตอร์คืออะไร (ต่อ) • พอยน์เตอร์ คือ ตัวแปรชนิดหนึ่งที่ใช้ในการเก็บค่าแอดเดรสของตัวแปรตัวอื่น • พอยน์เตอร์มีหลายชนิด(ตามชนิดตัวแปรที่มีอยู่) • พอยน์เตอร์ของตัวแปร int • พอยน์เตอร์ของตัวแปร float • พอยน์เตอร์ของตัวแปร char • ฯลฯ • ประโยชน์ของพอยน์เตอร์ • ใช้ในการพัฒนาโครงสร้างข้อมูล (Data Structure) • ใช้ในโปรแกรมที่ต้องมีการติดต่อกับหน่วยความจำโดยตรง
สัญลักษณ์ที่ใช้กับพอยน์เตอร์สัญลักษณ์ที่ใช้กับพอยน์เตอร์ • การประกาศตัวแปร ใช้เครื่องหมาย * เช่น • int *countPtr; countPtr เป็นพอยน์เตอร์ของ int (ซึ่งสามารถใช้ในการเก็บค่าแอดเดรสของตัวแปร int ได้) • char *str; str เป็นพอยน์เตอร์ของ char • float *nums; nums เป็นพอยน์เตอร์ของ float
สัญลักษณ์ที่ใช้กับพอยน์เตอร์ (ต่อ) • การกำหนดค่าให้กับพอยน์เตอร์ • ใช้เครื่องหมาย = • ค่าที่กำหนดให้กับพอยน์เตอร์ต้องเป็นค่าแอดเดรสของตัวแปร int num = 6; int *numPtr; numPtr = # numPtr num 50000 50000 6 40000 numPtr num กำหนดให้ numPtr ชี้ไปที่ num 6
สัญลักษณ์ที่ใช้กับพอยน์เตอร์ (ต่อ) • การอ้างอิงถึงค่าในตำแหน่งที่พอยน์เตอร์ชี้อยู่ • เรียกอีกอย่างว่า “Dereferencing” • ใช้เครื่องหมาย * นำหน้าตัวแปร • ตัวอย่างเช่น cout << *numPtr; *numPtr = 20; numPtr num 6 20
a 2.5 b 5.6 p q ตัวอย่างที่ 6-1 3.5 8.6 #include <iostream.h> int main() { float a = 2.5,b = 5.6; float *p,*q; p = &a; q = &b; cout << "*p = " << *p << endl; cout << "*q = " << *q << endl; *p = *p + 1; *q = *q + 3; cout << "a = " << a << endl; cout << "b = " << b << endl; return 0; } ผลลัพธ์ *p = 2.5 *q = 5.6 a = 3.5 b = 8.6
การเรียกใช้แบบ Call-by-Reference • การเรียกใช้ฟังก์ชันมี 2 แบบ คือ Call-by-Value และ Call-by-Reference • Call-by-Value • ใช้วิธีการส่งค่าของตัวแปรให้กับฟังก์ชัน • ไม่สามารถแก้ไขค่าของอาร์กิวเมนต์ภายในฟังก์ชันได้ • ใช้กับฟังก์ชันที่รับค่าเข้าเป็นตัวแปรธรรมดา (int, float, char, ...) • Call-by-Reference • ใช้วิธีการส่งแอดเดรสของตัวแปรไปให้ฟังก์ชัน • ใช้กับฟังก์ชันที่รับค่าเข้าเป็นพอยน์เตอร์หรืออาร์เรย์
main number 5 n squareByValue ตัวอย่างที่ 6-2 #include <iostream.h> int squareByValue(int n); int main() { int number = 5; cout << "The original value of number is " << number <<endl; number = squareByValue(number); cout << "The new value of number is " << number << endl; return 0; } int squareByValue(int n) { n = n*n; return n; } 25 5 25
main number 5 nPtr squareByReference ตัวอย่างที่ 6-3 #include <iostream.h> void squareByReference(int *nPtr); int main() { int number = 5; cout << "The original value of number is " << number <<endl; squareByReference(&number); cout << "The new value of number is " << number << endl; return 0; } void squareByReference(int *nPtr) { *nPtr = *nPtr * *nPtr; } 25
การใช้ตัวดำเนินทางคณิตศาสตร์กับพอยน์เตอร์การใช้ตัวดำเนินทางคณิตศาสตร์กับพอยน์เตอร์ • ตัวดำเนินการทางคณิตศาสตร์ที่มักจะใช้กับพอยน์เตอร์ • +, -, ++, --, +=, -= • ใช้ในการเลื่อนพอยน์เตอร์ไปข้างหน้าหรือถอยหลัง • การเลื่อนพอยน์เตอร์จะเลื่อนทีละ 1 บล็อก เช่น • ถ้าเป็นพอยน์เตอร์ของ int 1 บล็อกคือ 4 ไบต์ • ถ้าเป็นพอยน์เตอร์ของ char 1 บล็อกคือ 1 ไบต์ • ถ้าเป็นพอยน์เตอร์ของ float 1 บล็อกคือ 4 ไบต์ • ฯลฯ
ตัวอย่างการเลื่อนพอยน์เตอร์ตัวอย่างการเลื่อนพอยน์เตอร์ int v[5]; int *vPtr; vptr = v; //or vPtr = &v[0]; vPtr = vPtr + 2;
'C' 'o' 'e' '\0' msg[9] msg[0] msg[1] msg[2] msg[3] ... ptr ตัวอย่างที่ 6-4 #include <iostream.h> #include <string.h> int main() { char msg[10]; char *ptr; cout << "Enter text to reverse: "; cin >> msg; int len = strlen(msg); ptr = &msg[len-1]; while(ptr >= &msg[0]) { cout << *ptr; ptr--; } return 0; } Enter text to reverse: Coe eoC
การใช้คำสั่ง cout กับ char * และ อารเรย์ของ char • ถ้าใช้คำสั่ง cout กับตัวแปรอาร์เรย์ของ char สิ่งที่พิมพ์ออกมาคือ ตัวอักษรตั้งแต่อีลีเมนต์แรกไปจนกว่าจะเจอ ‘\0’ • ถ้าใช้คำสั่ง cout กับพอยน์เตอร์ชนิด char * สิ่งที่พิมพ์ออกมาคือ ตัวอักษรตั้งแต่ตำแหน่งที่พอยน์เตอร์ชี้อยู่ไปจนกว่าจะเจอ ‘\0’ • ตัวอย่างเช่น char name[8] = "Somchai"; cout << name; char *namePtr = name; cout << namePtr; namePtr = &name[3]; cout << namePtr; Somchai Somchai chai
ความสัมพันธ์ระหว่างอาร์เรย์กับพอยน์เตอร์ความสัมพันธ์ระหว่างอาร์เรย์กับพอยน์เตอร์ • ตัวแปรอาร์เรย์และพอยน์เตอร์สามารถใช้งานแทนกันได้ในหลายโอกาส • ตัวแปรอาร์เรย์ถือเป็นพอยน์เตอร์เนื่องจากค่าในตัวแปรอาร์เรย์คือแอดเดรสของอีลีเมนต์แรก
ความสัมพันธ์ระหว่างอาร์เรย์กับพอยน์เตอร์ (ต่อ) • สามารถกำหนดให้พอยน์เตอร์ชี้ไปที่อาร์เรย์ได้ int b[5]; int *bPtr; bPtr = b; // มีความหมายเหมือนกับbPtr = &b[0]; • สามารถใช้สัญลักษณ์ [] กับพอยน์เตอร์ได้ เช่น • bPtr[2]หมายถึง ค่าในตำแหน่งที่ถัดจาก bPtr ชี้อยู่ ไปอีก 2 บล็อก • bPtr[0]หมายถึง ค่าในตำแหน่งเดียวกับที่ bPtr ชี้อยู่
b[4] b[0] b[1] b[2] b[3] 6 2 7 5 4 bPtr ตัวอย่างที่ 6-5 #include <iostream.h> int main() { int b[5] = {2,7,5,4,6}; int *bPtr; bPtr = b; cout << "bPtr[0] = " << bPtr[0] << endl; cout << "bPtr[1] = " << bPtr[1] << endl; bPtr = &b[2]; bPtr[1] = 10; cout << "b[1] = " << b[1] << endl; cout << "b[3] = " << b[3] << endl; return 0; } 10 bPtr[0] = 2 bPtr[1] = 7 b[1] = 7 b[3] = 10
การจองหน่วยความจำ (Memory Allocation) • ในการประกาศตัวแปรแต่ละครั้ง คอมไพเลอร์จะจองหน่วยความจำชั่วคราว เพื่อใช้เก็บค่าของตัวแปรตัวนั้น เช่น • int a; จองหน่วยความจำขนาด 4 ไบต์ • char ch; จองหน่วยความจำขนาด 1 ไบต์ • int nums[10]; จองหน่วยความจำขนาด 40 ไบต์ • char name[20]; จองหน่วยความจำขนาด 20 ไบต์ • แต่หน่วยความจำเหล่านี้จะมีขอบเขตการใช้งานอยู่ภายในเครื่องหมาย {} ที่ได้มีประกาศตัวแปรไว้เท่านั้น • เช่น ตัวแปรที่ประกาศไว้ในฟังก์ชัน เมื่อออกจากฟังก์ชันแล้ว หน่วยความจำสำหรับตัวแปรเหล่านั้นก็จะถูกคืนให้แก่ระบบ
การจองหน่วยความจำ (ต่อ) • ถ้าต้องการหน่วยความจำเพื่อใช้ในการเก็บข้อมูล โดยสามารถที่จะคืนหน่วยความจำส่วนนี้เมื่อไรก็ได้ จะต้องจองหน่วยความจำโดยใช้คำสั่ง new • การจองหน่วยความจำโดยใช้คำสั่ง new มี 2 แบบ คือ • การจองหน่วยความจำแบบหนึ่งบล็อก • การจองหน่วยความจำเพื่อใช้งานเป็นอาร์เรย์
ptr การจองหน่วยความจำแบบหนึ่งบล็อก • ใช้แทนการประกาศตัวแปร 1 ตัว • รูปแบบ: ตัวแปรพอยน์เตอร์ = new ชนิดตัวแปร; • เช่น int *ptr; ptr = new int; • การคืนหน่วยความจำ delete ptr;
nums การจองหน่วยความจำเพื่อใช้งานเป็นอาร์เรย์ • รูปแบบ: ตัวแปรพอยน์เตอร์ = new ชนิดตัวแปร[ขนาดอาร์เรย์]; • ตัวอย่างเช่น int *nums; nums = new int[5]; • การใช้งานจะใช้แบบอาร์เรย์หรือพอยน์เตอร์ก็ได้ เช่น nums[1] = 10; // same as *(num+1) = 10; • การคืนหน่วยความ ต้องมีเครื่องหมาย [] หน้าตัวแปรพอยน์เตอร์ด้วย delete []nums; 10
ตัวอย่างที่ 6-6 #include <iostream.h> int main() { int num_std; cout << "Enter number of students: "; cin >> num_std; float *scores = new float[num_std]; int i; for(i=0;i<num_std;i++) { cout << "Enter score of student " << i+1 << ": "; cin >> scores[i]; }
ตัวอย่างที่ 6-6 (ต่อ) cout << "\nThe scores are "; float total = 0; for(i=0;i<num_std;i++) { cout << scores[i] << " "; total = total + scores[i]; } cout << "\nTotal scores of all students is "<< total; delete []scores; return 0; }
ตัวอย่างที่ 6-6 (ต่อ) • จากโปรแกรม จะเห็นว่าสามารถจองหน่วยความจำได้ตามที่ผู้ใช้กำหนด • แต่ถ้าใช้ตัวแปรอาร์เรย์ธรรมดา จะไม่สามารถทำอย่างนี้ได้เนื่องจากขนาดอาร์เรย์ต้องเป็นค่าคงที่ จะกำหนดเป็นตัวแปรไม่ได้
สตริง (String) • สตริงมี 3 ชนิด คือ • ค่าคงที่ประเภทข้อความ เช่น "Sanook" • อาร์เรย์ของ char • พอยน์เตอร์ชนิด char *
สตริงแบบที่ใช้อาร์เรย์ของ char • ตัวอย่างเช่น char name[8] = "Sawat"; • การเปลี่ยนแปลงข้อความในอาร์เรย์ของ char • ห้ามใช้เครื่องหมาย = (เช่น name = "Sombat"; ไม่ได้) • ใช้ฟังก์ชัน strcpy เช่น strcpy(name,"Sombat");
หน่วยความจำชั่วคราว สตริงแบบที่ใช้พอยน์เตอร์ชนิด char * • สามารถกำหนดค่าโดยใช้เครื่องหมาย = ได้ • char *str; • str = "Hello";
สตริงแบบที่ใช้พอยน์เตอร์ชนิด char * (ต่อ) • สามารถเปลี่ยนแปลงข้อความโดยใช้ฟังก์ชัน strcpy ก็ได้ แต่ต้องมีการจองหน่วยความจำเพื่อใช้ในการเก็บข้อความที่จะนำมาวางเสียก่อน • ตัวอย่างเช่น char *str = new char[6]; strcpy(str,"Hello");
อาร์เรย์ของพอยน์เตอร์อาร์เรย์ของพอยน์เตอร์ • ใช้ในกรณีที่ต้องการใช้งานพอยน์เตอร์หลายๆ ตัว • ตัวอย่างเช่น char *name_arr[3]; name_arr[0] = "Somchai"; name_arr[1] = "Sombat"; name_arr[2] = "Sawat";