Object dan Fungsi

Dalam membahas topik ini, bayangkan bahwa class adalah suatu tipe data baru.

Suatu fungsi, dalam C/C++ dapat dituliskan:

tipe_keluaran nama_fungsi( tipe_parameter_1 parameter_1,

tipe_parameter_2 parameter_2,

…...........................................,

tipe_parameter_n parameter_n)

maka, bila kita menggunakan object dapat ditulis:

nama_class nama_fungsi( nama_class_object_1 object_1,

nama_class_object_2 object_2, ….............................................,

nama_class_object_n object_n)

contoh fungsi dengan parameter berupa object:

#include

class Label

{

public:

Label(char *label)

{

lbl = label;

}

~Label()

{}

char *lbl;

int lenLabel;

};

void cetak(Label L)

{

std::cout << L.lbl;

std::cout << '\n';

}

int main()

{

Label iLabel("Hello");

cetak(iLabel);

return 0;

}

Pada contoh diatas, konstruktor class label membutuhkan parameter masukan bertipe char * , sehingga saat instansi, kita juga mendefinisikan parameter ini:

Label iLabel("Hello");

saat pemanggilan fungsi cetak, L dalam parameter cetak adalah reference ke iLabel dalam fungsi main karena dalam fungsi main, cetak dipanggil dengan:

cetak(iLabel);

oleh karena itu, member dari object iLabel dapat diakses pula oleh L, sehingga kita bisa mengakses variable member lbl dengan cara:

L.lbl;

contoh fungsi dengan keluaran berupa object:

#include

#include

class Label

{

public:

Label()

{}

Label(char *label)

{

lbl = label;

lenLabel = strlen(label);

}

~Label()

{}

public:

char *lbl;

int lenLabel;

};

Label cetak1(char *kar)

{

Label lbl(kar);

return lbl;

}

int main()

{

Label lb("Hai Dunia");

lb = cetak1("Hello World");

std::cout << lb.lbl;

std::cout << '\n';

std::cout << "panjang string = ";

std::cout << lb.lenLabel;

std::cout << '\n';

return 0;

}

Bagaimana keluaran program diatas?

Program diatas akan menampilkan:

Hello World

panjang string = 11

Mengapa menjadi begini? Padahal saat instansi, object lb akan mempunyai karakter “Hai Dunia” (sebesar 9 karakter)?

Penjelasannya adalah saat pertama instansi, lb memang mempunyai karakter “Hai Dunia” (sebesar 9 karakter), namun karena kita memanggil fungsi cetak1, dimana dalam fungsi cetak1 keluaran adalah object yang berisi data yang berbeda, maka lb dalam fungsi main juga akan diubah datanya sesuai yang diatur dalam fungsi cetak1().

Istilah - Istilah

Virtual Function

Telah disinggung pada sifat OOP, salah satunya adalah polymorfisme (banyak bentuk). Virtual function adalah fungsi yang dapat didefinisikan ulang oleh keturunannya, walaupun berbeda implementasi, namun parameter fungsi harus sejenis.

Contoh sehari-hari:

Seorang guru bahasa inggris mempunyai anak yang juga seorang guru, namun guru matematika. Maka dapat dikatakan status guru pada sang ayah adalah virtual function, sehingga keturunannya dapat pula menjadi guru walaupun lain bidang.

Contoh dalam C++:

class DASAR

{

public:

DASAR();

~DASAR();

private:

int x;

int y;

void printLabel(char *);

public:

char *label;

virtual void setLabel() //inisalisasi setLabel() sebagai fungsi virtual

{

cout >>“DASAR”;

}

};

class TURUNAN1 : public DASAR

{

public:

TURUNAN1()

~TURUNAN1();

void setLabel()

{

cout <<“TURUNAN1”;

}

};

class TURUNAN2 : public DASAR

{

public:

TURUNAN2()

~TURUNAN2();

void setLabel()

{

cout <<“TURUNAN2”;

}

};

fungsi setLabel() pada class TURUNAN1 dan TURUNAN2 diatas dikatakan sebagai override dari fungsi setLabel() pada class DASAR

bila kita instansi:

DASAR D;

TURUNAN1 T1;

TURUNAN2 T2;

kemudian kita panggil member function setLabel() pada masing-masing class:

