Minggu, Juli 19, 2015

Programming in C - Part 14: Pointer dalam bahasa C

Pointer adalah salah satu topik yang paling menarik untuk dibahas. Pointer adalah salah satu fasilitas yang hanya ada di bahasa C dan menjadi ciri dan kekuatan, sekaligus kelemahan dalam bahasa ini. Pointer memberikan fasilitas untuk mengakses secara langsung memory komputer yang merupakan 'isi perut' dari setiap program. Kemampuan ini memberikan keistimewaan yang luar biasa karena dengan mengetahui isi dalam dari sebuah program maka akan sangat mudah untuk melakukan apa saja yang diinginkan. Inilah kekuatan nyata yang dimiliki bahasa C.

Dilain sisi, kemampuan ini justru dapat membahayakan terutama bagi programmer pemula. Kesalahan sedikit saja dalam mengatur akan menyebabkan kesalahan fatal yang kadang sulit dideteksi. Ini yang membuat bahasa C menjadi seperti bahasa yang sulit untuk dipelajari dan sering kali memberikan efek 'jera' bagi mereka yang sudah terbiasa mendapatkan fasilitas 'mudah' dari bahasa tingkat tinggi lain.

Banyak yang mengatakan bahasa C ini seperti mengendarai mobil mewah yang cepat (sehingga anda bisa membuat program hebat yang cepat) namun tanpa rim (sehingga anda mungkin dapat menabrak/merugikan diri sendiri).Saya sendiri cendrung untuk melihat pointer ini sebagai sebuah tantangan yang harus dapat ditaklukkan karena memang ini adalah salah satu syarat yang harus dipenuhi jika anda ingin menjadi programmer kelas wahid. Oleh karenanya saya sangat menganjurkan agar andapun melihat pointer ini dengan cara yang sama, yaitu sebagai tantangan, bukan halangan. Tentu saja anda harus tetap mengenakan 'sabuk pengaman' alias harus tetap hati-hati menggunakan pointer ini.

Jadi apa sebenarnya pointer yang menghebohkan ini ?

Pointer adalah sebuah variabel khusus yang berisi alamat dari variabel lainnya dalam sebuah memori komputer. Jika anda mendeklarasikan sebuah variabel berarti anda sedang mencadangkan sebuah tempat di memori. Ketika anda melakukan inisiasi variabel tersebut, berarti anda mengisi suatu nilai ke dalam memori yang alamatnya ditentukan tersebut. Untuk sekedar menyegarkan ingatan berikut ini adalah contoh deklarasi dan inisiasi variabel integer biasa.

int beratBadan ;
beratBadan= 78 ;

perintah pertama adalah deklarasi variabel bertipe integer, yaitu mencadangkan tempat di memori yang hanya bisa diisi data bertipe integer dan diberi nama beratBadan. Perintah berikutnya adalah mengisi memori yang bernama beratBadan dengan nilai 78. Ini adalah contoh deklarasi dan inisiasi variabel biasa dalam program bahasa C.

Bagaimana dengan pointer? perhatikan contoh berikut ini

int beratBadan = 78 ;
int *contohPointer ;

contohPointer = &beratBadan;


Penjelasan :

baris pertama adalah deklarasi dan inisasi variabel beratBadan dengan nilai 78.
baris kedua adalah deklarasi sebuah pointer dengan nama contohPointer. Perhatikan tanda asterik (*) di depan nama pointer. Itulah tanda bahwa variabel yang dideklarasi adalah pointer. Jadi mulai sekarang anda bisa secara mental membayangkan pointer adalah jenis variabel istimewa sehingga diberi tanda bintang (*)
baris berikutnya adalah mengisi pointer contohPointer dengan ALAMAT    dari variabel yang bernama berat badan. Alamat ini ditandai dengan tanda &. Jadi isi dari pointer tersebut adalah alamat dari variabel berat badan dan bukan angka 78.

Perlu diingat bahwa variabel bintang tidak perlu mencetak isinya, tetapi mengarah pada isi dari alamat variabel yang ada. Jadi meskipun pointer contohPointer tidak berisi 78, tetapi jika diakses dengan cara tertentu maka nilainya adalah 78. Jika anda merasa bingung saat ini jangan takut karena nanti anda akan memahami dengan sendirinya setelah meneruskan membaca artikel ini

