Pemrograman Dasar C Minggu 10
Topik Bahasan • Pointer: – Pointer ke array • Penggunaan untuk mengirim ke fungsi
– Arithmatika pointer – Pointer ke pointer – Pointer dan Structure • Penggunaan untuk mengirim ke fungsi
Pointer dan Array • Sampai saat ini, kita telah mengakses array dengan menggunakan indeks array: int my_array [20]; ... my_array[5] = 26; /* elemen ke-6 */ my_array[0] = 32; /* elemen ke-1 */ Dapat mengakses berbagai elemen dengan memasukkan nomor indeks untuk elemen
Pointer dan Array • Nama dari array sendiri adalah pointer konstan pada elemen pertama dari array, jadi kita dapat meng-assign alamat dari sebuah array ke sebuah pointer: int *p_array; ... p_array = my_array; Diatas kita telah menciptakan sebuah pointer untuk tipe int (bertipe sama dengan array yang ingin kita tunjuk) dan menginisialisasi dengan alamat dari elemen pertama dari array my_array. Jadi menulis *p_array = 56; sama dengan p_array[0] = 56;
Arithmatika Pointer • Kita menciptakan variabel pointer untuk mempunyai tipe yang sesuai dengan sesuatu yang kita ingin tunjuk, contohnya untuk menunjuk double kita menciptakan sebuah pointer dari pointer ke tipe double dll. Ini memungkinkan arithmatika pointer.
int i_array [3], *p_i_array, i; /* kode lain */ p_i_array = i_array; *p_i_array = 12; p_i_array = p_i_array + 1; *p_i_array = 4; p_i_array += 1; *p_i_array = -67; for(i = 0; i < 3; i++) printf(“\t %2d”, i_array[i]);
Arithmatika Pointer • Disini kita menggunakan pointer untuk menunjuk setiap elemen dari array secara bergantian dengan menambah 1 setiap kali ke nilai pointernya. Untuk print loop dari array dengan menggunakan system indeks yang biasa dan mendapatkan 12
4
-67
Tambahan Arithmatika Pointer • Ruangan yang diperlukan untuk menyimpan sebuah elemen tunggal pada tipe tertentu adalah tergantung implementasi, contohnya pada sebuah PC sebuah int akan menempati 2 bytes. Jadi untuk menentukan alamat lokasi yang berurutan dari array int kita perlu untuk memajukan pointer dengan 2 byte lokasi setiap kali. Pada komputer jenis lain (atau menggunakan kompiler yang lain) int mungkin disimpan menggunakan sebuah lokasi alamat dengan angka yang berbeda jadi penambahan alamat (address) mungkin selain dengan 2. ‘C’ menghandel ini secara otomatis.
Tambahan Arithmatika Pointer • Kita dapat menggunakan arithmatika pointer karena pointer dibuat mempunyai tipe yang sama dengan sesuatu yang ditunjuknya (pada kasus contoh kita, tipenya int). Jadi ketika kita menambah pointer pada kenyataannya ditambah dengan jumlah yang tepat untuk menunjuk alamat dari elemen berikutnya dari tipe tsb. secara otomatis, contoh untuk lokasi integer pada sebuah PC alamat dari pointer int ditambah +2 byte alamat!
Contoh Arithmatika Pointer PC Random Access Memory
•
Long int menempati 4 byte pada PC IBM jadi pertimbangkan array: long int my_array [3]; long int *p_my_array = &my_array[0]; Jika alamat bytenya pada lokasi pertama adalah:
Byte wide memory addresses
•
0407 0406 0405 0404 0403 0402 0401 0400 03FF 03FE 03FD 03FC 03FB 03FA
[2] p_my_array +2 = 0402
[1] p_my_array + 1
[0]
= 03FE
p_my_array = 03FA
Mengirimkan Array ‘by reference’ ke #include <stdio.h> Fungsi
param. pointer
void cek_array (int *l_a, int array_size) { int i; fungsi std lib cari ukuran 1 int
•
•
Kita telah tahu kita tidak dapat mengirimkan seluruh array ‘by value’ ke fungsi, tapi kita dapat menggunakan pointer untuk memberikan fungsi akses ke array yang dengan cara lain tidak mungkin ‘by reference’ Catatan: penggunaan operator sizeof untuk mengetahui panjang array, dengan membagi jumlah byte digunakan untuk sebuah int dengan jumlah byte dari keseluruhan array int!
for( i = 0; i < (array_size / sizeof(int)); + +i) printf(“\n l_a[%d] = %d”, i, l_a[i]); }
pointer dipakai sbg nama array
int main (void) { int i_array [3] = {0}, i, size; for(i = 0; i < 3; ++i) i_array[i] = (i+1) * 5; menemukan ukuran seluruh array
}
size = sizeof(i_array); cek_array (i_array, size); return (0) kirim by reference
nama array = address
Hati-Hati dengan Indeks dan Pointer • Ingat C tidak melakukan cek kisaran untuk kita, contohnya tidak ada pesan error jika kita melakukan ini: int sml_a [10]; /* hanya berukuran 10 */ sml_a[15] = 66; /* indeks yang tidak baik */
• Kita telah berusaha menulis sebuah elemen dari array sml_a yang tidak ada! Konsekuensinya sangat berbahaya: ia mungkin merusak ruangan variabel yang lain, it mungkin mengakses register hardware dan merusak PC! Ini juga berlaku untuk pointer.
Hati-Hati dengan Indeks dan Pointer int *p_a, sml_a [10]; p_a = &sml_a[0]; *(p_a + 15) = 66;
• Diatas penggunaan pointer akan mempunyai akibat yang sama dengan contoh indeks. • Catat juga, penggunaan operator indirection * diatas, arithmatika alamat ada di dalam kurung untuk memaksa penjumlahan dilakukan dahulu (pada operator unary * dan mempunyai prioritas lebih tinggi dari +, jadi butuh () untuk memaksa + dilakukan dulu.
Inisialisasi Pointer • Kita dapat inisialisasi pointer pada saat penciptaannya: int a; int *p_i = &a;
Diatas, kita telah menginisialisasi p_i untuk menunjuk ke a.
• Kita tahu bahwa pointer alamat yang jelek bisa berbahaya, maka bijaksana untuk menginisialisasi semua pointer pada saat penciptaannya.
Inisialisasi Pointer • Inisialisasi yang aman: jika anda tidak mempunyai apapun yang sesuai untuk ditunjuk saat penciptaannya, inisialisasi ke ‘NULL’. (Alamat NULL pada dasarnya menunjuk ke “tanpa alamat”): double *p_d = NULL; Jelas, tidak masuk diakal mengakses ruangan yang ditunjuk pointer NULL, ini tidak ada artinya. double x, *p_d = NULL; x = *p_d; Tidak ada yang tahu x sekarang berisi apa?!
Pointer ke Pointer • Jika kita bisa mendeklarasikan pointer ke elemen dari tipe apa saja (int atau double dll) kita juga bisa mendeklarasikan pointer ke pointer. Pertimbangkan yang berikut: double dl = 34.2, x; double *p_doub = NULL; double **p_p_doub = NULL: Kita telah mendeklarasikan sebuah variabel dari tipe double: dl, dan satu lagi bertipe pointer ke double: p_doub dan akhirnya satu lagi bertipe pointer ke pointer ke double: p_p_doub. Catat bahwa p_doub dan p_p_doub tidak mempunyai tipe yang sama!
Pointer ke Pointer • Kita bisa menggunakan operator ‘alamat dari’ ‘&’ seperti sebelumnya untuk assign nilai pada pointer-pointer ini: p_doub = &dl; p_p_doub = &p_doub; Kita bisa menggunakan pointer indirection seperti sebelumnya, sekarang jika kita menulis: x = **p_p_doub; Kita bisa mengakses sesuatu yang ditunjuk oleh pointer yang ditunjuk oleh pointer p_p_doub, jadi dl maka x sekarang = 34.2!
Menunjuk ke Structure • Ingat structure yang kita definisikan sebelumnya? typedef struct { char nama [12]; int umur; float tinggi; } orang;
• Mari kita menciptakan sebuah variabel dari tipe structure diatas dan mengakses elemen darinya: orang my_struct; my_struct.umur = 20;
Menunjuk ke Structure • Kita juga bisa mendefinisikan pointer dari tipe structure diatas dan menggunakannya untuk menunjuk pada variabel struktur ini: orang *p_struct; p_struct = &my_struct; (*p_struct).umur = 20;
• CATATAN: membutuhkan kurung karena operator ‘.’ mempunyai prioritas yang lebih tinggi dibanding operator indirection ‘*’, juga bisa menggunakan operator pointer struktur khusus ‘->’ yang lebih rapi: p_struct -> tinggi = 1.43;
Mengirim Pointer Structure ke Fungsi • Seperti yang dikatakan sebelumya, structure dapat dikirim ke fungsi ‘by value’, tapi, karena value dikirim melalui ‘stack’, jika structurenya besar akan menjadi proses yang lambat, jika sangat besar dapat menyebabkan stack over-flow (bencana!). Alternatifnya adalah untuk mengirim ‘by reference’ jadi hanya alamat (address) yang dikirim melalui stack jadi lebih cepat.
Mengirim Pointer Structure ke Fungsi
typedef struct { char nama [12]; int umur; parameter bertipe float tinggi; ‘pointer ke structure’ } orang; /* -----------------------------------------------*/ void tes_structure (orang *p_s) { printf(“umur = %d”, p_s->age); } /* -----------------------------------------------*/ int main (void) mengirim address { orang my_struct; dari structure
my_struct.umur = 20; tes_structure(&my_struct); return (0); }
Menunjuk ke Array 2D • Sebuah array 2 dimensi adalah “sebuah array dari array”, contohnya lihatlah definisi array berikut: int array_2d [5][2]; Menciptakan sebuah array dengan lima elemen, masingmasing elemen pada dasarnya sebuah array dengan elemen 2 int.
• Pointer harus dibuat dari sebuah tipe dari yang bertipe: “pointer dari tipe sesuatu yang saya tunjuk” • Sebuah pointer untuk array diatas akan menjadi sebuah “pointer ke sebuah array dari 2 int”. Kita dapat mengirim pointer tsb. ke sebuah array:
Menunjuk ke Array 2D #include <stdio.h> typedef int coord[2]; void tes_array (coord *p_2d) { int i; for (i=0; i<3;i++) { printf(“\n%d”, p_2d[i][0]); printf(“\t%d”, p_2d[i][1]); }} void main (void) { int array_2d [3][2] = {{1,11}, {2,12}, {3,13}}; int tes_array (array_2d); }
Ringkasan • Pointer – Pointer ke Array • Nama array sudah merupakan pointer! • Gunakan nama untuk mengirim “by reference”
– Arithmatika Pointer • Pointer berubah dengan bertahap sesuai dengan tipe yang ditunjuknya! • Dapat meruntut pointer sepanjang array
Ringkasan • Pointer ke pointer – Sebuah tipe pointer baru
• Pointer dan Structure – Penggunaan untuk mengirim ke fungsi (menghindari stack overflow)
• Pointer Array 2 Dimensi – Bertipe untuk menunjuk tipe array