Angel Himonopus Chalistus: pointer

Senin, 17 Oktober 2011

pointer

     A.       Pendahuluan
Adapun hal yang melatarbelakangi dalam penyusunan tulisan ini adalah untuk memahami dan mempelajari dari salah satu materi matakuliah Algoritma dan Struktur Data, yaitu bab Pointer. Hal ini mengingat bahwa pointer adalah salah satu bab yang dirasa cukup berat dan menjadi dasar untuk bab-bab selanjutnya dalam perkuliahan Algoritma dan Struktur Data yang selanjutnya. Karena dengan pemahaman yang cukup pada bab Pointer ini, diharapkan dapat mempermudah untuk pemahaman bab selanjutnya yang mengharuskan dalam penggunaan pointer.



B.        Pengertian Pointer
Pointer adalah variabel yang berisi alamat memori sebagai nilainya, berbeda dengan variabel biasa yang berisi nilai tertentu. Memori dapat dianalogikan sebagai suatu kota, dan alamat memori diibaratkan sebagai rumah-rumah. Di dalam suatu kota terdapat rumah-rumah yang memiliki alamat tertentu yang unik (tidak ada yang sama). Demikian juga sistem operasi yang akan mengorganisasikan memori dengan nomor berurutan secara unik. Penentuan letak memori dalam deklarasi variabel dilakukan oleh compiler dan sistem operasi pada saat runtime.
a.   Dasar penggunaan Pointer
Dalam sistem komputer, semua bagian di memory dapat diasosiasikan dengan suatu nilai numerik yang disebut address atau alamat di memory. Dengan demikian, setiap bagian di memory dapat diakses menggunakan alamat.
Dalam bahasa pemrograman Delphi, khususnya pada tingkat yang lebih lanjut, peran pointer sangatlah penting, meskipun di sisi lain dapat menimbulkan malapetaka. Pointer memiliki kekuatan besar dalam membangun struktur data dan dapat dimanfaatkan untuk mengelola memori secara akurat. Di sisi lain, dalam penggunaan pointer, sangat mudah terjadi salah pakai yang bisa menimbulkan error yang sulit dicari penyebabnya, yaitu access violation. Karena peran pointer yang sangat besar dalam menghasilkan program yang efektif, seseorang tidak akan bisa menjadi programmer handal bila tidak memiliki pengetahuan yang baik tentang pointer.
b.   Operator Pointer ada dua, yaitu :
♦ Operator &
 Operator & bersifat unary (hanya memerlukan satu operand saja).
Operator & menghasilkan alamat dari operandnya.
♦ Operator *
 Operator * bersifat unary (hanya memerlukan satu operand saja).
 Operator * menghasilkan nilai yang berada pada sebuah alamat.
``Bentuk umum dari pernyataan variabel pointer adalah : <type> *<nama_variabel>``
Untuk mengetahui alamat dari variabel tersebut, digunakan operator ampersand sign (&). Dan untuk mengakses nilai dari alamat yang disimpan pada variabel digunakan operator asterisk (*) . (1) Contoh sederhana penggunaan pointer menggunakan  bahasa C :


//pinter_pointer1.cpp

#include<stdio.h>

void main()
{
int *pointer,bukanPointer,nilai;

nilai=20;

bukanPointer=nilai;

pointer=&nilai;

printf(“Variabel bukanPointer : %d”,bukanPointer);

printf(“\nVariabel *pointer : %d”,*pointer);

printf(“\nAlamat variabel *pointer : %d”,pointer);

}

Dari perintah di atas akan ditampilkan hasil :

Variabel bukanPointer : 20

Variabel *pointer : 20

Alamat variabel *pointer : 8744
ATAU Untuk mendefinisikan sebuah variabel pointer, kita bisa menggunakan ^ atau bisa menggunakan Pointer. (2). Perhatikan contoh berikut ini :

var p1: ^Integer; // Pointer to integer
    p2: ^Real;    // Pointer to real number
    px: Pointer   // Untyped pointer