D.setLabel();

T1.setLabel();

T2.setLabel();

Apa hasilnya? Keluarannya berbeda untuk masing-masing class. Hal seperti inilah yang dimaksud polymorfisme kemampuan untuk banyak bentuk.

FUNGSI VIRTUAL MURNI (PURE VIRTUAL)

fungsi virtual murni adalah fungsi virtual tanpa implementasi, cara inisialisasi:

virtual fungsi()=0;

untuk apa fungsi ini?

Untuk persiapan agar turunan dapat menggunakannya (override) dan mengimplementasikan.

ABSTRACT CLASS

Class abstrak adalah class yang hanya mempunyai fungsi virtual murni, sehingga tidak mempunyai constructor juga.

Contoh:

class DASAR

{

public: virtual void setLabel()=0;

};

Apa kegunaan class abstrak?

OVERLOAD

Berbeda dengan override, dalam overload kita dapat membuat ulang suatu fungsi dengan parameter yang harus berbeda (baik tipe atau jumlah parameter).

Contoh:

class DASAR

{

public:

DASAR();

~DASAR();

private:

int x;

int y;

void printLabel(char *);

public:

char *label;

virtual void setLabel() //inisalisasi setLabel() sebagai fungsi virtual

{

cout << “DASAR”;

}

virtual void setLabel( char *lbl)

{

cout << lbl

}

};

Apakah harus diinisialisasi sebagai fungsi virtual?

Tidak harus, tergantung apakah akan kita ijinkan keturunan meng-override atau tidak

Instansi Class

Misalkan dari class DASAR diatas akan kita turunkan menjadi class TURUNAN1, maka caranya:

//buat kerangka class TURUNAN1

class TURUNAN1 : public DASAR

{

public:

TURUNAN1();

~TURUNAN1();

public:

int currPosX;

int currPosY;

void setPosisi();

};

//implementasi:

TURUNAN1::TURUNAN1() : DASAR()

{

}

TURUNAN1::~TURUNAN1()

{

}

void TURUNAN1::setPosisi()

{

}

Pada class TURUNAN, akan mewarisi semua member dari class DASAR karena class TURUNAN diturunkan dari class DASAR

Class

Membuat Class

cara membuat class:

class nama_class

{

data_member;

function_member;

};

contoh:

class DASAR

{

public:

DASAR();

~DASAR();

private:

int x;

int y;

void printLabel(char *);

public:

char *label;

void setLabel();

};

Pada contoh diatas, kita telah membuat class dengan nama DASAR dengan data member adalah x, y, *label juga mempunyai function member yaitu DASAR(), ~DASAR() dan setLabel().

Untuk apa fungsi DASAR() dan ~DASAR() ?

Fungsi DASAR() adalah konstruktor dari kelas DASAR.

Fungsi ~DASAR() adalah destruktor dari kelas DASAR.

Apa yang dimaksud konstruktor? Apa gunanya? Bagaimana cirinya?

Konstruktor adalah fungsi yang pertama kali dipanggil saat suatu object class diciptakan/di-inherit.

Kegunaanya adalah terserah programmer, misalnya jika kita ingin menginisialisasi suatu data member pada saat pertama-kali object diciptakan, maka proses inisialisasi tersebut dapat kita tuliskan dalam fungsi konstruktor.

Ciri suatu fungsi sebagai konstruktor adalah:

  1. Mempunyai nama yang sama dengan nama class.
  2. Tidak mempunyai tipe keluaran.
  3. Selalu mempunyai akses public.

Apa yang dimaksud Destruktor? Apa gunanya? Bagaimana Cirinya?

Destruktor adalah fungsi yang dipanggil saat suatu object class dimusnahkan.

Kegunaanya adalah terserah programmer, misalnya jika kita ingin membebaskan memori yang merupakan member object, yang telah kita alokasikan, maka proses pembebasan alokasi memori ini dapat kita letakkan pada Destruktor

Ciri suatu fungsi sebagai destruktor adalah:

  1. Mempunyai nama yang sama dengan nama class, namun diawali tanda ~.
  2. Tidak mempunyai tipe keluaran.
  3. Selalu mempunyai akses public.

Pada class diatas, hanyalah suatu kerangka object, implementasinya kira-kira adalah seperti berikut ini:

DASAR::DASAR()

{

//isi konstruktor

}

DASAR::~DASAR()

{

//isi destruktor

}

void DASAR::setLabel()

{

//implementasi fungsi setLabel

}

void DASAR::printLabel(char *)

{

//implementasi fungsi setLabel

}

Apa maksud public, private diatas?

Lihat pada topik “tipe akses“!

Tips:

Buat file .h (header) yang berisi kerangka object dan file .cpp (source) yang berisi implementasi dari class dan jangan lupa include kan file .h nya.

Contoh file header (dasar.h):

#ifndef DASAR_H

#define DASAR_H

class DASAR

{

public:

DASAR();

~DASAR();

private:

int x;

int y;

void printLabel(char *);

public:

char *label;

void setLabel();

};

#endif

contoh implementasi class (dasar.cpp)

#define “dasar.h”

DASAR::DASAR()

{

//isi konstruktor

}

DASAR::~DASAR()

{

//isi destruktor

}

void DASAR::setLabel()

{

//implementasi fungsi setLabel

}

void DASAR::printLabel()

{

//implementasi fungsi setLabel

}

Konsep OOP

Salah satu kelebihan utama C++ dibandingkan dengan C adalah ditambahkannya fasilitas Object Oriented Programming (OOP), sehingga pada awal mulanya, C++ dinamakan “C dengan class”. Sebenarnya apakah yang dimaksud dengan istilah OOP, class dan object tersebut? Pengertian istilah-istilah ini sangat penting untuk memahami C++.

Untuk membahas konsep Prosedural dalam C dan OOP dalam C++, kita asumsikan kita akan membuat suatu tombol. Tombol push-button? Ya! Tombol push-button yang biasa kita click dengan mouse!

Tombol ini mempunyai data:

label berupa string.

PosisiX berupa int

posisiY berupa int.

status berupa boolean.

Untuk men-create tombol, kita gunakan fungsi

create_tombol()

Kemudian aksi pada tombol ini adalah:

tombol_diclick()

Program Prosedural

Pada program prosedural, data-data tombol diatas mungkin akan kita satukan dalam sebuah struct. Sedangkan fungsi create_tombol() dan tombol_diclick() kita buat terpisah.

OOP

Pada OOP, tombol diatas dianggap sebagai suatu object, sehingga data, beserta fungsi yang berkaitan dengannya: crate_tombol() dan tombol_diclick() dibungkus menjadi satu menjadi katakanlah object tombol. Pembungkus dari data dan fungsi-fungsi bersesuaian menjadi satu object disebut sebagai class. Sehingga dengan menggunakan pembungkus (class) ini diharapkan data-data dan fungsi-fungsi yang bersesuaian untuk suatu object dapat dikumpulkan menjadi satu sehingga program akan menjadi lebih rapi.

Sehingga:

Object : Ingat pelajaran Bahasa Indonesia tentang SPO! Object adalah apa yang “dikenakan” oleh subject, bila subject adalah pengguna program, maka tombol dalam program adalah object-nya.

Class : Telah dibahas diatas, class adalah pengumpul data, fungsi yang bersesuaian untuk membentuk suatu object.

Untuk dapat dikatakan OOP, suatu bahasa pemrograman harus mempunyai ciri:

  1. Abstraction (Penyembunyian detail)

Yaitu penyembunyian detail object. Untuk apa? Untuk menyederhanakan cara pikir programer, maka detil oject yang tidak perlu untuk diatur/diutak-atik lagi perlu diabstraksi. Pada contoh object tombol diatas, untuk pengunaan object selanjutnya kita tidak perlu mengutak-atik cara penggambaran tombol ke screen. Proses penggambaran tombol ke screen kita abstraksi.

  1. Encapsulation (Pembungkusan)

Seperti penjelasan diatas, data dan fungsi yang bersesuaian pada suatu object dibungkus oleh class menjadi suatu object, pembungkusan inilah yang disebut encapsulation

  1. Inheritance (Pewarisan object)

Pewarisan object adalah kita dapat membuat object1 dengan sifat baru, namun masih memiliki sifat object2, object1 dikatakan diturunkan dari object2

  1. Polymorfisme (Banyak bentuk)