Untuk sementara coba anda hapalkan berikut ini :

Setiap variabel memiliki beberapa karakteristik, yaitu :
  1. tipe
  2. nama
  3. alamat
  4. isi/NILAI

Khusus untuk pointer memiliki karakteristik tambahan
  1. tipe
  2. nama
  3. alamat
  4. isi
  5. NILAI

Bedanya adalah bahwa pada variabel biasa isi dan NILAI dapat dianggap sama. Sedangkan pointer membedakan isi dengan NILAI, isi adalah isi memory secara fisik, yaitu (menuju) alamat dari varibel lain, sedangkan NILAI adalah isi dari variabel yang dituju. Lihat ilustrasi di awal tulisan ini.


Perhatikan program berikut ini

/* Menggunakan Pointer dalam C
 * Created by Sastrawan
 *
 * ================================
 */

#include<stdio.h>

int main(int argc, char *argv[])
{

//Pointer

int beratBadan =78 ;
int *contohPointer ;

printf("isi dari variabel beratBadan adalah \t %d \n\n",beratBadan);
printf("=====================================================================\n\n") ;

printf("Perintah : ( contohPointer = &beratBadan )\n");
printf("akan mengarahkan contohPointer ke alamat beratBadan : \n\n");
printf("=====================================================================\n") ;


contohPointer = &beratBadan ;   //cara mengarahkan pointer ke alamat ttt
                                // perhatikan penggunaan tanda &

printf("Alamat dari variabel beratBadan adalah \t %x \n\n", &beratBadan); 
            // hasilnya akan sama dengan contohPointer

// isi dari ptr adalah alamat variabel nilai
printf("isi pointer ( contohPointer ) adalah \t %x \n",  contohPointer); 

// perhatikan penggunaan tanda & untuk mengambil alamat
printf("Alamat pointer ( &contohPointer ) adalah %x \n", &contohPointer);

// perhatikan penggunaan tanda * untuk mengambil NILAI
printf("NILAI  pointer ( *contohPointer ) adalah %d \n", *contohPointer);

return 0;
}

Output dari program di atas adalah sbb:

isi dari variabel beratBadan adalah      78

=====================================================================

Perintah : ( contohPointer = &beratBadan )
akan mengarahkan contohPointer ke alamat beratBadan :

=====================================================================
Alamat dari variabel beratBadan adalah      bfd6dd58

isi pointer ( contohPointer ) adalah      bfd6dd58
Alamat pointer ( &contohPointer ) adalah bfd6dd5c
NILAI  pointer ( *contohPointer ) adalah 78


Alamat sebuah variabel adalah deretan angka (hexadesimal) Setiap variabel pasti akan diberikan alamat secara otomatis dalam bentuk deretan angka tersebut. Perlu diperhatikan bahwa tipe variabel dan tipe pointer harus sama persis.

Pointer dan Array


Pointer akan benar-benar terasa manfaatnya ketika kita akan melakukan manipulasi terhadap array, terutama pada array berukuran sangat besar. Bayangkan sebuah buku yang mempunyai daftar isi. Dengan melihat ke daftar isi kita akan dapat dengan cepat menemukan informasi dalam buku tersebut. Kita tidak perlu membuka lembar demi lembar untuk menemukan apa yang kita cari. Pointer kira kira bekerja dengan cara yang sama. Dengan pointer kita bisa lebih cepat manipulasi data sehingga meningkatkan kecepatan akses program dan meningkatkan efisiensi penggunaan memori (tidak perlu membuat copy dari array yang akan dimanipulasi, cukup dengan menggunakan alamat dari array yang sudah ada).


Pointer yang diarahkan ke sebuah array akan secara otomatis menunjuk ke alamat awal dari array tersebut. Dalam deklarasi tidak diperlukan tanda &. (karena array mengandung banyak alamat yang berurutan). Jadi pengarahan pointer ke array dapat dilakukan langsung sbb :

int namaArray[3] = {1,20,34} ;
int *namaPointer ;


namaPointer = namaArray ;  

cara di atas akan menyebabkan namaPointer akan mengarah ke alamat array pertama. Perhatikan bahwa tanda & tidak digunakan depan nama Array tanpa indeks. Perintah berikut akan memberikan hasil yang identik

namaPointer = &namaArray[0] ;