Variabel p1 adalah variabel dengan tipe pointer to integer, artinya nilai yang ditunjuk oleh p1 adalah nilai bertipe integer. Variabel p2 adalah pointer to real, artinya nilai yang ditunjuk oleh variabel ini adalah bilangan real. Semetera variabel px adalah untyped pointer, artinya tipe yang ditunjuk oleh variabel pointer ini tidak ditentukan. Variabel bertipe untyped pointer akan kompatibel dengan variabel pointer bertipe apapun. Menggunakan utyped pointer pada umumnya lebih fleksibel tetapi kurang aman.
Mengambil nilai yang ditunjuk oleh sebuah variabel pointer biasanya disebut sebagai dereferencing pointer. Untuk melakukan dereferencing pointer, kita harus menggunakan simbol ^. Bila p adalah pointer, maka p^ adalah nilai yang ditunjuk oleh p. Kita bisa mengisi sebuah pointer dengan alamat variabel lain, atau kita bisa mengalokasikannya dari heap memory. Untuk mengambil alamat dari suatu variabel tertentu, kita dapat menggunakan simbol @. Dengan demikian @a berarti alamat dari variabel a. Ada sebuah nilai konstanta khusus yang disebut dengan nil, yang berarti pointer tindak menunjuk ke manapun. (3). Perhatikan contoh berikut ini :

var
  a: Integer;
  p1, p2, p3: ^Integer;
begin
  p1 := @a;
  p2 := p1;
  p2^ := 100;
  p3 := nil;
end;

Pada langkah pertama, p1 diisi dengan alamat dari a (@a). Jadi setelah langkah pertama tersebut, pointer p1 menunjuk ke variabel a. Langkah kedua p2 diisi dengan nilai p1. Ini berarti p2 menunjuk ke a juga. Langkah ketiga p2^ diisi dengan 100. Artinya alamat di memori yang ditunjuk oleh p2 diisi dengan sebuah nilai interger 100. Setelah perintah ini, nilai a, nilai p1^, maupun p2^ adalah sama, yaitu 100. Langkah keempat, p3 diisi nil sehingga p3 sekarang tidak menunjuk kemana-mana. Perlu dicatat disini bahwa variabel pointer tidak diinisialisasi, sehingga isinya bisa menunjuk ke alamat tertentu yang tidak valid. Perkecualian diberikan kepada variabel pointer yang dimiliki oleh objek, dimana nilainya diinisialisasi dengan nil.


C.      Deklarasi Pointer
Seperti halnya variabel yang lain, variabel pointer juga harus dideklarasikan terlebih dahulu sebelum digunakan. Bentuk Umum : Tipe_data *nama_pointer; Tipe data pointer mendefinisikan tipe dari obyek yang ditunjuk oleh pointer. Secara teknis, tipe apapun dari pointer dapat menunjukkan lokasi (dimanapun) dalam memori. Bahkan operasi pointer dapat dilaksanakan relatif terhadap tipe dasar apapun yang ditunjuk. Contoh, ketika kita mendeklarasikan pointer dengan tipe int*, kompiler akan menganggap alamat yang ditunjuk menyimpan nilai integer - walaupun sebenarnya bukan (sebuah pointer int* selalu menganggap bahwa ia menunjuk ke sebuah obyek bertipe integer, tidak peduli isi sebenarnya). Karenanya, sebelum mendeklarasikan sebuah pointer, pastikan tipenya sesuai dengan tipe obyek yang akan ditunjuk.
Ada beberapa hal yang perlu kita pahami dan perhatikan dalam pendeklarasian variabel pointer :
Kita tidak dapat meng”assign” nilai dalam variabel pointer seperti pada variabel biasa apabila bukan variabel array. Misal :

pointer=nilai ;            // ini bakalan salah lho!!!

bukanPointer=pointer;      // ini juga salah
Kurang dalam menginisialisasikan atau mendeklarasikan pointer

*pointer=nilai ;     // salah karena belum menunjuk ke suatu alamat