Kita diijinkan untuk membuat/mendefinisi ulang member fungsi dari class induk pada class turunan dengan syarat member fungsi induk haruslah virtual function (dibahas nanti). Pembuat/definisi ulang ini dapat mempunyai isi yang berbeda.

KOMPUTER LAMA

Sedikit Cerita

Saya mempunyai background pendidikan Elektronika/ELKA (Elektro Arus lemah) dan mempunyai hobby di bidang elektronika. Oleh karena itu sering sekali saya mendesain serta mengimplementasikan suatu rangkaian elektronika baik analog maupun digital. Solder, timah dan komponen elektronika sudah menjadi keseharian saya! Namun, disamping itu semua saya juga menyukai pemrograman komputer, pada awalnya karena ketertarikan saya untuk “mengontrol sesuatu” menggunaka komputer. Mulai prosesor kelas 8088 dan Z80 dari Zilog dengan mode minimum, hingga komputer saya sekarang (dengan dual-core)! Dasar-dasar digital, minimum sistem dengan mapping memori dan I/O, sedikit banyak membantu saya dalam mempelajari pointer dan alokasi memori misalnya.

Komputer tipe lama misal 486 atau Pentium awal, sekarang ini banyak yang sudah dimanfaatkan lagi, bahkan di suatu iklan saya pernah mendapati Pentium 166 dengan harga Rp 6000, lebih murah dari sebungkus rokok! Sebagai orang elektronika, rasanya sayang kalau kekuatan komputasi komputer sekelas Pentium 166 hanya disia-siakan begitu saja.

Sebenarnya kita sadari atau tidak kita (termasuk saya), komputasi yang kita pakai saat ini banyak sekali yang mubazir. Misalnya kita menggunakan aplikasi word prosessor, microsoft. Coba bandingkan saat anda memakai microsoft office 95 dengan microsoft office XP! Apakah kita benar-benar telah memakai fungsi-fungsi microsoft office XP? Ataukah kita hanya mengganti (konversi) format data dari microsoft office 95 ke microsoft office XP? Menurut penilaian saya, kita lebih banyak “hanya” konversi format. Fungsi bold, underline, italic dengan font times-new-roman, arial ataupun verdana saya rasa sudah cukup tertangani oleh microsoft office 95! atau bahkan microsoft office 95 sudah terlalu advance? Dan kita hanya membutuhkan edit.com di DOS? Coba renungkan! Jujur saja!

Update software seperti aplikasi microsoft office pada contoh diatas harus kita bayar mahal dengan kekuatan komputasi yang berlipat-ganda hanya untuk mengkonversi format! Buktinya?

Coba anda jalankan microsoft office XP pada Pentium 166 dengan memori 16M! Bagaimana hasilnya? Bisa jalan? Berapa space harddisk yang dibutuhkan? Itulah kekuatan komputasi yang harus kita bayar!

Mengapa hal ini bisa terjadi? Menurut pendapat saya, hal ini disebabkan karena:

  1. Marketing! Marketing begitu membuai konsumen untuk update software dengan iming-iming penampilan software yang aduhai, bandingkan microsoft XP dengan microsoft Vista. Oleh marketing software kita dibuai untuk update software, saat kita update ternyata oops..! spesifikasi komputer kita masih kurang dan... kita harus update komputer. Komputer lama? Nganggur!
  2. Kecenderungan kita yang menggunakan program bajakan! Sangat mudah dan murah untuk mendapatkan program-program terbaru dan updatenya! Hingga kita melupakan yang lama.
  3. O ya! Selain alasan diatas kemungkinan besar kita tidak akan bisa mendapatkan microsoft 98 lagi di reseller microsoft karena sudah tidak diproduksi, dan kita dipersilahkan untuk membeli versi terbaru (Microsoft Vista), tentunya dari segi harga akan lebih mahal !
  4. Satu lagi! Saat kita mengetik suatu dokumen, kemudian kita tekan ctrl-S untuk saving document, maka dokumen akan disimpan ke dalam format terbaru, bukan format yang paling sederhana dan tepat (efisien) ! Sehingga bila kita akan membuka dengan aplikasi lain dengan versi lebih lama, dokumen tidak terbaca.

