Suatu fungsi dalam C mempunyai bentuk:
tipe_keluaran nama_fungsi ( tipe_parameter_1
parameter_fungsi_1,
tipe_parameter_2
parameter_fungsi_2,
.....
tipe_parameter_n
parameter_fungsi_n )
contoh fungsi main yang biasa dipakai:
int main(int argc, char argv[][])
{
return 0;
}
Pada fungsi main diatas, keluaran fungsi berupa integer (int), nama fungsi main, parameter1 bertipe integer, parameter 2 bertipe char. Instruksi return akan mengembalikan keluaran fungsi ini, keluaran fungsi ini adalah 0.
parameter2 fungsi main diatas adalah array dua dimensi, maka seperti yang telah kita pelajari diatas, maka fungsi main diatas dapat ditulis ulang dengan pointer seperti berikut:
int main(int argc, char **argv)
{
return 0;
}
suatu fungsi pertukaran nilai X dan nilai Y dituliskan sebagai berikut:
#include
int hasilY;
int tukar(int X,int Y)
{
int Z;
Z = X;
X = Y;
Y = Z;
hasilY = Y;
return X;
}
int main()
{
int X,Y,Z
X=10;
Y=20;
printf("sebelum ditukar:\n");
printf("X = %d\n",X);
printf("Y = %d\n",Y);
Z = tukar(X,Y);
printf("setelah ditukar:\n");
printf("X = %d\n",Z);
printf("Y = %d\n",hasilY);
}
Program diatas melibatkan variabel global hasilY, sebagai parameter penyimpan nilai Y setelah ditukar. Sedangkan nilai X setelah ditukar digunakan sebagai keluar fungsi tukar. Program seperti ini mempunyai kekurangan karena menggunakan variabel global, selain memboroskan memori, ada kemungkinan kesamaan dalam penamaan antara variabel satu dengan variabel yang lain.
Maka program diatas diubah menjadi:
#include
void tukar(int *X,int *Y)
{
int Z;
Z = *X;
*X = *Y;
*Y = Z;
}
int main()
{
int A,B;
A=10;
B=20;
printf("sebelum ditukar:\n");
printf("A = %d\n",A);
printf("B = %d\n",B);
tukar(&A,&B);
printf("setelah ditukar:\n");
printf("A = %d\n", A);
printf("B = %d\n", B);
}
Bagaimana cara kerja fungsi tukar diatas?
1. Parameter fungsi diinisialisasi sebagai pointer *X dan *Y.
2. Saat pemanggilan fungsi tukar:
tukar(&A, &B);
Maka terjadi penunjukan alamat A dan B oleh pointer *X dan *Y.
3. Karena penunjukan oleh pointer ini, maka perubahan nilai A dan B sesuai dengan perubahan pada pointer *X dan *Y, demikian pula perubahan nilai pointer *X dan *Y maka nilai A dan B juga berubah.
FUNGSI dengan KELUARAN berupa POINTER
Pernah menemui fungsi seperti ini?
int *fungsi(int x, int y);
fungsi tersebut adalah fungsi dengan keluaran pointer bertipe integer, salah satu contoh nyatanya adalah fungsi malloc yang pernah kita gunakan.
void *malloc(size_t sizeAlocation);
Lalu, apa guna fungsi seperti ini?
contoh program dengan fungsi mengembalikan pointer:
#include
#include
char *KAPITAL(char *Y)
{
char z;
char *X;
while(*Y)
{
i = i + sizeof(char);
Y = Y + sizeof(char);
}
Y = Y - i*sizeof(char);
X = (char *)malloc(i + sizeof(char));
while(*Y)
{
z = *Y;
if(z>'a' && z<'z')
*X = z;
Y = Y + sizeof(char);
X = X + sizeof(char);
}
*X = *Y;
return X = X - i*sizeof(char);
}
int main()
{
char *p="huruf kecil";
char *h;
h = KAPITAL(p);
printf("%s\n",h);
free(h);
return 0;
}
Cara kerja program diatas adalah sesuai dengan comment diatas, saya jelaskan ulang:
pada fungsi main()
h = KAPITAL(p);
sebenarnya adalah identik dengan kita menunjuk ke alamat return variabel (keluaran fungsi) dari fungsi KAPITAL. Sesuai dengan analisa kita didepan (topik pointer dan array) alamat ini adalah alamat index pertama dari keluaran fungsi itu sendiri dalam fungsi KAPITAL adalah N[0].
Apabila kita cermati dalam fungsi KAPITAL diatas, kita harus mengembalikan posisi pointer ke posisi awal pointer[0] setelah kita melakukan increment.
Y = Y - i*sizeof(char);
Untuk apa?
Karena kita membutuhkan alamat awal (index 0) dari pointer asal agar dapat kita gunakan untuk mengaksesnya sebagai satu kumpulan string, hal ini identik dengan "pemberi jejak" agar kita tidak tersesat.
maksudnya? Pada while berikut ini:
while(*Y)
{
i = i + sizeof(char);
Y = Y + sizeof(char);
}
apabila kita printf(Y) maka hasilnya tidak akan sama dengan isi Y yang kita maksud, karena alamat (pointer) dari Y itu sendiri telah bergeser akibat increment.
coba print alamat awal Y dan bandingkan dengan alamat sesudah increment:
//sebelum dan sesudah while coba tuliskan code berikut:
printf("Y = %p",&Y[0]);
Ingat lagi: karena *Y adalah pointer maka Y adalah alamat pada index ke 0 atau &Y[0]
Kenapa kita harus mengalokasikan memori dulu dalam fungsi KAPITAL dan kenapa h harus di free di fungsi main?
Kita, kompiler dan komputer tidak pernah mengetahui berapa jumlah array yang dibutuhkan untuk mem-buffer parameter masukan yang telah diolah, oleh karena itu besar kemungkinan terjadi segmentation fault karena kita/program dapat sembarangan menimpakan data ke alamat yang tidak teralokasikan!
Kita perlu membebaskan memori yang telah dialokasikan dengan free, dan tentu saja free ini harus ditempatkan setelah penggunaan memori telah selesai (tidak digunakan lagi). Karena pada contoh diatas memori yang disimpan akan ditampilkan dengan printf, maka setelah printf-lah kita dapat mem-free-nya.
Kenapa harus di free?
Untuk menghindari memory leak, yaitu kondisi dimana memori yang telah kita pakai (alokasikan) dan sudah tidak berguna namun tidak dapat digunakan (alokasikan) lagi, hal ini tentu menyebabkan pemborosan memori.
Untuk lebih jelas coba dan modifikasi program diatas! Bagaimana hasilnya?
Pada fungsi KAPITAL, setelah pengalokasian memori:
X = (char *)malloc(i + sizeof(char));
tambahkan:
printf("alamat X = %p\n", X);
Pada fungsi main, ganti dengan:
int main()
{
char *p="huruf kecil";
char *h;
int i;
for(i=0;i<10;i++)
{
h = KAPITAL(p);
printf("%s\n",h);
free(h);
}
return 0;
}
bandingkan dengan tanpa free:
int main()
{
char *p="huruf kecil";
char *h;
int i;
for(i=0;i<10;i++)
{
h = KAPITAL(p);
printf("%s\n",h);
}
return 0;
}
dengan main() yang pertama, alamat X akan selalu tetap, sedangkan pada main kedua alamat X akan selalu berubah (bertambah) sebesar jumlah memori yang dialokasikan (dalam contoh adalah 11 byte), sehingga dengan 10 perulangan kita telah memboroskan memori sebesar:
(10 * 11 byte) - 11 byte = 99 byte
bagaimana bila 1000 perulangan, dengan tipe memori yang dialokasikan adalah double ( 8 byte)?
Tidak ada komentar:
Posting Komentar