BAB
2.
Pointer
2.1 Pengantar
Pointer adalah sebuah variabel yang memuat (yang nilainya berupa) alamat
memori dari variabel lain. Unit dasar dari memori adalah sebuah bit. Bit-bit
dikelompokkan ke dalam grup-grup delapan bit. Grup-grup bit ini disebut dengan
byte. Memori utama (RAM) dari komputer memuat byte-byte yang dinomori secara
sekuensial. Setiap byte dinomori dan nomor ini adalah alamatnya. Ketika Anda
mendeklarasikan sebuah variabel, Anda menyebutkan tipe dan nama variabel, dan
kompiler berikut dengan sistem operasi mengalokasikan suatu blok memori dan
lokasi untuk menyimpan nilai dari variabel tersebut. Jumlah byte yang
dialokasikan kepada suatu variabel untuk penyimpanan nilainya bergantung pada
tipe data dari variabel tersebut. Sebagai contoh, umumnya 4 byte dialokasikan
untuk menyimpan sebuah nilai integer. Alamat
dari sebuah variabel adalah alamat (nomor byte) dari byte pertama dari blok
memori yang dialokasikan kepada variabel itu. Jadi, variabel mendapatkan
sebuah alamat dimana nilainya disimpan. Anda dapat mengekstraksi alamat memori
dari sebuah variabel dengan menggunakan operator
alamat (&), yang juga dikenal dengan operator referensi. Sebagai contoh, jika n adalah sebuah variabel,
maka alamatnya diberikan oleh &n. Anda dapat mendeklarasikan variabel lain
untuk menyimpan &n, yang
merupakan alamat dari variabel n. Variabel (yang menyimpan &n) itu disebut dengan pointer yang menunjuk ke n.
2.2 Deklarasi
Pointer
Deklarasi atas sebuah variabel pointer dilakukan dengan menyebutkan tipe
data dari variabel yang ditunjuknya, diikuti dengan operator indireksi, yang juga dikenal dengan operator dereferensi (*) dan nama dari variabel pointer. Operator
(*) memberitahu kompiler bahwa variabel yang sedang dideklarasikan adalah
sebuah pointer. Nama dari variabel pointer sama seperti variabel biasa.
Sejumlah ilustrasi dari deklarasi pointer untuk variabel-variabel int diberikan berikut.
int m,
n,; //m dan
n adalah variabel-variabel integer
int *ptr
; //ptr merupakan
pointer yang menunjuk ke sembarang nilai integer
int* ptr
= &n; //ptr sekarang
menunjuk ke n.
int *ptr
= &m; //ptr sekarang
menunjuk ke m
int* ptr = 0; //sekarang ptr diinisialisasi dengan 0.
Perhatikan pula bahwa Anda bisa mendeklarasikan pointer dengan int* ptr atau dengan int *ptr, dimana simbol asterisk (*)
dilekatkan pada int pada kasus pertama atau pada ptr pada kasus kedua. Adalah
praktek pemrograman yang baik untuk menginisialisasi pointer ketika ia
dideklarasikan. Pointer dapat diinisialisasi dengan suatu alamat atau dengan 0
atau NULL, yang merupakan sebuah konstanta simbolis yang didefinisikan di dalam
bahasa C dan diwarisi oleh C++. NULL juga didefinisikan di dalam file header <iostream> dan file-file header
lain di dalam C++. Pointer NULL tidak menunjuk ke data apapun.
Sebuah pointer yang menunjuk ke suatu variabel yang memiliki nilai desimal
titik-mengambang seperti PI = 3.14159;
dan yang menunjuk ke sebuah variabel karakter dideklarasikan seperti berikut.
Dimisalkan bahwa pf adalah nama dari
pointer yang menunjuk ke sebuah variabel float,
pd adalah nama pointer yang menunjuk
ke sebuah variabel double, dan pc adalah nama pointer yang menunjuk ke
sebuah variabel karakter.
GAMBAR 2.1 Pointer-pointer yang menunjuk ke
pelbagai tipe data
Pointer-pointer yang menunjuk ke dua atau lebih variabel yang bertipe sama
dapat dideklarasikan pada baris yang sama seperti ditunjukkan pada kode
berikut.
int n, y,
*ptrn, *py; //n dan y adalah variabel-variabel integer
//ptrn dan
py adalah pointer-pointer
ptrn = &n; //inisialisasi
dari pointer ptrn dengan &n
py = &y; //inisialisasi
dari pointer py dengan &y
Pada deklarasi di atas, ptrn
adalah pointer yang menunjuk ke n dan py
adalah pointer yang menunjuk ke y. Anda juga bisa menggunakan typedef berikut untuk mendeklarasikan
sejumlah pointer bertipe sama.
typedef double* ptd;
double x, y, z;
ptd px = &x, py = &y, pz = &z;
OPERATOR INDIREKSI ATAU DEREFERENSI
Nilai dari sebuah variabel bisa didapatkan dari pointernya menggunakan operator indireksi yang juga dikenal
dengan operator dereferensi (*).
Aplikasi dari operator dereferensi diberikan berikut.
int n = 60,
*ptrn;
ptrn = &n;
*ptrn = 60; //menggunakan
operator dereferensi
Program 2.1 berikut mengilustrasikan pendeklarasian atas pointer-pointer
dan aplikasi dari operator alamat (&). Pointer juga adalah suatu variabel
yang kepadanya dialokasikan sebuah blok memori untuk menyimpan nilainya (yang
merupakan alamat dari variabel lain). Operator alamat (&) dapat pula
digunakan untuk mendapatkan alamat dari pointer.
Program 2.1 Mengilustrasikan pendeklarasian
pointer dan penggunaan operator alamat &
|
|
|
#include <iostream>
using namespace std;
int main()
{
int
n = 60 ;
double
B = 8.56;
int*
ptrn = &n; //ptrn adalah
pointer yang menunjuk ke variabel int n.
double
*pB = &B; //pB adalah pointer
yang menunjuk ke variabel double B
cout<<"n =
"<<n<<", B = "<<B<<endl;
cout<<"Alamat dari n adalah =
"<<&n<<", ptrn = "<<ptrn<<endl;
cout<< "*ptrn =
"<<*ptrn<<", *pB = " <<*pB <<endl;
cout<<"Alamat dari B =
"<<&B <<", pB = "<<pB<<endl;
cout<<"Alamat dari ptrn =
"<<&ptrn<<endl;
return
0;
}
|
KELUARAN
|
|
n = 60, B =
8.56
Alamat dari n
adalah = 0018FF44, ptrn = 0018FF44
*ptrn = 60, *pB
= 8.56
Alamat dari B =
0018FF3C, pB = 0018FF3C
Alamat dari
ptrn = 0018FF38
|
Dari keluaran program, jelaslah bahwa n dan *ptrn memiliki nilai yang sama, yaitu 60. Sama halnya, B dan *pB keduanya sama bernilai 8.56. Jadi,
ini menunjukkan bahwa penggunaan operator dereferensi (*) pada variabel pointer
ptrn dan pB menghasilkan nilai yang disimpan di dalam alamat yang
ditunjuknya. Program juga menghasilkan alamat di mana ptrn disimpan. Di sini,
Anda melekatkan ptr atau p pada nama variabel untuk mengindikasikan bahwa
variabel itu adalah pointer. Tetapi, Anda sebenarnya bisa memberikan nama legal
apapun. Program berikut mengilustrasikan beberape deklarasi pointer lain dan
penggunaan dari typedef.
Program 2.2 Mengilustrasikan typedef
pada pendeklarasian pointer
|
|
|
#include <iostream>
using namespace std;
int main()
{
char
ch = 'S';
char*
pc = &ch;
cout<<"*pc =
"<<*pc<<endl;
double
x = 4.5, z;
typedef
double* pd;
pd px = &x; //di sini, pd adalah singkatan untuk double*
cout<<"px =
"<<px<<endl; //menampilkan
nilai dari px
cout<<"&x = "<<
&x<<endl; //menampilkan
alamat dari &x
pd pz = &z;
pz = px; //px
(alamat dari x) ditugaskan kepada pz
cout<<"*pz =
"<<*pz<<endl;
cout<<"*px =
"<<*px<<endl;
return
0;
}
|
KELUARAN
|
|
*pc = S
px = 0012FF70
&x = 0012FF70
*pz = 4.5
*px = 4.5
|
Keluaran menunjukkan bahwa alamat dari x sama dengan nilai dari px dan dengan mengekuasikan pz = px, Anda juga membuat pz untuk
menunjuk ke nilai dari x seperti diilustrasikan pada Gambar 2.2.
GAMBAR 2.2 Dua pointer menunjuk ke variabel yang
sama
Pointer-pointer yang menunjuk ke semua
tipe data menempati ukuran memori yang sama karena nilai dari suatu pointer
adalah alamat memori, yaitu sebuah integer tak-bertanda. Namun, variabel-variabel yang ditunjuk oleh pointer-pointer, tentu saja,
menempatkan ukuran blok memori yang berbeda yang tergantung dari tipe datanya.
Ini diilustrasikan pada program 2.3.
Program 2.3 Mengilustrasikan ukuran dari pointer yang
menunjuk ke semua tipe data adalah sama
|
|
|
#include <iostream>
using namespace std;
int main()
{
int
n = 60, *pn;
double
PI = 3.14159, *pPI;
pPI = &PI;
pn = &n;
char
ch = 'M', *sam; //sam adalah nama pointer
sam = &ch; //pointer diinisialisasi dengan &ch.
cout<<"Ukuran dari pointer yang
menunjuk ke int n = " <<sizeof(pn)<<endl;
cout<<"Ukuran dari pointer yang
menunjuk ke double PI = "<<sizeof(pPI)<<endl;
cout<<"Ukuran dari pointer yang
menunjuk ke char ch = "<<sizeof(sam)<<endl;
cout<<"Variabel-variabel yang
digunakan: "<<*pn <<", "<<*pPI<<"
dan "<<*sam<< endl;
return
0;
}
|
KELUARAN
|
|
Ukuran dari
pointer yang menunjuk ke int n = 4
Ukuran dari pointer
yang menunjuk ke double PI = 4
Ukuran dari
pointer yang menunjuk ke char ch = 4
Variabel-variabel
yang digunakan: 60, 3.14159 dan M
|
Keluaran menunjukkan bahwa ukuran dari memori yang dialokasikan untuk
sebuah pointer adalah 4 byte tanpa memandang fakta bahwa variabel yang ditunjuk
adalah integer, double, atau karakter. Program 2.4 berikut mengilustrasikan
bahwa aksi dari operator dereferensi dan aksi dari operator alamat (&)
adalah berlawanan satu sama lain.
Program 2.4 Mengilustrasikan operator dereferensi(*) dan
operator alamat (&)
|
|
|
#include <iostream>
using namespace std;
main()
{
int
n = 60;
int*
ptrn, *ptrm ; //deklarasi dari dua
piointer ke int
ptrn = &n;
ptrm = ptrn; //menugaskan pointer
cout<<"n =
"<<n<<"\t&n = "<<&n<<"\t
*&n = "<<*&n<<endl;
cout<<"ptrn =
"<<ptrn<<" "<<"ptrm =
"<<ptrm<<endl;
cout<<"Nilai yang ditunjuk oleh
ptrn = "<<*ptrn<<"\n" ;
// *ptrn adalah nilai yang ditunjuk oleh
pointer ptrn
cout<<"Nilai yang ditunjuk oleh
ptrm = " <<*ptrm<<endl;
cout<<"Alamat dari ptrn =
"<<&ptrn<<endl;
double
PI = 3.141592;
double
*pPI; //deklarasi dari
pointer untuk PI
pPI = &PI;
cout<<"PI="<<PI<<",\t
&PI = "<<&PI<<"\n";
cout<<"*&PI =
"<<*&PI<< " ,\t *pPI =
"<<*pPI<<"\n";
return
0;
}
|
KELUARAN
|
|
n = 60 &n = 0018FF44 *&n = 60
ptrn = 0018FF44
ptrm = 0018FF44
Nilai yang
ditunjuk oleh ptrn = 60
Nilai yang
ditunjuk oleh ptrm = 60
Alamat dari
ptrn = 0018FF40
PI=3.14159, &PI = 0018FF34
*&PI =
3.14159 , *pPI = 3.14159
|
Dari keluaran perogram, dapat dilihat bahwa n adalah sebuah integer dengan
nilai 60. Alamat dari n adalah 0018FF44. Nilai dari ptrn, yang merupakan pointer yang menunjuk ke n, juga adalah
0018FF44. Nilai dari ptrn ditugaskan kepada ptrm untuk menciptakan pointer lain
yang menunjuk ke n. Alamat dari ptrn
dapat pula ditentukan dengan menggunakan operator &. Jadi, alamat dari ptrn
adalah 0018FF40, yang jauhnya 4 byte dari 0018FF44. Nilai dari variabel n dapat
ditentukan menggunakan operator dereferensi (*). Blok-blok memori yang
dialokasikan untuk penyimpanan nilai n dan pointernya diilustrasikan pada
Gambar 2.3a.
GAMBAR 2.3a Sebuah integer dan pointernya di dalam
memori
GAMBAR 2.3b Dua pointer yang menunjuk nilai yang
sama
Bagian kedua pada keluaran program terkait dengan suatu nilai double PI =
3.14159. Pointer untuk PI diberi nama dengan pPi. Alamat dari PI adalah 0018FF34. Nilai dari PI dapat ditentukan
dengan memanggil PI atau dengan *&PI
atau dengan *pPI. Penggunaan
operator dereferensi (*) diilustrasikan pada Gambar 2.3b.
2.3 Memproses
Data Menggunakan Pointer
Pointer dapat dipakai menggantikan variabel yang ditunjuknya. Anda telah
melihat pada program sebelumnya bahwa n dan *ptrn memiliki nilai yang sama. Sekarang, jika ada perubahan pada
nilai dari *ptrn, maka n juga
berubah.
Program berikut menghitung keliling dan luas dari sebuah lingkaran dengan
diameter D. Di sini, Anda akan menggunakan pointer-pointer yang menunjuk D dan
PI, menggantikan penggunaan D dan PI. Nilai dari PI diberikan pada program
sedangkan nilai diameter dimasukkan oleh user.
Program 2.5 Mengilustrasikan aplikasi dari pointer dalam
komputasi
|
|
|
#include <iostream>
using namespace std;
int main()
{
int
D, *ptrD = &D ; //deklarasi D
dan pointer yang menunjuk ke D
double
PI= 3.14159;
double*
ptrPI = &PI; //pointer ke PI
cout<<"Tuliskan diameter
lingkaran: ";
cin>>*ptrD;
cout<<"Diameter =
"<<*ptrD <<endl;
double
keliling = *ptrD * *ptrPI; //
= PI*D
double
luas = *ptrPI* *ptrD **ptrD/4; // = PI*D
*D /4
cout<<"Keliling = "
<<keliling<<endl;
cout<<"Luas lingkaran = "
<<luas<<endl;
return
0;
}
|
KELUARAN
|
|
n = 60 &n = 0018FF44 *&n = 60
ptrn = 0018FF44
ptrm = 0018FF44
Nilai yang
ditunjuk oleh ptrn = 60
Nilai yang
ditunjuk oleh ptrm = 60
Alamat dari
ptrn = 0018FF40
PI=3.14159, &PI = 0018FF34
*&PI =
3.14159 , *pPI = 3.14159
|
2.4 Pointer
(yang menunjuk) ke Pointer
Sama seperti ketika Anda memiliki pointer yang menunjuk ke suatu variabel,
Anda juga bisa mendefinisikan pointer yang menunjuk ke pointer untuk menjejak
alamat pointer yang menunjuk ke variabel. Pada program berikut, n adalah sebuah
variabel integer dengan nilai 57, ptrn adalan nama dari pointer yang menunjuk
ke n dan pptrn adalah nama dari
pointer yang menunjuk ke ptrn.
Pointer ptrn yang menunjuk ke n dan
pointer pptrn yang menunjuk ke
pointer ptrn dideklarasikan dan
diinisialisasi berikut.
int* ptrn
= &n ; //ptrn adalah
pointer yang menunjuk ke n
int**
pptrn = & ptrn ; //pptrn adalah
pointer yang menunjuk ke ptrn
Perhatikan bahwa keduanya, pointer maupun pointer ke pointer, bertipe int
karena n adalah integer. Perhatikan pula bahwa untuk mendapatkan nilai dari
variabel, Anda menggunakan satu operattor dereferensi (*) untuk pointer
sedangkan untuk mendapatkan nilai dari variabel dari pointer (yang menunjuk) ke
pointer, Anda perlu menggunakan dua operator dereferensi (**). Tetapi tidak ada
perubahan pada penerapan atas operator alamat &. Perhatikan bahwa Anda
tidak bisa menggunakan &&n karena & memerlukan suatu nilai kiri (l-value) sedangkan &n adalah suatu
nilai kanan (r-value). Objek yang
ditempatkan di sisi kiri dari operator penugasan (=) adalah nilai kiri dan
objek yang ditempatkan di sisi kanan dari operator penugasan (=) adalah nilai
kanan.
Program 2.6 Mengilustrasikan aplikasi dari pointer (menunjuk)
ke pointer
|
|
|
#include <iostream>
using namespace std;
int main()
{
int
n = 57 ;
int*
ptrn = &n; //pointer ke n
cout<<"n =
"<<n<<", Alamat dari n = "
<<&n<<endl;
cout<<"ptrn = "<<
ptrn<<endl;
cout<<"Alamat dari ptrn =
"<<&ptrn<<endl;
int**
pptrn = &ptrn; //pointer ke pointer ke n
cout<<"pptrn =
"<<pptrn<<endl;
int***
ppptrn = &pptrn; //pointer ke pointer ke pointer ke n
cout<<"Alamat dari pptrn =
"<<&pptrn<<endl;
cout<<"ppptrn =
"<<ppptrn<<"\n";
cout<<"*ptrn =
"<<*ptrn<<endl;
cout<<"*pptrn =
"<<*pptrn<<endl;
cout<<"**pptrn =
"<<**pptrn<<endl;
cout<<"***ppptrn =
"<<***ppptrn<<endl;
return
0;
}
|
KELUARAN
|
|
n = 57, Alamat dari n = 0012FF7C
ptrn = 0012FF7C
Alamat dari ptrn = 0012FF78
pptrn = 0012FF78
Alamat dari pptrn = 0012FF74
ppptrn = 0012FF74
*ptrn = 57
*pptrn = 0012FF7C
**pptrn = 57
***ppptrn = 57
|
Keluaran dari program tersebut diilustrasikan pada Gambar 2.4.
GAMBAR 2.4 Nilai-nilai yang dituliskan di dalam
blok-blok memori adalah nilai-nilai yang disimpan di dalam blok-blok memori.
Alamat dari tiap blok dituliskan di bawah blok.
Pada deklarasi atas pointer ke float dan ke double, kedua tipe tidak bisa
dicampur seperti diilustrasikan berikut.
float m ; //variabel bertipe float
float* ptrm =
& m; //pointer ke float,
jangan gunakan double.
float** kptrm
= & ptrm; //pointer ke pointer, bertipe
float
double n ; //variabel double
double* ptrn =
&n; //pointer ke double, jangan
gunakan float.
double** kptrn
= &ptrn //pointer ke pointer ke
double
POINTER KONSTAN
Pemodifikasi const dapat pula digunakan pada pointer. Namun, deklarasi seharusnya
dilakukan dengan hati-hati, seperti berikut.
const int*
ptr ; //di
sini, ptr adalah sebuah ptr tak-konstan yang
menunjuk ke suatu int konstan
int* const
ptr ; //di sini, ptr adalah
sebuah pointer konstan yang
menunjuk ke
suatu int tak-konstan
const int* const
ptr ; //di
sini, ptr adalah sebuah pointer konstan yang menunjuk
ke suatu int konstan
2.5 Pointer dan
Array
Ketika Anda mendeklarasikan suatu array, pengenalnya (nama array) adalah
sebuah pointer const yang menunjuk
ke elemen pertama dari array. Pointer ke array tersebut juga membawa alamat
dari elemen pertama array. Jadi, pointer ke sebuah array memiliki nilai sama
dengan nama array. Perbedaannya adalah bahwa nama array adalah sebuah pointer const, yang tidak bisa diinkremen atau
diubah sedangkan pointer yang menunjuk ke array yang membawa alamat dari elemen
pertama array dapat diinkremen. Jika pointer yang menunjuk ke array diinkremen
sebesar 1, maka pointer itu akan menunjuk ke elemen berikutnya dari array.
Jadi, nilai dari pointer akan bertambah sebesar jumlah byte yang dialokasikan
kepada satu elemen array. Deklarasi atas sebuah pointer yang menunjuk ke suatu
array diilustrasikan berikut.
int A[]
= {12, 25, 36, 50}; //A
adalah nama array
int
*ptrA ;
ptrA = A ; //Perhatikan bahwa tidak
ada operator & digunakan
Definisi tersebut dapat pula dituliskan berikut.
int
*ptrA = A;
dan juga dituliskan sebagai,
int* ptrA =
&A[0];
Hal itu karena alamat dari A[0] sama dengan nilai dari A. Elemen-elemen
array A[0], A[1], A[2], dan A[3] yang memiliki nilai-nilai berturut-turut 12,
25, 36, dan 50 dapat diperoleh dari pointer-pointer seperti diilustrasikan
berikut.
A[0] = *ptrA;
A[1] = *(ptrA+1);
A[2] = *(ptrA+2);
A[3] = *(ptrA+3);
Diskusi tersebut menunjukkan bahwa indeks array dan offset pointer adalah
sama. Jika Anda memanggil array A tanpa indeks, maka yang dihasilkan adalah
alamat dari elemen pertama array. A + 1
menghasilkan alamat dari elemen kedua array, A + 2 menghasilkan alamat dari elemen ketiga array, dan seterusnya.
Oleh karena itu, Anda juga dapat memperoleh nilai-nilai yang disimpan pada
alamat-alamat tersebut menggunakan operator dereferensi (*). Jadi, untuk array
yang dideklarasikan tersebut, Anda bisa mendapatkan nilai dari tiap elemen
array sebagai berikut.
*A = 12
*(A+1) = 25
*(A+2) = 36
*(A+3) = 50
Perhatikan bahwa ekspresi *A++ tidak legal karena A adalah suatu pointer
konstan yang menunjuk ke array dan sebuah konstanta tidak bisa diinkremen. Perhatikan
pula bahwa indeks array sama dengan offset pointer untuk menjelajahi
elemen-elemen array.
Program 2.7 Mengilustrasikan deklarasi atas pointer ke
array
|
|
|
#include <iostream>
using namespace std;
int main()
{
int
A[] = {80, 40, 20, 10}; //A adalah
sebuah array integer
int
*ptrA = A; //ptrA adalah pointer ke array A. Perhatikan bahwa A tidak
digunakan
cout<<"*ptrA =
"<<*ptrA<<" , \tptrA = "<<ptrA<<endl;
cout<<"*(ptrA+1) =
"<<*(ptrA+1)<<" ,\tptrA+1 =
"<<ptrA+1<<endl;
cout<<"*(ptrA+2) =
"<<*(ptrA+2)<<" , \tptrA + 2 =
"<<ptrA+2<<endl;
cout<<"*(ptrA+3) =
"<<*(ptrA+3)<<" , \tptrA+3=
"<<ptrA+3<<"\n\n";
cout<<"A = "
<<A<<endl;
cout<<ptrA[0]<<"\t"<<ptrA[1]<<"\t"<<ptrA[2]<<"\t"<<ptrA[3]<<endl;
cout<<*(A+0)<<"\t"<<*(A+1)<<"\t"<<*(A+2)<<"\t"<<*(A+3)<<endl;
//ini akan menampilkan nilai dari tiap
elemen array
return
0;
}
|
KELUARAN
|
|
*ptrA = 80 , ptrA = 0018FF38
*(ptrA+1) = 40 , ptrA+1 = 0018FF3C
*(ptrA+2) = 20 , ptrA + 2 = 0018FF40
*(ptrA+3) = 10 , ptrA+3= 0018FF44
A = 0018FF38
80 40
20 10
80 40
20 10
|
Dari keluaran program, Anda dapat melihat bahwa nilai dari A sama dengan
nilai dari pointer ptrA yang
menunjuk ke array. Keduanya menghasilkan alamat dari elemen pertama array,
yaitu A = ptrA = 0018FF38.
Sekarang ptrA + 1 memiliki
nilai 0018FF3C yang jaraknya 4 byte dari alamat dari elemen pertama array dan
bahwa pada alamat itu nilai yang disimpan adalah *(ptrA + 1) = 40; atau *(A +
1) = 40, yang merupakan elemen kedua array. Oleh karena itu, ketika sebuah
pointer yang menunjuk ke array diinkremen sebesar 1, pointer itu akan menunjuk
ke elemen berikutnya di dalam array. Nilainya, pada dasarnya, diinkremen
sebesar jumlah byte yang dialokasikan kepada satu elemen array. Sama halnya, ptrA + 2 adalah pointer yang menunjuk
ke elemen ketiga, ptrA + 3 adalah
pointer yang menunjuk ke elemen keempat array. Program berikut mengilustrasikan
penjelajahan array menggunakan pointer.
Program 2.8 Mengilustrasikan penjelajahan array
menggunakan pointer
|
|
|
#include <iostream>
using namespace std;
int main()
{
int
kim[] = {50, 86, 90, 12};
int*
pkim = kim; //mendefinisikan pointer ke array kim
for
(int i=0 ;i<4; i++) //loop for
untuk menampilkan isi array
cout<<"kim["<<i<<"] =
"<<*(pkim +i)<<", ";
//*(pkim +i) adalah nilai dari elemen
kim[i] dari array
return
0;
}
|
KELUARAN
|
|
kim[0] = 50, kim[1] = 86, kim[2] =
90, kim[3] = 12,
|
Pada kasus array, penginkremenan pointer sebesar satu, pada dasarnya,
menambah nilai dari pointer sebesar ukuran byte dari satu elemen array. Jadi,
jika pkim menunjuk ke elemen pertama
dari array, maka pkim + 1 akan
menunjuk ke elemen kedua array. Pada program berikut, elemen-elemen array akan
dikenai operasi-operasi aritmatika dengan bantuan array.
Program 2.9 Mengilustrasikan pemanipulasian elemen-elemen
array dengan pointer-pointer
|
|
|
#include <iostream>
using namespace std;
int main()
{
int
kim[] = {6,8,5,4} ; //array dengan empat
elemen
int*
pkim = kim; //deklarasi
pointer
for
(int i=0; i<4; i++)
cout<<"kim2["<<i<<"] =
"<<*(pkim +i)**(pkim +i)<<", ";
//menciptakan array kim2 dari
elemen-elemen array kim
cout<<"\n";
for(int j= 0; j<4; j++) //menciptakan array kim3
cout<<"kim3["<<j<<"]= "<<*(pkim+j)**(pkim
+j) - *(pkim+j)<<", ";
cout<<"\n";
return
0;
}
|
KELUARAN
|
|
kim2[0] = 36, kim2[1] = 64, kim2[2] =
25, kim2[3] = 16,
kim3[0]= 30, kim3[1]= 56, kim3[2]=
20, kim3[3]= 12,
|
2.6 Array yang
Memuat Pointer-Pointer (menunjuk) ke Array-Array
Pada program berikut, sebuah array yang memuat pointer-pointer int *pAB[2] dideklarasikan untuk dua
array. Elemen pertama adalah pointer pAB[0]
yang menunjuk ke array A dengan empat elemen 80, 70, 60, dan 50, dan elemen
kedua adalah pointer pAB[1] yang menunjuk
ke array B dengan elemen-elemen 10, 20, 30, dan 40. Program berikut
mengilustrasikan bagaimana menampilkan elemen-elemen dari array A dan array B.
Program 2.10 Mengilustrasikan sebuah array yang memuat
pointer-pointer ke array-array
|
|
|
#include <iostream>
using namespace std;
int main()
{
int
A[] = {80, 70, 60, 50} ; //array A
int
B[] = {10, 20, 30, 40}; //array B
int*
pAB[] = {A, B} ;
//Array yang memuat pointer-pointer yang
diinisialisasi dengan
//nama array A dan B
cout<<"Alamat dari A =
"<<A<<endl;
cout<<"Alamat dari B =
"<<B<<"\n\n";
cout<<"Alamat dari elemen
pertama dari pAB[0] = "<<pAB<<endl;
cout<<"Alamat dari elemen kedua
dari pAB[1] = "<<pAB +1<<endl;
cout<<"*pAB =
"<<*pAB <<",\t**pAB = "<<** pAB
<<"\n\n";
// Here *pAB = A and **pAB = A[0], see the
output below.
cout<<"A[0] = *(*pAB) =
"<<* (* pAB)<<endl;
cout<<"A[1] = *(*pAB+1)
="<<*(*pAB+1)<<endl;
cout<<"A[2] = *(*pAB+2) =
"<<*(*pAB +2)<<endl;
cout<<"A[3] = *(*pAB+3) =
"<<*(*pAB +3)<<endl<<endl;
cout<<"*(pAB+1)= "
<<*(pAB+1) <<"\t **(pAB+1) = "
<<**(pAB+1)<< endl;
//di sini, *(pAB+1) = B dan **(pAB +1) =
B[0], lihat keluaran
cout<<"B[0]= *(*(pAB+1)) =
"<<*(*(pAB+1)+0)<<endl;
cout<<"B[1] = *(*(pAB+1)+1) =
"<<*(*(pAB+1)+1)<<endl;
cout<<"B[2]= *(*(pAB+1)+2) =
"<<*(*(pAB+1)+2)<<endl;
cout<<"B[3] = *(*(pAB+1)+2)
="<<*(*(pAB+1)+3 )<<endl;
return
0;
}
|
KELUARAN
|
|
Alamat dari A = 0018FF38
Alamat dari B = 0018FF28
Alamat dari elemen pertama dari
pAB[0] = 0018FF20
Alamat dari elemen kedua dari pAB[1]
= 0018FF24
*pAB = 0018FF38, **pAB = 80
A[0] = *(*pAB) = 80
A[1] = *(*pAB+1) =70
A[2] = *(*pAB+2) = 60
A[3] = *(*pAB+3) = 50
*(pAB+1)= 0018FF28 **(pAB+1) = 10
B[0]= *(*(pAB+1)) = 10
B[1] = *(*(pAB+1)+1) = 20
B[2]= *(*(pAB+1)+2) = 30
B[3] = *(*(pAB+1)+2) =40
|
Pada kode tersebut, Anda memberitahu bahwa inisialisasi dari array pointer
dilakukan dengan menggunakan nama-nama array karena merupakan pointer-pointer
konstan ke array-array. Pada program berikut, Anda memiliki tiga array dan
mendeklarasikan sebuah array yang memuat pointer-pointer yang menunjuk ke
ketiga array tersebut. Inisialisasi dari array pointer itu dilakukan
menggunakan nama-nama array.
Program 2.11 Mengilustrasikan contoh lain
dari sebuah
array yang memuat pointer-pointer ke array-array
|
|
|
#include <iostream>
using namespace std;
int main()
{
int
Satu[] = {6, 8, 5, 4} ; //array
dengan 4 elemen
int
Dua[] = {2, 3, 7}; //array
dengan 3 elemen
int
Tiga[] = {10, 11, 12, 13,14 }; //array
dengan 5 elemen
int*
pKBS[] = {Satu , Dua, Tiga};
//array pointer, inisialisasi dilakukan
menggunakan nama-nama array
cout<<"Satu :
"<<**pKBS<<"\t"<<*(*(pKBS)+1)
<<"\t"<<*(*(pKBS)+2)<<"\t"
<<*(*(pKBS)+3)<<endl;
//mendapatkan elemen-elemen dari array Satu
cout<<"Dua :
"<<*(*(pKBS+1))<<"\t"<<*(*(pKBS+1)+1)<<"\t"<<
*(*(pKBS+1)+2)
<<endl; //mendapatkan
elemen-elemen dari array Dua
cout<<"Tiga : "
<<*(*(pKBS+2))<<"\t"
<<*(*(pKBS+2)+1)<<"\t"
<<*(*(pKBS+2)+2)<<"\t"<<*(*(pKBS+2)+3)<<"\t"<<*(*(
pKBS+2)+4)<<endl;
//mendapatkan elemen-elemen dari array
return
0 ;
}
|
KELUARAN
|
|
Satu : 6 8 5
4
Dua : 2 3 7
Tiga : 10 11
12 13 14
|
2.7 Pointer ke
Array Multi-Dimensi
POINTER KE ARRAY DUA DIMENSI
Program 2.11 pada dasarnya adalah sebuah contoh dari array dua-dimensi,
karena, sebuah array dengan elemen-elemen berupa array satu dimensi merupakan
sebuah array dua dimensi. Pada deklarasi atas pointer ke array dua dimensi,
Anda juga menugaskan alamat array menggunakan nama array yaitu alamat dari
elemen pertama array. Deklarasi tersebut dilakukan sebagai berikut.
int
A[n][m]; //A adalah
sebuah array dua dimensi
int
(*pA)[m] = A ; //pointer
ke array dua dimensi
Sebuah elemen dari array dua dimensi dengan indeks i dan j dapat diakses
dengan berikut.
A[i][j]
Pada notasi pointer, elemen tersebut dapat diakses dengan ekspresi
berikut.
*(*(A+ i) + j)
atau dengan menggunakan pointer pA
berikut
*(*(pA +i)+j)
Program berikut mengilustrasikan deklarasi dan keluaran dari sebuah array
dua dimensi.
Program 2.12 Mengilustrasikan pointer ke
array dua dimensi
|
|
|
#include <iostream>
using namespace std;
int main()
{
int
KBS[3][4] = {6,8,5,4, 2,3,7,9, 10,11,12,13};
int(*pKBS)[4]
= KBS ; //deklarasi dari pointer ke KBS
cout<<**pKBS<<"\t"<<*(*(pKBS)+1)<<"\t"<<*(*(pKBS)+2)<<"\t"
<<*(*(pKBS)+3)<<endl;
cout<<*(*(pKBS+1))<<"\t"<<*(*(pKBS+1)+1)<<"\t"<<*(*(pKBS+1)+2)<<"\t"
<< *(*(pKBS+1)+3) <<endl;
cout<<*(*(pKBS+2))<<"\t"<<*(*(pKBS+2)+1)<<"\t"<<*(*(pKBS+2)+2)
<<"\t"<<*(*(
pKBS+2)+3)<<endl;
return
0;
}
|
KELUARAN
|
|
6 8
5 4
2 3
7 9
10 11
12 13
|
Dari keluaran program, Anda dapat melihat bahwa A[i][j] dan pada notasi pointer *(*(pA+i)+j) adalah dua ekspresi yang ekivalen. Jadi, Anda bisa
juga menggunakan ekspresi *(*(pA+i)+j)
untuk menjelajah sebuah array dua dimensi atau matriks.
DEKLARASI POINTER KE ARRAY TIGA DIMENSI
Array tiga dimensi adalah sebuah array yang memuat matriks-matriks.
Dimisalkan bahwa A adalah sebuah array tiga dimensi. Deklarasi pointer dan
inisialisasinya dilakukan seperti berikut.
int
A[2][3][4];
int
(*pA)[3][4] = A; //pointer
ke array A
Di sini, (*pA)[3][4] adalah
pointer yang menunjuk ke array A[2][3][4].
Sebuah elemen array dengan indeks i, j, dan k dapat diakses dengan ekspresi
berikut.
A[i][j][k]
Dan pada notasi pointer, sebuah elemen dengan indeks i, j, dan k dapat
diakses dengan ekspresi berikut.
*(*(*(A +i) + j) + k)
Pada program berikut, sebuah array tiga dimensi dideklarsikan. Untuk
menampilkan isi dari array tersebut, Anda menggunakan notasi pointer sebagai
sebuah array yang memuat dua matriks.
Program 2.13 Mengilustrasikan pointer ke
array tiga dimensi
|
|
|
#include <iostream>
using namespace std;
int main()
{
int
KBS[2][3][4] = {6,8,5,4, 2,3,7,9, 1,2,3,4, 21,22,23,24, 31,32,33,34,
41, 42, 43, 44} ;
//sebuah array tiga dimensi
int(*
pKBS )[3][4] = KBS; //deklarasi pointer
for
(int i = 0; i<2; i++)
{
for
(int j =0; j <3; j++)
{
for
(int k =0; k<4; k++)
cout<<*(*(*(pKBS +i) + j)
+k)<<" ";
cout<<"\n";
}
cout<<"\n";
}
return
0;
}
|
KELUARAN
|
|
6 8 5 4
2 3 7 9
1 2 3 4
21 22 23 24
31 32 33 34
41 42 43 44
|
2.8 Pointer ke
Fungsi
Pada bagian sebelumnya, Anda telah melihat bahwa nama array memuat nilai
dari alamat dari elemen pertama array dan merupakan sebuah pointer konstan yang
menunjuk ke array. Sama halnya, nama dari sebuah fungsi juga memuat alamat dari
fungsi dan merupakan sebuah pointer yang menunjuk ke fungsi. Oleh karena itu,
Anda dapat mendeklarasikan sebuah pointer yang menunjuk ke suatu fungsi dan
menginisialisasinya dengan nama fungsi. Pointer yang menunjuk ke suatu fungsi
dapat dideklarasikan sebagai berikut.
tipe
(*pengenal_untuk_pointer)(tipe_parameter_fungsi);
Di sini, tipe mengacu pada tipe
data yang dihasilkan oleh fungsi, pada kurung pertama terdapat operator
indireksi yang diikuti oleh nama pointer. Kurung kedua memuat tipe data dari
tiap parameter fungsi. Dimisalkan bahwa Fptr
adalah nama pointer yang menunjuk ke sebuah fungsi Fung dengan tipe int dan
yang memerlukan dua parameter integer, yaitu int Fung(int, int). Pointer yang menunjuk ke fungsi ini
dideklarasikan sebagai berikut.
int
(*Fptr) (int, int);
Deklarasi tersebut pada dasarnya diperuntukkan bagi sembarang fungsi yang
memiliki nilai balik bertipe int dan
memiliki dua parameter int.
Dimisalkan bahwa int Fung1(int, int)
dan int Fung2(int, int) merupakan
dua fungsi yang memenuhi kriteria di atas. Deklarasi dari pointer tersebut
dapat diterapkan kepada kedua fungsi ini. Jadi, jika Anda menugaskan nilai
berikut kepada Fptr,
Fptr = Fung1; //Fptr menunjuk ke Fung1
Pointer FPtr menunjuk ke Fung1. Fungsi Fung1 dapat dipanggil menggunakan operator dereferensi berikut.
int a , b;
(*Fptr)(a, b); //memanggil fungsi
Pada dasarnya, operator dereferensi tidak diperlukan dan fungsi dapat
dipanggil dengan berikut.
Fptr(a, b);
Sekarang, Anda dapat pula menginisialisasi FPtr dengan alamat dari Fung2.
Fptr = Fung2; //pointer FPtr sekarang
menunjuk ke Fung2
Dengan definisi tersebut, pointer Fptr
sekarang menunjuk ke Fung2. Fungsi Fung2 dapat dipanggil dengan ekspresi (*Fptr)(i, d) atau dengan Fptr(i, d) dimana i dan d adalah
integer. Ini memberikan fasilitas kepada user untuk memilih salah satu fungsi
yang disediakan di dalam program yang sesuai dengan deklarasi pointer.
Pada deklarasi tersebut, *Fptr
diapit di dalam kurung karena, kalau tidak, hanya akan ada satu kurung yang
mengapit parameter, dan yang memiliki keutamaan lebih keutamaan daripada
operator *. Jadi, ekspresi seperti int
*Fptr(int, int) berarti bahwa fungsi Fptr
memerlukan dua argumen int dan
menghasilkan sebuah pointer yang menunjuk ke suatu integer. Oleh karena itu,
adalah diperlukan untuk mengapit *Fptr
di dalam kurung. Program berikut mengilustrasikan penggunaan dari pointer yang
menunjuk ke fungsi. User dapat memilih salah satu dari keempat fungsi, dan
pilihan itu difasilitasi oleh statemen switch.
Program 2.14 Mengilustrasikan pointer ke
fungsi
|
|
|
#include <iostream>
using namespace std;
int F1(int n){return n;} //menghasilkan
argumen
int F2(int n){return n*n;} //menghasilkan
kuadrat dari argumen
int F3(int n){return n*n*n;} //menghasilkan pangkat tiga dari
argumen
int F4(int n){return n*n*n*n;} //menghasilkan
pangkat empat dari argumen
int main()
{
int
m;
int
(*Fptr)(int m); //pointer ke fungsi-fungsi tersebut
cout<<"Tuliskan sebuah integer:
";
cin>>m ;
int
pilihanUser ; //user memilih fungsi
cout<<"Berikan pilihan Anda
antara 1 sampai 4: ";
cin>>pilihanUser;
switch
(pilihanUser)
{
case
1:
Fptr = F1 ; //memilih fungsi F1
cout<<m<<"
dipangkatkan 1 = "<<F1(m)<<endl ;
break;
case
2:
Fptr = F2 ; //memilih fungsi F2
cout<<m<<"
dipangkatkan 2 = "<<F2(m)<<endl;
break;
case
3:
Fptr = F3 ; //memilih fungsi F3
cout<<m<<"
dipangkatkan 3 = "<< F3(m)<<endl;
break;
case
4:
Fptr = F4 ; //memilih fungsi F4
cout<<m<<"
dipangkatkan 4 = "<< F4(m)<<endl;
break;
default:
cout<<"Berikan pilihan
kedua antara 1 sampai 4"<<endl;
}
return
0;
}
|
KELUARAN
|
|
Tuliskan sebuah integer: 35
Berikan pilihan Anda antara 1 sampai
4: 4
35 dipangkatkan 4 = 1500625
|
2.9 Array yang
Memuat Pointer-Pointer ke Fungsi-Fungsi
Fungsi tidak dapat menjadi elemen array. Namun Anda dapat memiliki sebuah
array yang memuat pointer-pointer yang menunjuk ke fungsi-fungsi yang berbeda.
Fungsi dapat dipanggil di dalam main()
melalui pointer. Pada program berikut, Anda mendekalarasikan array yang memuat
pointer-pointer yang menunjuk ke tiga fungsi yang semuanya bertipe int. Fungsi-fungsi didefinisikan di
luar main(), karens sebuah fungsi
tidak bisa didefinisikan di dalam fungsi lain. Fungsi pertama menghasilkan
argumen, fungsi kedua menghasilkan kuadrat dari argumen, dan fungsi ketiga
menghasilkan pangkat tiga dari argumen.
Program 2.15 Mengilustrasikan array yang
memuat pointer-pointer ke fungsi-fungsi
|
|
|
#include<iostream>
using namespace std;
int fung1(int); //prototipe
fungsi dari fung1
int fung2(int) ; //prototipe fungsi dari fung2
int fung3(int); //prototipe
fungsi dari fung3
int main()
{
int
P;
int
(*F[3])(int)={fung1, fung2,
fung3}; //array yang memuat tiga pointer
//inisialisasi dilakukan menggunakan
nama-nama fungsi
cout<<"Masukkan sebuah nilai:
";
cin>>P;
cout<<"Anda telah memasukkan
nilai: "<<P<<endl;
for(int i=0;i<3;i++) //loop for untuk
memanggil fungsi-fungsi yang berbeda
cout<<"Pangkat
"<<i+1<<" dari nilai "<<P<<" =
"<<(*F[i])(P)<<endl;
return
0;
}
int fung1(int a) //definisi dari fung1
{
return
a;
}
int fung2(int a) //definisi dari fung2
{
return
a*a;
}
int fung3(int a) //definisi dari fung3
{
return
a*a*a;
}
|
KELUARAN
|
|
Masukkan sebuah nilai: 17
Anda telah memasukkan nilai: 17
Pangkat 1 dari nilai 17 = 17
Pangkat 2 dari nilai 17 = 289
Pangkat 3 dari nilai 17 = 4913
|
2.10 Pointer ke
Fungsi Sebagai Parameter dari Fungsi Lain
Nama dari sebuah fungsi memuat alamat dari fungsi itu. Sebuah fungsi dapat
memiliki fungsi lain sebagai salah satu dari parameternya. Jadi, sebuah fungsi
dapat dilewatkan kepada fungsi lain sebagai argumennya menggunakan nama fungsi
atau menggunakan pointer yang memuat alamat dari parameter fungsi tersebut.
Dengan pointer ke fungsi sebagai parameter, user memiliki fasilitas untuk
memilih fungsi-fungsi. Anda bisa mendapatkan lebih dari satu nilai dari suatu
fungsi.
Pada program berikut, sebuah fungsi dengan nama Fungsi diberikan dengan tipe double
yang menghasilkan suatu nilai double.
Pointer ke fungsi-fungsi lain, yaitu double(*)(double,
double, double) merupakan salah satu parameter. Tiga parameter fungsi lain
adalah double, double, double. Pointer
dipakai untuk memanggil dua fungsi, volume dan luas permukaan dari sebuah
prisma kubik.
Program 2.16 Mengilustrasikan pointer ke
fungsi sebagai parameter dari fungsi lain
|
|
|
#include <iostream>
using namespace std;
double Fungsi(double (*)(double, double, double), double, double, double);
//prototipe
dari Fungsi()
double volume(double, double, double); //prototipe dari fungsi volume()
double permukaan(double, double, double); //prototipe dari fungsi permukaan()
int main()
{
cout<<"Luas permukaan dan volume dari bangun kubik dengan sisi-sisi
4.0,5.0,6.0:"<<endl;
cout<<"Luas permukaan =
"<<Fungsi(permukaan, 4.0,5.0,6.0)<<endl;
cout<<"Volume =
"<<Fungsi(volume,4.0,5.0,6.0)<<endl;
return
0;
}
//definisi dari
fungsi Fungsi
double Fungsi(double(*pF)(double k, double m, double n), double p, double q, double r)
{
return
(*pF)(p,q,r);
}
//berikut
adalah definisi dari fungsi permukaan
double permukaan(double k, double m, double n)
{
return
2*(m*k+ n*k+ m*n);
}
// berikut
adalah definisi dari fungsi volume
double volume(double k, double m, double n)
{
return
k*m*n;
}
|
KELUARAN
|
|
Luas permukaan dan volume dari bangun
kubik dengan sisi-sisi 4.0,5.0,6.0:
Luas permukaan = 148
Volume = 120
|
LATIHAN
1.
Apa itu
pointer? Bagaimana ia dideklarasikan untuk sebuah integer?
2. Sebuah variabel
integer x memiliki nilai 50. Tuliskan kode untuk mendeklarasikan variabel itu,
referensinya dengan nama xKu dan
pointer dengan nama ptrx.
3. Tuliskan sebuah
program uji yang mendeklarasikan sebuah variabel float y, yang diinisialisasi dengan 0. Ciptakan sebuah referensi
dengan nama refy. Sekarang ubah y
menjadi 6.454. Carilah nilai dari refy
dan lokasi memorinya.
4. Apakah ukuran
(dalam byte) dari ruang memori yang dialokasikan untuk pointer yang menunjuk ke
a.
sebuah nilai long int
b.
sebuah nilai float
c.
sebuah variabel
karakter
d.
sebuah nilai double
5.
Tuliskan kode
untuk mendeklarasikan pointer yang menunjuk ke
a.
array satu
dimensi
b.
array dua
dimensi
c.
array tiga
dimensi
6.
Bagaimana Anda
mendapatkan nilai dari variabel melalui pointer yang menunjuk ke pointer?
7. Tuliskan sebuah program untuk
mendeklarasikan sebuah variabel int
dan pointernya dan untuk menentukan kuadrat dan pangkat tiga dari variabel itu
menggunakan pointernya.
8.
Bagaimana Anda mendeklarasikan pointer
yang menunjuk ke pointer untuk
a.
variabel int
b.
variabel double
c.
variabel float
9.
Apa yang salah
dengan kode berikut.
a.
int* ptrn = n;
b.
double ptrnPI =
3.14159;
c.
char *ch = A;
10.
Apa perbendaan
antara referensi dan pointer?
11.
Apa yang Anda
pahami dari berikut.
a.
int (*Fungsi)(int, int);
b.
double(*Fungsi[])(int, int, double)
12.
Jelaskan
perbedaan antara dua deklarasi berikut.
a.
int (*A)[6];
b.
int *A[6];
13.
Jelaskan
perbedaan dari deklarasi-deklarasi berikut.
a.
const int* ptr;
b.
int * const ptr;
c.
const int * const ptr;
14.
PA adalah
sebuah pointer yang menunjuk ke array A[10]. Mana sajakah yang benar untuk
mengakses elemen berikutnya dari array?
a.
*PA + 1;
b.
*(PA + 1);
c.
*A++;
15.
Tuliskan sebuah
program untuk mengilustrasikan kegunaan dari pointer untuk menjelajah sebuah
array.
No comments:
Post a Comment