Kasus seperti ini pernah saya temui, saat saya berada dirental pengetikan. Tiba-tiba masuk dua mahasiswi teknik dengan membawa file yang dibuat dengan AutoCad untuk di-print, saat dibuka ternyata tidak ada gambar yang tampak! Panik-lah kedua mahasiswi ini, karena dianggap file rusak, belum ter-save dsb...! kasihan.....! Setelah diusut ternyata sang mahasiswa menggunakan AutoCad 2008 (yang harganya mungkin lebih mahal daripada printer di-rental) dan langsung di-save apa adanya, sementara rental menggunakan AutoCad2005. Hanya beda tiga tahun document sudah tidak bisa dibaca!

  1. Ada juga satu alasan yang mungkin sering kita dengar: mengikuti trend agar dapat membaca format terbaru! Benarkah? Coba anda ketik suatu document, kemudian save-as html. Buka dengan browser! Adakah komputer atau OS yang tidak bisa membaca file html?

Cerita saya diatas bukanlah bermaksud melarang anda untuk update, there is up to you! Atau menjelek-jelekan suatu produk. Namun hanya mencoba berbagi bagaimana kita menggunakan komputer secara lebih efisen.

Kembali ke cerita tentang hardware. Ada “sesuatu” yang saya anggap hilang saat saya mengganti komputer lama saya dengan yang baru. “sesuatu” tersebut adalah ISA slots dan Serial port cuma satu, untuk laptop keluaran terbaru bahkan lebih parah! Jangan harapkan anda melihat DB9-male untuk serial port dan DB-25 Female untuk paralel port (LPT)!

Mungkin kita dapat mengunakan konverter USB untuk menggantinya. Tetapi apakah telah sesuai? Pernah saya menggukan USB-Serial converter untuk menambahkan satu serial port lagi, harapan saya dengan cara ini saya bisa menggunakan (menghubungkan) dengan port serial yang lain (bawaan mobo) membentuk null modem. Tapi apa yang terjadi? Dengan minicom di Linux karakter yang ditransfer menjadi kacau dan transfer terjadi hanya satu arah. Saat dicoba dengan hyperterminal di windows kasus di minicom terulang, bahkan lebih parah, setelah beberapa menit windows menjadi HANG, ctrl-alt-del end-task? No response! Ctrl-alt-del shutdown? No response! Akhirnya saya ikuti perintah dari microsoft yang biasa keluar saat blue-screen (dengan sedikit modifikasi) “Press any key to continue” yang dimaksudkan om gates dalam “any key” adalah “restart button” karena hanya dengan tombol inilah yang berhasil!

Menurut analisa saya dan dengan membolak-balik halaman web, banyak (kebanyakan) didalam USB-Serial converter adalah mikrontroler yang diisi program komunikasi dengan USB dan dikeluarkan sebagai UART (sistem komunikasi yang dipakai serial port PC) beberapanya adalah mikrokontroller keluarga MCS51buatan cypress semiconductor dan kebetulan saya pernah mencoba mikrokontroler dari cypress ini dengan USB (dengan firmware dari deVaSys). Yang saya ingat tegangan yang dipakai adalah 3.3 V (kalau tidak 3.7V) sehingga logika tegangan portnya akan mengikuti! Perbedaan level tegangan antara USB-Serial Converter dengan Serial Port inilah yang menjadi masalahnya!

Kenapa saya “merindukan” slot ISA?

Antarmuka pada slot isa inilah yang saya anggap sederhana. Walaupun tidak secepat ISA, namun untuk aplikasi kontrol sudah mencukupi. Dengan adanya ISA slot, kita dapat memasang I/O Card baik yang sederhana dengan suatu latch dan buffer ataupun yang terintegrasi dengan IC PPI (Programmable Peripheral Interface), IC yang murah dan relatif masih mudah ditemui, mungkin pembuatan PCBnya yang agak repot (bukan rumit) karena pemotongan dan posisi ke slot harus sesuai. Kita juga bisa membuat ADC (Analog – Digital Converter) Card untuk dihubungkan ke sensor suhu, kecepatan angin, kelembaban sehingga menjadi suatu data logger pemantau cuaca sederhana!