Teknik di atas memungkinkan kita untuk mengarahkan pointer ke elemen array tertentu ( tidak harus dari awal). Misalkan kita ingin mulai mengakses elemen array ke 3, maka kita bisa mengarahkan pointer langsung dengan memberikan indeks 3 pada namaArray sbb :

namaPointer = &namaArray[3];  

Jika pada saat ini kita mengambil NILAI pada namaPointer, maka kita akan mendapatkan 1. Untuk mendapatkan nilai berikutnya dilakukan dengan penambahan pada alamat pointer yang dituju. Caranya adalah sbb
*namaPointer          // menghasilkan 1
*(namaPointer + 1); // menghasilkan 20
*(namaPointer + 2); // menghasilkan 34

Penambahan 1 pada namaPointer akan secara otomatis dikenali sebagai 1 x besar memory yang dibutuhkan oleh tipe data yang digunakan. misalnya tipe data int membutuhkan 4 bytes, maka sebenarnya yang terjadi adalah penambahan alamat memory saat ini dengan 1 x 4 bytes, sehingga pointer maju 4 bytes berkut. Penambahan dengan 2 akan menyebabkan pointer berpindah sebanyal 2 x 4 bytes = 8 bytes. Jadi perlu dipahami bahwa penambahan pointer BUKAN operasi aritmatika biasa melainkan suatu yang khusus yang dikenali dan diolah langsung pada saat kompilasi program.

Perhatikan contoh berikut ini

/* =======================================
 * Pointer dan Array
 * Created by: Sastrawan
 * Topik : Membuat dan menggunakan array dengan pointer
 * ========================================
 */

 
 #include<stdio.h>

 int main( int argc, char *argv[])
 {
    int deretAngka[5];  //deklarasi array ukuran 5
  
    deretAngka[0] = 10 ;
    deretAngka[1] = 11 ;
    deretAngka[2] = 12 ;
    deretAngka[3] = 13 ;
    deretAngka[4] = 14 ;


       int *point ;             // deklarasi pointer point
     
       point= deretAngka ;      //mengisi pointer point dengan alamat awal deretAngka
                            // untuk pointer yang mengarah ke alamat array maka
                            // tanda & tidak perlu ditulis
     
       // Mencetak isi array
       int panjang = sizeof(deretAngka);        //Menghitung jumlah byte  yang
                                //dibutuhkan untuk arrayIntY.
                                //ingat integer membutuhkan 4 byte
                                //jadi banyak elemen dalam array ini = jumlahmemory/4
     
       printf("Banyaknya memory deretAngka adalah %d Bytes\n", panjang);

       printf("Banyaknya elemen deretAngka adalah %d \n\n", panjang/4);
     
       int i ;
     
       for(i=0; i<(panjang/4) ; i++) {     // pembagian 4 karena tipe int.
        // disini kita mengarahkan pointer ke alamat pertama
        // kemudia disusul ke alamat berikutnya sampai selasai
        // Penambahan pointer dilakukan dengan *(point+i)
      
        printf("pointer %d adalah %d \n",i,*(point+i));
    }

 return 0 ;
 }

Output dari program ini adalah :

Banyaknya memory deretAngka adalah 20 Bytes
Banyaknya elemen deretAngka adalah 5

pointer 0 adalah 10
pointer 1 adalah 11
pointer 2 adalah 12
pointer 3 adalah 13
pointer 4 adalah 14


Array of Pointer


Cara di atas adalah menggunakan 1 pointer untuk mengakses Array. Methode lain yang dapat digunakan adalah membuat pointer untuk setiap elemen array. Artinya bahwa kita dapat memnuat deretan pointer yang masing - masing menunjuk ke satu alamat elemen array. Disini kita bisa membuat Array of Pointer (array yang berisi pointer). Contoh di bawah ini akan menggunakan contoh yang sama dengan contoh sebelumnya tetapi aksesnya menggunakan array of pointer

Untuk mendeklarasikan array of pointer dapat dilakukan dengan cara sbb :

int *deretPoint[5] ;   

Perintah ini akan mendeklarasi array of pointer tipe int  sebanyak 5 buah. Perbedaannya hanya terletak pada pennambahan kurung siku