Contoh :
int *px;
char *sh;
Contoh Program :
#include “stdio.h”
#include “conio.h”
void main()
{    int x, y;  /* x dan y bertipe int */
int *px;  /* px pointer yang menunjuk objek */
clrscr();
x = 87;
px = &x;  /* px berisi alamat dari x */
y = *px;  /* y berisi nilai yang ditunjuk px */
printf(“Alamat x = %p\n”, &x);
printf(“Isi px       = %p\n”, px);
printf(“Isi x         = %i\n”, x);
printf(“Nilai yang ditunjuk oleh px = %i\n”, *px);
printf(“Nilai  y    = %i\n”, y);
getch();
}




D.       Operasi Pointer
Ada beberapa bagian operasi  dalam operasi pointer yaitu :
a.      Operasi Penugasan
♦ Suatu variable pointer seperti halnya variable yang lain, juga bisa  mengalami operasi penugasan. Nilai dari suatu variable pointer dapat disalin ke variable pointer yang lain.
Contoh Program :
#include “stdio.h”
#include “conio.h”
void main()
{    float *x1, *x2, y;
clrscr();
y = 13.45;
x1 = &y;  /* Alamat dari y disalin ke variabel x1 */
x2 = x1;  /* Isi variabel x1 disalin ke variabel x2 */
printf(“Nilai variabel y = %.2f ada di alamat %p\n”, y, x1);
printf(“Nilai variabel y = %.2f ada di alamat %p\n”, y, x2);
getch();
}

b.      Operasi Aritmatika
♦ Suatu variabel pointer hanya dapat dilakukan operasi aritmatika dengan nilai integer saja. Operasi yang biasa dilakukan adalah operasi penambahan dan pengurangan. Operasi penambahan dengan suatu nilai menunjukkan lokasi data berikutnya (index selanjutnya) dalam memori. Begitu juga operasi pengurangan. Pointer dapat diberikan operator berdasarkan ukuran masing-masing tipe datanya. Hanya 4 operator yang dapat dikenakan pada pointer, yaitu : ++,–,+ dan -. Misalkan saja didefinisikan sebagai berikut :

int *pointer;

pointer++;
Dari contoh sederhana di atas dapat dijelaskan bahwa alamat memori dari variabel pointer akan bertambah 1, misalkan alamat variabel pointer adalah 8774, maka pointer++;, menyebabkan alamat bertambah 1 menjadi 8775.

Contoh Program :
#include “stdio.h”
#include “conio.h”
void main()
{    int nilai[3], *penunjuk;
clrscr();
nilai[0] = 125;
nilai[1] = 345;
nilai[2] = 750;
penunjuk = &nilai[0];
printf(“Nilai %i ada di alamat memori %p\n”, *penunjuk, penunjuk);
printf(“Nilai %i ada di alamat memori %p\n”, *(penunjuk+1), penunjuk+1);
printf(“Nilai %i ada di alamat memori %p\n”, *(penunjuk+2), penunjuk+2);
getch();
}


c.      Operasi Logika
♦ Suatu pointer juga dapat dikenai operasi logika.
^,  Untuk mengakses data yang ditunjuk oleh suatu variabel pointer. Operator ini hanya bekerja untuk typed pointer.
=,  Untuk memeriksa apakah dua variabel pointer menunjuk alamat yang sama atau tidak
<>, Untuk memeriksa apakah dua variabel pointer menunjuk alamat yang berbeda
@, Untuk mengetahui alamat variabel tertentu. Operand dari operator ini adalah variabel apapun, sedangkan hasil dari operator ini adalah pointer. Peran operator ini sama persis dengan function Addr.
Contoh Program :
#include “stdio.h”
#include “conio.h”
void main()
{    int a = 100, b = 200, *pa, *pb;
clrscr();
pa = &a;
pb = &b;
if(pa < pb)
printf(“pa menunjuk ke memori lebih rendah dari pb\n”);
if(pa == pb)
printf(“pa menunjuk ke memori yang sama dengan pb\n”);
if(pa > pb)
printf(“pa menunjuk ke memori lebih tinggi dari pb\n”);
getch();
}

