7 pointer day10
TRANSCRIPT
พอยนเตอร พอยนเตอร (Pointer)(Pointer)
Pointer
• Pointer หมายถงตำาแหนงหรอทอยในหนวยความจำา (memory address) Pointer (ตวช) ถอวาเปนตวแปรชนดหนง ทเกบคา address ของหนวยความจำา
• เปนจดเดนทสดในภาษาซ สามารถทำางานได รวดเรวและไมเปลองเนอทหนวยความจำา
• มความยดหยนสง เหมาะสำาหรบการทำางานของโปรแกรมทมการเปลยนแปลงไมคงท(dynamic) เชน โครงสรางขอมลแบบ linked list
Pointer แบงไดเปน 2 ลกษณะคอ พอยนเตอรทเปนคาคงท และ พอยนเตอรทเปน
คาตวแปร
พอยนเตอรทเปนคาคงท มสองกรณคอ1. จากการใช operator & (เรยกวา Address of)ซงถา
operator & นำาหนาตวแปรใดจะไดตำาแหนงหนวยความจำา (memory address) ซงเปนคาคงท
2. เกดจากการประกาศตวแปร array เมอใดกตามทมการประกาศตวแปรแบบอะเรย ชอตวแปรอะเรยทไมม index หรอ subscript จะเปน พอยนเตอรทเปนคาคงท
Pointer
หนวยความจำาในคอมพวเตอรจะมการแบงเปนสวน ๆ โดยแตละสวนจะมคาตำาแหนงไว คาตำาแหนงนจะเรยกวาทอยของหนวยความจำาหรอ address
Pointer กบ หนวยความจำา
Int a,b,c ;char ch;
a = 10;b = 20;c = 30ch = ‘x’
Value
10
20
30
x
variable
a
b
c
d
Value
FFF4
FFF2
FFF0
FFEF
จะใชเครองหมาย * เรยกวา Derefencing Operator ไวหนาตวแปรทตองการ
ประกาศรปแบบ
type *variable_name
หรอ type* variable_name
Type คอชนดของตวแปรvariable-name คอชอของตวแปร pointer
Ex.
int *ptr; หรอ int* prt;
เปนการประกาศตวแปร ptr ชไปยงขอมลชนด int
การประกาศ ตวแปรแบบ พอยนเตอร
• ตวดำาเนนการแอดเดรส (Address Operator)
ใชเครองหมาย & นำาหนาตวแปร เพอระบถง address ของตวแปรในหนวยความจำา ทจะกำาหนดคาใหแกตวแปร pointer
• ตวดำาเนนการอางอง (Dereferencing Operator)
ใชเครองหมาย * นำาหนาตวแปร pointer เพอ ระบถงคาทอยใน address ท pointer ชอย
ตวดำาเนนการสำาหรบ พอยนเตอร
ตวอยาง int a;
int *pa;
a = 5;
pa=&a;
• การอางถงตำาแหนงหรอ address ของตวแปร ทถกช ดวย pa (address ของ a) เขยนแทนดวย pa
• การอางถงขอมลทตำาแหนงท pa ชอย (value ของa) เขยนแทนดวย *pa
• การอางถง address ของตวแปร pa เขยนแทนดวย &pa
การใชตวแปร พอยนเตอร
5 60000
60000 55900
. .
.
.
.
.
a
pa
• เมอมการประกาศตวแปร คาของตวแปรจะถกเกบอยในหนวยความจำา
• แอดเดรสของตวแปร คอ ตำาแหนงในหนวยความจำาทใชเกบตวแปรตวนน เขยนแทนดวยเครองหมาย &– เชน แอดเดรสของตวแปร x เขยนแทนดวย &x
560000
1055900
y
x
..
.
..
.
int x = 10;...
int y = 5;
การใชตวแปร พอยนเตอร
• พอยนเตอร คอ ตวแปรชนดหนงทใชในการเกบคาแอดเดรสของตวแปรตวอน
• พอยนเตอรมหลายชนด(ตามชนดตวแปรทมอย)– พอยนเตอรของตวแปร int– พอยนเตอรของตวแปร float– พอยนเตอรของตวแปร char– ฯลฯ
• ประโยชนของพอยนเตอร– ใชในการพฒนาโครงสรางขอมล (Data Structure)– ใชในโปรแกรมทตองมการตดตอกบหนวยความจำา
โดยตรง
การใชตวแปร พอยนเตอร
สญลกษณทใชกบพอยนเตอร• การประกาศตวแปร ใชเครองหมาย * เชน
– int* countPtr;
countPtr เปนพอยนเตอรของ int (ซงสามารถใชในการเกบคาแอดเดรสของตวแปร int ได)
– char* str;
str เปนพอยนเตอรของ char– float *nums;
nums เปนพอยนเตอรของ float
สญลกษณทใชกบพอยนเตอร (ตอ)• การกำาหนดคาใหกบพอยนเตอร• ใชเครองหมาย =• คาทกำาหนดใหกบพอยนเตอรตองเปนคาแอดเดรสของ
ตวแปร
int num = 6;
int *numPtr;
numPtr = #
50000numPtr
6num
6numnumPtr
กำาหนดให numPtr ชไปท num
5000040000
สญลกษณทใชกบพอยนเตอร (ตอ)
• การอางองถงคาในตำาแหนงทพอยนเตอรชอย– เรยกอกอยางวา “Dereferencing”– ใชเครองหมาย * นำาหนาตวแปร– ตวอยางเชน int num = 6;int *numPtr;
numPtr = #
cout << *numPtr;
*numPtr = 20;
6numnumPtr20
MemoryAddress Memory Variable
0x0012FF48 100 X
0x0012FF4c
0x0012FF50 11.25 y
0x0012FF54
0x0012FF58
0x0012FF5C 0x0012FF48 px
0x0012FF60
0x0012FF64
0x0012FF68 0x0012FF50 py
0x0012FF6C
…….
การใชตวแปร พอยนเตอร
Int x = 100; Int *px = &x;float y = 11.25;float *py;py = &y
*ตวแปรพอยนเตอรจะเกบคาของหนวยความจำา
2.5a
p
5.6b
q
#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;}
3.5 8.6
*p = 2.5*q = 5.6a = 3.5b = 8.6
ผลลพธ
การเรยกใชแบบ Call-by-Reference• การเรยกใชฟงกชนม 2 แบบ คอ Call-by-Value
และ Call-by-Reference• Call-by-Value– ใชวธการสงคาของตวแปรใหกบฟงกชน– ไมสามารถแกไขคาของอารกวเมนตภายในฟงกชนได– ใชกบฟงกชนทรบคาเขาเปนตวแปรธรรมดา (int,
float, char, ...)• Call-by-Reference– ใชวธการสงแอดเดรสของตวแปรไปใหฟงกชน– ใชกบฟงกชนทรบคาเขาเปนพอยนเตอรหรออารเรย
#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;
}
5number
main
squareByValue
n525
25
#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;
} nPtr
5number
main
squareByReference
25
การใชตวดำาเนนทางคณตศาสตรกบพอยนเตอร
• ตวดำาเนนการทางคณตศาสตรทมกจะใชกบพอยนเตอร– +, -, ++, --, +=, -=– ใชในการเลอนพอยนเตอรไปขางหนาหรอถอยหลง
• การเลอนพอยนเตอรจะเลอนทละ 1 บลอก เชน– ถาเปนพอยนเตอรของ int 1 บลอกคอ 4 ไบต– ถาเปนพอยนเตอรของ char 1 บลอกคอ 1 ไบต– ถาเปนพอยนเตอรของ float 1 บลอกคอ 4 ไบต– ฯลฯ
ตวอยางการเลอนพอยนเตอร
v[0]
vPtr
v[1] v[2] v[3] v[4]
3000 3004 3008 3012 3016int v[5];int *vPtr;vptr = v;//or vPtr = &v[0];
v[0]
vPtr
v[1] v[2] v[3] v[4]
3000 3004 3008 3012 3016
vPtr = vPtr + 2;
#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: CoeeoC
'\0''e''o''C'
msg[3]msg[2]msg[1]msg[0]...
msg[9]
ptr
การใชคำาสง 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 ชอย
#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;
}
bPtr[0] = 2bPtr[1] = 7b[1] = 7b[3] = 10
4
b[3]
5
b[2]
7
b[1]
2
b[0]
6
b[4]
bPtr
10
การจองหนวยความจำา (Memory Allocation)• ในการประกาศตวแปรแตละครง คอมไพเลอรจะจอง
หนวยความจำาชวคราว เพอใชเกบคาของตวแปรตวนน เชน– int a; จองหนวยความจำาขนาด 4 ไบต– char ch; จองหนวยความจำาขนาด 1 ไบต
– int nums[10]; จองหนวยความจำาขนาด 40 ไบต
– char name[20]; จองหนวยความจำาขนาด 20 ไบต
• แตหนวยความจำาเหลานจะมขอบเขตการใชงานอยภายในเครองหมาย {} ทไดมประกาศตวแปรไวเทานน– เชน ตวแปรทประกาศไวในฟงกชน เมอออกจาก
ฟงกชนแลว หนวยความจำาสำาหรบตวแปรเหลานนกจะถกคนใหแกระบบ
การจองหนวยความจำา (ตอ)• ถาตองการหนวยความจำาเพอใชในการเกบ
ขอมล โดยสามารถทจะคนหนวยความจำาสวนนเมอไรกได จะตองจองหนวยความจำาโดยใชคำาสง new
• การจองหนวยความจำาโดยใชคำาสง new ม 2 แบบ คอ– การจองหนวยความจำาแบบหนงบลอก– การจองหนวยความจำาเพอใชงานเปนอารเรย
การจองหนวยความจำาแบบหนงบลอก• ใชแทนการประกาศตวแปร 1 ตว• รปแบบ:
ตวแปรพอยนเตอร = new ชนดตวแปร;• เชน
int *ptr;
ptr = new int;
• การคนหนวยความจำาdelete ptr;
ptr
การจองหนวยความจำาเพอใชงานเปนอารเรย• รปแบบ:
ตวแปรพอยนเตอร = new ชนดตวแปร[ขนาดอารเรย];
• ตวอยางเชนint *nums;
nums = new int[5];
• การใชงานจะใชแบบอารเรยหรอพอยนเตอรกได เชนnums[1] = 10; // same as *(num+1) = 10;
• การคนหนวยความ ตองมเครองหมาย [] หนาตวแปรพอยนเตอรดวยdelete []nums;
10nums
#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];
}
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;
}• จากโปรแกรม จะเหนวาสามารถจองหนวยความจำาไดตามทผใช
กำาหนด• แตถาใชตวแปรอารเรยธรรมดา จะไมสามารถทำาอยางนได
เนองจากขนาดอารเรยตองเปนคาคงท จะกำาหนดเปนตวแปรไมได
สตรง (String)• สตรงม 3 ชนด คอ– คาคงทประเภทขอความ เชน "Sanook"– อารเรยของ char – พอยนเตอรชนด char *
สตรงแบบทใชอารเรยของ char• ตวอยางเชน
char name[8] = "Sawat";
• การเปลยนแปลงขอความในอารเรยของ char– หามใชเครองหมาย = (เชน name = "Sombat"; ไม
ได)– ใชฟงกชน strcpy เชนstrcpy(name,"Sombat");
name[0]
'S'
name[1]
'a'
name[2]
'w'
name[3]
'a'
name[4]
't'
name[5]
'\0'
name[6] name[7]
สตรงแบบทใชพอยนเตอรชนด char *
• สามารถกำาหนดคาโดยใชเครองหมาย = ได– char *str;– str = "Hello";
‘H’
str
‘e’ ‘l’ ‘l’ ‘o’ ‘\0’
หนวยความจำาชวคราว
สตรงแบบทใชพอยนเตอรชนด 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";
‘S’name_arr[0] ‘o’ ‘m’ ‘c’ ‘h’ ‘\0’‘a’ ‘i’
‘S’ ‘o’ ‘m’ ‘b’ ‘a’ ‘t’ ‘\0’name_arr[1]
‘S’ ‘a’ ‘w’ ‘a’ ‘t’ ‘\0’name_arr[2]