/* =======================================
 * Array of pointer
 * Created by: Sastrawan
 * Topik : Membuat dan menggunakan array of pointer
 * untuk mengakses Elemen array
 * ========================================
 */

 
 #include<stdio.h>

 int main( int argc, char *argv[])
 {
    int deretAngka[5];  //deklarasi array ukuran 5
  
    deretAngka[0] = 10 ;
    deretAngka[1] = 11 ;
    deretAngka[2] = 12 ;
    deretAngka[3] = 13 ;
    deretAngka[4] = 14 ;
  
  
       int *deretPoint[5] ;     // deklarasi array of pointer
 
     
       // Mencetak isi array
       int panjang = sizeof(deretAngka);        //Menghitung jumlah byte  yang
                                //dibutuhkan untuk arrayIntY.
                                //ingat integer membutuhkan 4 byte
                                //jadi banyak elemen dalam array ini = jumlahmemory/4
     
       printf("Banyaknya memory deretAngka adalah %d Bytes\n", panjang);

       printf("Banyaknya elemen deretAngka adalah %d \n\n", panjang/4);
     
       int i ;
     
       for(i=0; i<(panjang/4) ; i++) {
        deretPoint[i] = &deretAngka[i] ; // mengisi masing pointer dengan alamat array sekarang
        printf("pointer %d adalah %d \n",i,*deretPoint[i]);  //menampilkan isi
    }
     

 return 0 ;
 }


Program ini akan menghasilkan output yang sama


Perbedaan cara kedua dan pertama.

Jika keduanya menghasilkan output yang sama, lantas apa bedanya ?. Pertanyaan ini juga muncul dalam benak saya ketika baru belajar bahasa ini. Dari pengalaman, keduanya memang terkadang dibutuhkan untuk situasi tertentu. Untuk suatu proses yang dilakukan sekali jalan dan berurutan, misalnya perhitungan aritmatika pada elemen array, maka cara pertama kelihatannya lebih efisien karena hanya membuat 1 pointer saja. Akan tetapi jika kita membutuhkan pengolahan secara acak, artinya tidak harus berurutan, maka cara kedua akan lebih menguntungkan. Contoh dari situasi ini adalah ketika anda menjumlahkan komponen beberapa kali dalam sebuah proses. Jika menggunakan cara pertama anda akan harus melakukan looping dari awal lagi, sedangkan pada cara kedua karena pointer sudah diisi pada looping pertama, maka proses selanjutnya hanyalah melakukan analisa data saja.

Array of pointer tipe char dan int


Anda juga dapat mendeklarasi sebuah pointer dan langsung menginisiasinya dengan NILAI tanpa harus membuat nama variabel kedua.Caranya adalah sbb :

char *hari[] = {"Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"};  

Perintah diatas mendeklarasikan dan inisiasi array of pointer yang diberi nama hari dan langsung diisi nilai dengan nama hari. Adapun nama variabel yang mengandung nama-nama hari tersebut tidak di deklarasikan karena komputer akan mendeklarasi secara otomatis dan kita hanya membutuhkan alamatnya, bukan namanya.

Catatan kecil : deklarasi dengan cara ini berjalan mulus untuk tipe char, tetapi memunculkan pesan error pada saat kompilasi ketika menggunakan tipe int. Namun demikian error tersebut tidak mempengaruhi proses kerjanya.

Perhatikan contoh berikut ini

/* =======================================
 * Array of pointer
 * Created by: Sastrawan
 * Topik : Membuat dan menggunakan array of pointer
 * ========================================
 */


 #include<stdio.h>

 int main( int argc, char *argv[])
 {
    char *hari[] = {"Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"};  // Deklarasi & inisiasi array of pointer
  
       int i ;
     
       for(i=0; i<7 ; i++) {
      
        printf("pointer %d adalah %s\n",i,hari[i]);

    }
return 0 ;

 }


Outputnya :
pointer 0 adalah Minggu
pointer 1 adalah Senin
pointer 2 adalah Selasa
pointer 3 adalah Rabu
pointer 4 adalah Kamis
pointer 5 adalah Jumat
pointer 6 adalah Sabtu


Untuk saat ini pembahasan mengenai pointer sudah cukup mendiskusikan basic yang dapat dipergunakan untuk berbagai keperluan. Pembahasan lanjutan mengenai pointer akan dibahas pada tulisan lain.

0 comments:

Posting Komentar

Write your comment here