Oh ya! Saya juga pernah mempunyai sebuah EPROM Emulator yang membutuhkan PPI Card pada ISA slot. EPROM Emulator adalah alat yang mengemulasi EPROM (Erasable Programmable Read Only Memory), jika tidak menggunakan EPROM Emulator tentu kita akan sering isi/hapus EPROM yang tidak sebentar dan tidak murah. EPROM Emulator ini banyak membantu saya saat mempelajari minimum system 8088 mulai bagaimana prosessor 8088 sesaat setelah reset? Bagaimana NMI? Bagaimana mengakses I/O pada 8088 dsb.

Selain dengan 8088 dan Z80, saya juga sering bermain-main dengan mikrokontroller keluarga MCS51,8031 dan hem... RISC AVR. Dengan fasilitas mikrokontroller yang semakin lengkap, harga semakin murah, mudah didapat semakin mudah pula kreatifitas tersalurkan!

Saat ini sudah ada embedded sytem yang telah siap pakai, berprosessor kecepatan tinggi (bahkan dengan RISC) dengan data lebih lebar (32 bit atau lebih), kapasitas memori besar bisa diisi Linux lagi! Tinggal dikonfigurasi ulang, isi program khusus dan siap dipakai seperti sebuah PC dengan special function! Dengan system seperti ini, kita dengan mudah bisa memasukkan fungsi filter digital dengan FFT untuk mengolah sinyal suara bahkan encoding/decoding Audio/Video.

Kapan saya bisa memilikinya ya? Mencobanya paling tidak! Atau ikut mengembangkannya? Ada yang mau menawari?

Namun, saya percaya minimum system dengan mikrokontroller dan embedded sytem dengan fasilitas yang wah, pasti mempunyai tempat sendiri-sendiri sesuai fungsinya. Mikrokontroller= to Controll , Mikroprosessor = to Process sesuai kata alm dosen saya. Menggabungkan keduanya, mungkin akan memberikan hasil yang baik.

Kembali ke PC tua, adakah kendala pada penggunaan PC tua?

Salah satunya adalah masalah storage (harddisk). Kita susah mendapatkan storage (harddisk) yang masih baik, fresh dari pabrik dengan jaminan garansi tentunya, yang dapat dipasang pada PC tua. Coba pasang harddisk 160 GB pada komputer 486!

Bagaimana pemecahannya? Update BIOS? Tidak semua produsen BIOS masih mensupport BIOS PC lama! LinuxBIOS? Masih terbatas, apalagi untuk komputer lama.

Mengganti harddisk dengan USB flashdisk? Kalaupun sudah ada port USB, namun pada PC lama belum support ke booting dengan BIOS.

Menggunakan floppy disk? Ya seperti perangkat wartel, banyak yang hanya menggunakan floppy disk, tapi untuk saat ini floppy-disk kan sudah ke laut......!

Saya pernah menemukan disuatu web adalah menggunakan Compact-Flash (CF) to IDE converter. Cara ini mungkin lebih masuk akal, dengan CF dengan kapasitas terkecil dipasaran sekalipun, sudah mencukupi untuk diisi kernel linux versi terbaru sekalipun beserta aplikasi kontrol kita, harga CF-pun masih termasuk ekonomis. Namun saya belum pernah mencoba (dan mendapatkan) CF to IDE converter ini.

Masalah lain adalah PSU, susah untuk mendapatkan PSU untuk komputer lama (AT bukan ATX).

Solusinya adalah memodifikasi PSU ATX menjadi PSU AT, keuntungan dengan modifikasi ini adalah kita akan mendapatkan PSU yang cukup powerful untuk komputer lama (apalagi untuk komputer tanpa Harddisk, CDROM). Kendalanya? Saya belum pernah mencoba memodifikasi PSU jadi belum tahu kendalanya he.. he..

POINTER dan ALOKASI MEMORI


Seperti dibahas pada topik POINTER dan ARRAY, bila kita ingin memfungsikan pointer sebagaimana suatu ARRAY maka kita harus mengalokasikan memori sesuai ukuran yang kita ingini. Inilah kelebihannya, kita mampu mengalokasikan memori sesuai kebutuhan kita.

Contoh kasus:

Kita ingin mengambil data pixel suatu gambar, kemudian kita menyimpannya ke buffer (penampung sementara) untuk diolah. Bagaimana kita mendefinisikan ukuran array bila ukuran gambar bermacam-macam?

Perlu diingat jumlah array harus didefinisikan dahulu sebelum, dipakai !

