Algorithms and Programming C/C++ SYS Course 4
Pointer & Address
Ketika komputer dijalankan, komputer akan menjalankan sebuah program yang memiliki sebuah alamat/address yang biasanya disimpan didalam memori komputer. Pointer sendiri merupakan Pengalihfungsi sebuah variabel dari a ke b ataupun sebaliknya. Pointer mengimplementasikan address sebagai syarat penggunaannya. Jika kita memiliki sebuah variabel, maka variabel tersebut akan tersimpan didalam sebuah memori yang memiliki sebuah alamat unik khusus (yang kita sebut sebagai address), alamat tersebut dapat digunakan pada variabel lain untuk menghasilkan keluaran nilai yang sama. pointer memiliki dua poin penting yang harus dipelajari, yaitu address dan nilai. berikut ini adalah contoh penggunaan pointer:
1 |
|
Structure (Struct)
Struct merupakan tipe data object yang berisi banyak data dan memungkinkan memiliki tipe data berbeda. Setiap variabel yang ada didalam struct memiliki alamat/address memori yang berbeda. Strcut digunakan ketika kita memiliki kumpulan data yang memiliki tipe data berbeda misalkan seperti data user/pengguna yang memiliki variabel username (string), password (string), dan id (int). Untuk mendeklarasikan strcut anda dapat menggunakan keyword struct lalu nama structnya, berikut ini contohnya:
1 |
|
Union
Union merupakan tipe data object yang digunakan ketika terjadi dua perbedaan opsi, meskipun bisa menyimpan banyak data, tetapi union menyimpannya didalam satu alamat yang sama (setiap member union saling berbagi alamat memori yang sama). Biasanya union digunakan ketika terdapat opsi pemilihan pada program. Perumpamaan paling sederhana ialah pada sebuah game. sebagai player, kita dapat memilih opsi untuk menggunakan senjata (pistol, pisau, dan senapan angin). Player hanya dapat memilih satu diantara ketiganya untuk digunakan, disinilah biasanya union akan digunakan. untuk mendeklarasikan union anda dapat menggunakan keyword union lalu diikuti nama unionnya, berikut ini contohnya:
1 |
|
Structure Berindex
Structure berindex merupakan ilmu lanjutan dari structure dimana sebuah structure akan memiliki index, biasanya struct berindex digunakan pada sebuah data yang banyak/masif. berikut contoh dalam membuat struct berindex dan melakukan pengisian nilainya:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using namespace std;
typedef struct{
string email;
string username;
string password;
} database;
database g_struct_login[max_index] = {
/* EMAIL | USERNAME | PASSWORD */
{ "[email protected]", "administrator1", "12345" }, //Index 0
{ "[email protected]", "administrator2", "12345" }, //Index 1
{ "[email protected]", "administrator3", "12345" }, //Index 2
{ "[email protected]", "administrator4", "12345" }, //Index 3
{ "[email protected]", "administrator5", "12345" }, //Index 4
};
int main() {
int index = 0; //Masukkan Index bebas
cout<<g_struct_login[index].email<<endl;
cout<<g_struct_login[index].username<<endl;
cout<<g_struct_login[index].password<<endl;
return 0;
}
Extension
Ekstensi .c
File kode sumber dalam bahasa pemrograman C. Berisi implementasi dari fungsi-fungsi dan logika program.
Contoh: main.c mungkin berisi fungsi main() yang merupakan titik awal dari program.
Ekstensi .h
File header dalam bahasa pemrograman C. Berisi deklarasi fungsi, variabel, dan tipe data yang akan digunakan di file .c.
Contoh: stdio.h berisi deklarasi fungsi seperti printf() dan scanf().
Ekstensi .o
File objek yang dihasilkan setelah kompilasi kode sumber, tetapi sebelum proses linking.
Contoh: main.o, utils.o.
Ekstensi .a
File arsip yang berisi kumpulan file objek, biasanya digunakan untuk pustaka statis.
Contoh: libm.a, libc.a.
Ekstensi .so
File pustaka bersama (shared library) yang dapat digunakan oleh beberapa program secara bersamaan.
Contoh: libm.so, libc.so.
Ekstensi .exe (di Windows) atau tanpa ekstensi (di Unix/Linux)
File eksekusi yang dihasilkan setelah proses linking, siap untuk dijalankan.
Contoh: program.exe (Windows), program (Unix/Linux).
Contoh Kode
File greetings.h:1
2
3
4
5
6
7
8
9// greetings.h
// Deklarasi fungsi untuk menyapa
void sayHello();
void sayGoodbye();
File greetings.c:1
2
3
4
5
6
7
8
9
10
11
12// greetings.c
// Definisi fungsi untuk menyapa
void sayHello() {
printf("Hello!\n");
}
void sayGoodbye() {
printf("Goodbye!\n");
}
File main.c:1
2
3
4
5
6
7
8// main.c
int main() {
sayHello();
sayGoodbye();
return 0;
}
Penjelasan:
greetings.h: File header ini mendeklarasikan dua fungsi, sayHello dan sayGoodbye.
greetings.c: File kode sumber ini mendefinisikan fungsi sayHello dan sayGoodbye.
main.c: File kode sumber utama yang menggunakan fungsi sayHello dan sayGoodbye dari greetings.c untuk mencetak pesan sapaan.
Dengan contoh ini, kamu bisa melihat bagaimana file header (greetings.h) digunakan untuk mendeklarasikan fungsi-fungsi yang kemudian diimplementasikan di file kode sumber (greetings.c). File utama (main.c) kemudian menggunakan fungsi-fungsi tersebut untuk menjalankan program.
Keyword dalam C
Keyword pada C merupakan kata kunci yang digunakan sebagai perintah dengan maksud tertentu seperti menentukan tipe data ataupun menentukan alur kode, dsb. Pada C sebenarnya terdapat 32 keyword, tetapi penulis tidak akan membahas semuanya, karena pada pertemuan sebelumnya sebagian besar sudah dibahas dan ini adalah pembahasan terkait keyword tambahan sebagai pelengkap.
Static
Keyword static dalam bahasa C memiliki beberapa fungsi penting tergantung pada konteks penggunaannya:
Variabel Lokal dalam Fungsi
Ketika digunakan dalam deklarasi variabel lokal di dalam fungsi, static membuat variabel tersebut mempertahankan nilainya antara pemanggilan fungsi.
Contoh:
1 | void count() { |
Pada contoh ini, nilai callCount akan terus bertambah setiap kali fungsi count() dipanggil
Variabel Global dan Fungsi:
Ketika digunakan dalam deklarasi variabel global atau fungsi, static membatasi cakupan (scope) variabel atau fungsi tersebut hanya pada file tempat mereka dideklarasikan.
Contoh:
1 | // file1.c |
Variabel count dan fungsi increment() hanya dapat diakses di dalam file1.c
Pustaka Statis
static juga digunakan untuk mendeklarasikan fungsi atau variabel dalam pustaka statis, sehingga mereka tidak dapat diakses dari luar pustaka tersebut.
Dengan menggunakan keyword static, kamu dapat mengontrol cakupan dan masa hidup variabel serta fungsi dalam program C, membuat kode lebih terorganisir dan efisien.
Typedef
Typedef merupakan sebuah keyword pada C/C++ untuk mendefinisikan ulang variabel, fungsi, ataupun tipe data, berikut ini contoh penggunaan typedef:
1 |
|
Extern
Extern merupakan keyword yang digunakan untuk mendeklarasikan variabel atau fungsi yang dideklarasikan di file lain. Extern digunakan ketika kita ingin menggunakan variabel atau fungsi yang dideklarasikan di file lain. Berikut adalah contoh penggunaan extern:
File variables.h1
2
3
4
5
6
7
8// variables.h
// Deklarasi variabel eksternal
extern int sharedVariable;
File variables.c1
2
3
4
5// variables.c
// Definisi variabel eksternal
int sharedVariable = 10;
File main.c1
2
3
4
5
6
7
8
9// main.c
int main() {
// Mengakses dan mencetak nilai variabel eksternal
printf("Nilai sharedVariable: %d\n", sharedVariable);
return 0;
}
Dengan menggunakan keyword extern, kita dapat mendeklarasikan variabel di satu file dan menggunakannya di file lain. Ini sangat berguna untuk berbagi data antar modul dalam program yang lebih besar.
Untuk mengetahui keyword lain dan masing2 kegunaannya kamu bisa cek di dokumentasi bahasa resmi C.
Memory Management
Manajemen memori dalam bahasa C adalah proses mengelola penggunaan memori oleh program melalui berbagai operasi seperti alokasi, realokasi, dan dealokasi memori. Berikut adalah beberapa konsep penting dalam manajemen memori di C:
Alokasi Memori Statis
Memori dialokasikan pada saat kompilasi.
Contoh: Deklarasi variabel lokal dalam fungsi.
1 | int x = 10; |
Alokasi Memori Dinamis
Memori dialokasikan pada saat runtime menggunakan fungsi dari pustaka standar C.
Fungsi yang sering digunakan:
- malloc(): Mengalokasikan blok memori.
- calloc(): Mengalokasikan dan menginisialisasi beberapa blok memori.
- realloc(): Mengubah ukuran blok memori yang telah dialokasikan sebelumnya.
- free(): Mengembalikan memori yang dialokasikan ke sistem.
Contoh penggunaan malloc() dan free():
1 |
|
Manajemen Memori Dinamis
- malloc(): Mengalokasikan blok memori dengan ukuran tertentu.
- calloc(): Mengalokasikan beberapa blok memori dan menginisialisasinya ke nol.
- realloc(): Mengubah ukuran blok memori yang telah dialokasikan sebelumnya.
- free(): Mengembalikan memori yang dialokasikan ke sistem.
malloc()
Fungsi malloc() digunakan untuk mengalokasikan blok memori secara dinamis. Fungsi ini mengembalikan pointer ke blok memori yang dialokasikan.
Contoh:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main() {
int *ptr;
ptr = (int *)malloc(5 * sizeof(int)); // Mengalokasikan memori untuk 5 integer
if (ptr == NULL) {
printf("Alokasi memori gagal!\n");
return 1;
}
for (int i = 0; i < 5; i++) {
ptr[i] = i * 10;
printf("ptr[%d] = %d\n", i, ptr[i]);
}
free(ptr); // Mengembalikan memori yang dialokasikan
return 0;
}
calloc()
Fungsi calloc() digunakan untuk mengalokasikan beberapa blok memori dan menginisialisasinya ke nol. Fungsi ini mengembalikan pointer ke blok memori yang dialokasikan.
Contoh:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main() {
int *ptr;
ptr = (int *)calloc(5, sizeof(int)); // Mengalokasikan memori untuk 5 integer dan menginisialisasinya ke nol
if (ptr == NULL) {
printf("Alokasi memori gagal!\n");
return 1;
}
for (int i = 0; i < 5; i++) {
printf("ptr[%d] = %d\n", i, ptr[i]);
}
free(ptr); // Mengembalikan memori yang dialokasikan
return 0;
}
realloc()
Fungsi realloc() digunakan untuk mengubah ukuran blok memori yang telah dialokasikan sebelumnya.
Contoh:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int main() {
int *ptr;
ptr = (int *)malloc(5 * sizeof(int)); // Mengalokasikan memori untuk 5 integer
if (ptr == NULL) {
printf("Alokasi memori gagal!\n");
return 1;
}
// Mengubah ukuran blok memori menjadi 10 integer
ptr = (int *)realloc(ptr, 10 * sizeof(int));
if (ptr == NULL) {
printf("Realokasi memori gagal!\n");
return 1;
}
for (int i = 0; i < 10; i++) {
ptr[i] = i * 10;
printf("ptr[%d] = %d\n", i, ptr[i]);
}
free(ptr); // Mengembalikan memori yang dialokasikan
return 0;
}
free()
Fungsi free() digunakan untuk mengembalikan memori yang telah dialokasikan oleh malloc(), calloc(), atau realloc().
Contoh:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main() {
int *ptr;
ptr = (int *)malloc(5 * sizeof(int)); // Mengalokasikan memori untuk 5 integer
if (ptr == NULL) {
printf("Alokasi memori gagal!\n");
return 1;
}
// Menggunakan memori yang dialokasikan
for (int i = 0; i < 5; i++) {
ptr[i] = i * 10;
}
free(ptr); // Mengembalikan memori yang dialokasikan
return 0;
}
Pentingnya Manajemen Memori
- Mengoptimalkan kinerja program dengan menggunakan memori secara efisien.
- Menghindari kebocoran memori (memory leaks) dengan memastikan memori yang tidak lagi digunakan dikembalikan ke sistem.
- Menghindari kesalahan seperti dereferensi pointer null atau akses memori yang tidak valid.
Manajemen memori yang baik sangat penting untuk memastikan program berjalan dengan efisien dan bebas dari kesalahan yang terkait dengan penggunaan memori
Bit Field
Bitfield dalam bahasa C adalah cara untuk mengelola memori secara efisien dengan memungkinkan kita mendefinisikan jumlah bit yang tepat untuk merepresentasikan variabel. Bitfield sering digunakan dalam sistem embedded dan pemrograman tingkat perangkat keras di mana penggunaan memori yang efisien sangat penting.
Penggunaan Bitfield
Bitfield memungkinkan kita untuk menentukan ukuran dalam satuan bit dari anggota struct. Ini sangat berguna ketika kita tahu bahwa nilai dari suatu field tidak akan melebihi batas tertentu, sehingga kita dapat menghemat ruang memori.
Contoh Penggunaan Bitfield
Tanpa Bitfield:1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct date {
unsigned int day;
unsigned int month;
unsigned int year;
};
int main() {
struct date dt = {31, 12, 2024};
printf("Size of date: %lu bytes\n", sizeof(struct date));
printf("Date: %d/%d/%d\n", dt.day, dt.month, dt.year);
return 0;
}
Pada contoh diatas, struct date menggunakan 12 bytes memori (4 bytes untuk setiap unsigned int).
Dengan Bitfield:1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct date {
unsigned int day : 5; // 5 bit cukup untuk nilai 0-31
unsigned int month : 4; // 4 bit cukup untuk nilai 0-15
unsigned int year : 12; // 12 bit cukup untuk nilai 0-4095
};
int main() {
struct date dt = {31, 12, 2024};
printf("Size of date: %lu bytes\n", sizeof(struct date));
printf("Date: %d/%d/%d\n", dt.day, dt.month, dt.year);
return 0;
}
Pada contoh ini, struct date menggunakan hanya 4 bytes memori karena kita telah menentukan ukuran bit yang tepat untuk setiap field12.
Kelebihan dan Kekurangan
Kelebihan
- Efisiensi Memori: Menghemat ruang memori dengan menggunakan jumlah bit yang tepat.
- Kontrol yang Lebih Baik: Memberikan kontrol yang lebih baik atas representasi data.
Kekurangan
- Portabilitas: Implementasi bitfield dapat berbeda antara compiler, sehingga dapat mempengaruhi portabilitas kode.
- Kompleksitas: Penggunaan bitfield dapat menambah kompleksitas dalam pengelolaan data.
Bitfield sangat berguna dalam situasi di mana penggunaan memori yang efisien sangat penting, seperti dalam pengembangan sistem embedded dan perangkat keras.
Latihan
Buatlah sistem login dengan mengimplementasikan struct berindex dengan index paling sedikit 10, dimana terdapat dua menu pilihan login menggunakan email/username, Jika email/username atau password salah maka, program akan terus berulang dan Jika email/username dan password benar maka akan muncul tampilan login berhasil. Implementasikan pemrograman berorientasi objek dengan membuat fungsi untuk melakukan input serta fungsi untuk melakukan cek validasi email/username dan password. Berikut outputnya:
1 | ----------------------- |