d.      POINTER DAN STRING
Contoh Program 1 :
#include “stdio.h”
#include “conio.h”
char *nama1 = “SPIDERMAN”;
char *nama2 = “GATOTKACA”;
void main()
{    char namax;
clrscr();
puts(“SEMULA :”);
printf(“Saya suka >> %s\n”, nama1);
printf(“Tapi saya juga suka >> %s\n”, nama2);
/* Penukaran string yang ditunjuk oleh pointer nama1 dan nama2 */
printf(“SEKARANG :”);
printf(“Saya suka >> %s\n”, nama1);
printf(“Dan saya juga masih suka >> %s\n”, nama2);
getch();
}
Contoh Program 2 :
#include <stdio.h>
void misteri1(char *);
void main() {
    char string[] = "characters";
    printf("String sebelum proses adalah %s", string);
    misteri1(string);
    printf("String setelah proses adalah %s", string);
}
void misteri1(char *s) {
    while ( *s != '\0' ) {
        if ( *s >= 'a' && *s <= 'z' )
            *s -= 32;
        ++s;
    }
}

e.      POINTER DAN ARRAY
Array dapat diakses dengan pointer.
 Contoh :
int huruf[20], *h;

h=huruf;

Dalam hal ini h akan berisi elemen pertama dari array huruf atau sama artinya dengan h=&huruf[0]; yang juga berarti bahwa h adalah pointer ke integer tunggal. Bentuk penulisan pointer dalam mengakses array bervariasi, untuk jelasnya dapat dilihat contoh berikut

//(pinter_pointer5.cpp) :

#include<stdio.h>

void main()

{

int huruf[5],*h;

h=huruf;*h=10;

h++; *h=20;

h=&huruf[2]; *h=30;

h=huruf + 3; *h=40;

h=huruf; *(h+4)=50;

for(int i=0;i<5;i++)

{

printf(” %d”,h[i]);

}

}

Dalam contoh di atas dapat dilihat bentuk penulisan yang berbeda-beda dalam mengakses elemen array. Contoh di atas akan menghasilkan : 10 20 30 40 50


f.       POINTER MENUNJUK SUATU ARRAY 
Contoh Program :
#include “stdio.h”
#include “conio.h”
void main()
{    static int tgl_lahir[] = { 13,9,1982 };
int *ptgl;
ptgl = tgl_lahir;   /* ptgl berisi alamat array */
printf(“Diakses dengan pointer”);
printf(“Tanggal  = %i\n”, *ptgl);
printf(“Bulan      = %i\n”, *(ptgl + 1));
printf(“Tahun     = %i\n”, *(ptgl + 2));
printf(“\nDiakses dengan array biasa\n”);
printf(“Tanggal = %i\n”, tgl_lahir[0]);
printf(“Bulan     = %i\n”, tgl_lahir[1]);
printf(“Tahun    = %i\n”, tgl_lahir[2]);
getch();
}
g.      MEMBERI NILAI ARRAY DENGAN POINTER
Contoh Program :
#include “stdio.h”
#include “conio.h”
void main()
{    int x[5], *p, k;
clrscr();
p = x;
x[0] = 5;  /* x[0] diisi dengan 5 sehingga x[0] = 5 */
x[1] = x[0];  /* x[1] diisi dengan x[0] sehingga x[1] = 5 */
x[2] = *p + 2;  /* x[2] diisi dengan x[0] + 2 sehingga x[2] = 7 */
x[3] = *(p+1) – 3; /* x[3] diisi dengan x[1]  - 3 sehingga x[3] = 2 */
x[4] = *(x + 2); /* x[4] diisi dengan x[2] sehingga x[4] = 7 */
for(k=0; k<5; k++)
printf(“x[%i] = %i\n”, k, x[k]);
getch();
}