Apabila ukuran array lebih kecil dari yang kita gunakan, maka akan menyebabkan segmentation fault (banjir).

Menggunakan Array yang super besar? Bagaimana jika yang kita load ternyata ukurannya kecil? Tentu memboroskan memori.

Mengatur ukuran gambar agar fix? Tentu program kita menjadi tidak portable! Serta perlu editor gambar.

Solusi:

Kita gunakan alokasi memori dinamis! Dinamis? Ya! Karena kita dapat mengalokasikan dimana saja, berapa saja serta dapat didealokasikan kapan saja agar dapat dipakai untuk yang lain.

Apa perbedaan memori dinamis dan statis (Array)?

Memori dinamis telah djelaskan diatas, sedangkan array alokasi dan dealokasi dilakukan oleh kompiler, jumlah alokasi sudah tetap sebesar saat kita mendefinisikan Array di awal program.

OK! Algorithma pemecahan masalah diatas:

Inisialisasi pointer

Load File Image

Dapatkan ukuran Image beserta pixelnya.

Alokasikan memori sebesar ukuran pada step 3, tunjuk pointer ke alamat memori yang dialokasikan ini.

Proses Image.

Apabila proses telah selesai dan alamat memori diatas sudah tidak dipakai, maka de-alokasikan alamat memori dari step 4. Agar bisa digunakan untuk yang lain.

Proses dealokasi penting dilakukan untuk meningkatkan performa, serta menghindari “out of memory”.

Cara mengalokasi memori salah satunya adalah menggunakan fungsi malloc seperti yang didefinisikan pada file stdlib.h:

(void *)malloc(size_of_memory_yang_dialokasikan)

Contoh program Pointer , Array dan alokasi memori dinamis.

#include

#include

int main()

{

int *X;

int *posAwal;

int i;

X = (int *)malloc(10*sizeof(int)); // alokasi memori sebesar 10 *4 byte.

// Identik dengan X[10] pada Array

posAwal = X; // simpan posisi awal X ke posAwal (agar tidak tersesat)

/* Dengan Array */

for(i=0;i<10;i++)

X[i] = i;

for(i=0;i<10;i++)

printf(“X[%d] = %d”,i,X[i]);

/* Dengan Pointer */

for(i=0;i<10;i++)

*X++ = i *10;

X = posAwal; // kembalikan posisi awal X

for(i=0;i<10;i++)

printf(“*X = %d”,*X++);

free(X); //bebaskan memori X

}

Pada program diatas, saat menggunakan pointer sebaiknya kita menyimpan posisi awal dari memori yang ditunjuk, agar tidak terjadi kasus seperti pada pembahasan POINTER dan ARRAY

POINTER dan ARRAY

Dalam pemrograman C, definisi array dituliskan:

type_name array_name[number_of_array]

misal array A bertipe integer dengan 10 anggota didefinisikan dengan:

int A[10];

Apa maksudnya?

Dengan penulisan diatas, maka kita memrintahkan kompiler untuk menyediakan alamat memori sebesar 10 * sizeof(int). Bila ukuran int adalah 4 byte, maka compiler akan mengalokasikan sebesar 10 * 4 byte = 40 byte memori untuk A.

Bagaimana penggambaran di memori:

misalnya alamat awal Array A (A[0]) adalah 0xFFFF0000, maka dapat digambarkan:

A[0]

0xFFFF0000

A[1]

0xFFFF0004

A[2]

0xFFFF0008

…..

…......................

A[7]

0xFFFF001C

A[8]

0xFFFF0020

A[9]

0xFFFF0024

Lalu apa hubungannya dengan pointer?

Seperti pada pembahasan pointer dengan variabel, pointer pada array sesungguhnya kita juga memerintahkan pointer agar menunjuk ke alamat yang telah dialokasikan oleh array tersebut. Pada contoh diatas, bila kita mendefinisikan suatu pointer

int *P:

kemudian kita tunjuk ke alamat Array A

P = &A[0];

maka alamat P akan menunjuk ke alamat 0xFFFF0000

Untuk lebih jelasnya coba program berikut ini:

int main()

{

int *pointer, Array[10];

int i;

for(i=0;i<10;i++)>

Array[i] = i; //pengisian array

for(i=0;i<10;i++)

printf(“Array = %d\n”,Array[i]); //cetak Array

pointer = &Array[0]; // tunjuk pointer ke alamat awal array

// bisa dituliskan pointer=Array

for(i=0;i<10;i++)

printf(“pointer = %d\n”,*pointer++); //cetak pointer

}

Bagaimana hasil program diatas?

Hasil dari:

for(i=0;i<10;i++)

printf(“Array = %d\n”,Array[i]); //cetak Array

dengan:

for(i=0;i<10;i++)

printf(“pointer = %d\n”,*pointer++); //cetak pointer

adalah sama.

Hal ini berarti dapat kita simpulkan bahwa:

1. Kita dapat membaca isi dari suatu array melalui suatu pointer, asalkan pointer tersebut menunjuk ke alamat dari array yang ingin kita baca.

2 Increment dari pointer yang menunjuk ke array adalah sam dengan increment index (posisi) dari array yang ditunjuk.

Bagaimana dengan mengisikan data ke array dengan pointer?

Sama halnya dengan contoh diatas. Lihat contoh berikut ini;

int main()

{

int *pointer, Array[10];

int i;

pointer = &Array[0]; // tunjuk pointer ke alamat awal array

// bisa dituliskan pointer=Array

for(i=0;i<10;i++)

printf(“pointer = %d\n”,*pointer++); //cetak pointer

for(i=0;i<10;i++)

printf(“Array = %d\n”,Array[i]); //cetak Array

}

Hasilnya sama bukan?

Namun hati-hati ada kalanya kita tanpa sadar mebuat bug yang menyebabkan segmentation fault, contohnya:

int main()

{

int *pointer, Array[10];

int i;

for(i=0;i<10;i++)

Array[i] = i; //pengisian array

pointer = &Array[0]; // tunjuk pointer ke alamat awal array

// bisa dituliskan pointer=Array

for(i=0;i<10;i++)

printf(“pointer = %d\n”,*pointer++); //cetak pointer

for(i=0;i<10;i++)>

*pointer++ = i+10; //pengisian array melalui pointer

for(i=0;i<10;i++)

printf(“Array = %d\n”,Array[i]); //cetak Array

}

Bila kita lihat sekilas, tidak ada kesalahan dalam program diatas, namun saat kita eksekusi akan timbul segmentation fault. Penyebabnya adalah:

for(i=0;i<10;i++)>

*pointer++ = i+10; //pengisian array melalui pointer

Pada instruksi diatas posisi *pointer sudah tidak lagi menunjuk ke Array[0], namun sudah menunjuk ke Array[9 + 1], karena proses increment alamat pointer pada instruksi sebelumnya:

for(i=0;i<10;i++)

printf(“pointer = %d\n”,*pointer++); //cetak pointer

Dan kita telah memesan alamat memori sebesar 10 block (40 byte), sedangkan *pointer menunjuk ke block ke 11 (Array[9+1]). Jadi block ke 11 (Array[9+1]) belum dialokasikan, akibatnya muncul segmentation fault.

Bagaimana mengatasinya?

Menambah index Array? Solusi ini mungkin bisa berjalan namun tidak efisien. Solusi yang baik adalah dengan mengarahkan kembali penunjukan pointer ke alamat awal Array:

pointer = &Array[0]; // Tunjuk pointer ke alamat awal array

// bisa dituliskan pointer=Array

for(i=0;i<10;i++)>

*pointer++ = i+10; //pengisian array melalui pointer

pointer = &Array[0]; // tunjuk pointer ke alamat awal array

// bisa dituliskan pointer=Array

Coba ubah program diatas! Jalankan! Masih terjadi segmentation fault?

Maka yang perlu diingat adalah jangan lupa untuk mengembalikan pointer keposisi awal (posisi yang teralokasikan) sebelum kita menggunakan lagi.

Lalu apa perbedaan Array dan Pointer?

Array telah teralokasikan alamatnya pada memori pada tiap-tiap indexnya, sedangkan pointer hanyalah suatu penunjuk ke alamat memori (context Array).

Bisakah pointer menggantikan Array tanpa ada Array?

Bisa, asalkan pointer kita tunjuk ke alamat yang sudah teralokasikan oleh compiler. Caranya? Lihat pada bagian “POINTER dan ALOKASI MEMORI DINAMIS”