h.      POINTER SEBAGAI PARAMETER
Pointer dapat juga digunakan sebagai parameter fungsi. Pointer dilewatkan ke dalam fungsi melalui nilainya (passing by value). Misalkan seperti fungsi menukar nilai di bawah ini

//pinter_pointer2.cpp

#include<stdio.h>

void tukarNilai(int *j, int *k)

{

int temp;

temp=*j;

*j=*k;

*k=temp;

}

void main()

{

int a=20,b=10;

printf(“nilai a : %d dan nilai b : %d”, a, b);

tukarNilai(&a,&b);

printf(“\nnilai a : %d dan nilai b : %d”, a, b);

}

Di sini dapat dilihat bahwa variable pointer dapat dilewatkan melalui fungsi sebagai parameter. Dalam fungsi tukarNilai hanya dilewatkan alamatnya saja (tukarNilai(&a,&b);) dan di dalam fungsi ini barulah proses pertukaran dimulai. *j dan *k nilainya sama dengan a dan b, kemudian *j dan *k barulah dipertukarkan kedua nilainya.
i.        POINTER VOID

Pointer tipe void adalah pointer tipe khusus, yang dapat menunjuk sembarang tipe data dari nilai integer ke suatu string character. Kelemahannya adalah data yang ditunjuk tidak dapat mengacu secara langsung dan panjangnya tidak tertentu. Oleh karena itu, dibutuhkan type casting untuk mengubah void pointer ke suatu pointer dari suatu concrete data type dimana kita dapat mengacu padanya.

//pinter_pointer3.cpp

#include<iostream.h>

void increase(void *data,int type)

{

switch (type)

{

case sizeof(char): (*((char*)data))++;break;

case sizeof(short): (*((short*)data))++;break;

case sizeof(long): (*((long*)data))++;break;

}

}

void main()

{

char a=5;

short b=9;

long c=12;

increase(&a,sizeof(a));

increase(&b,sizeof(b));

increase(&c,sizeof(c));

cout<<(int)a<<”,”<<b<<”,”<<c;

}

Output : 6,10,13

Kita tidak dapat langsung mengoperasikan pointer dengan tanda asterisk (*) karena setiap data memiliki tipe yang berbeda-beda. Type casting digunakan untuk solusi masalah di atas.

j.       POINTER UNTUK STRUKTUR DATA DINAMIK

Struktur data dinamik adalah struktur data yang dapat bertambah maupun berkurang sesuai dengan kebutuhan di saat program berjalan. Struktur data dinamik dapat mengalokasikan blok-blok memori sesuai dengan yang diinginkan dalam program yang dirangkai (link) dengan menggunakan struktur pointer. Bila blok memori tidak digunakan lagi, maka blok memori tersebut dilepas untuk keperluan yang lain.

//pinter_pointer4.cpp

#include <stdio.h>

#include <stdlib.h>

void main()

{

int *p;

p=(int *) malloc (sizeof(int));

*p=10;

printf(“%d\n”,*p);

free(p);

}

Perintah malloc digunakan untuk mengalokasikan memori dengan jumlah tertentu, dalam hal ini adalah ukuran memori dari integer, yaitu 4 byte. Type casting dilakukan supaya mengubah pointer generic (pointer void) yang dihasilkan oleh malloc menjadi pointer integer. Fungsi free digunakan untuk melepaskan blok memori yang tidak digunakan.

k.     POINTER PERBANDINGAN
Pointer dapat dibandingkan dengan menggunakan operator hubungan, seperti !=, ==, <, dan >.Contoh :

//(pinter_pointer6.cpp)

#include <iostream.h>

int main()

{

int num[10];

int *start, *end;

start = num;

end = &num[9];

while(start != end) {

cout << “Masukkan bilangan sebanyak 9 data : “;

cin >> *start;

start++;

}

return 0;

}

Data yang akan dimasukkan sebanyak 9 buah data dan program tidak akan berhenti apabila belum sampai 9 buah data.


silahkan download versi power pointa di sini 

Tidak ada komentar:

Posting Komentar