PEMROGRAMAN BAHASA C
NAMA
:TOMYDARMAWAN
NPM
:36419386
KELAS
:1ID07
BAHASA
PEMROGRAMAN C
Bahasa
Pemrograman C adalah sebuah bahasa pemrograman komputer yang bisa
digunakan untuk membuat berbagai aplikasi (general-purpose programming language), mulai dari sistem operasi
(seperti Windows atau Linux), antivirus, software pengolah gambar (image processing), hingga compiler untuk bahasa
pemrograman, dimana C banyak digunakan untuk membuat bahasa pemrograman lain
yang salah satunya adalah PHP.
Meskipun
termasuk general-purpose
programming language, yakni bahasa pemrograman yang bisa membuat berbagai aplikasi,
bahasa pemrograman C paling cocok merancang aplikasi yang berhubungan langsung
dengan Sistem Operasi dan hardware. Ini tidak terlepas dari tujuan awal bahasa
C dikembangkan.
Bahasa
pemrograman C dibuat pertama kali oleh Dennis M. Ritchie pada tahun 1972. Saat itu Ritchie
bekerja di Bell Labs, sebuah pusat penelitian yang berlokasi di Murray Hill, New
Jersey, Amerika Serikat.
Ritchie membuat bahasa
pemrograman C untuk mengembangkan sistem operasi UNIX. Sebelumnya, sistem
operasi UNIX dibuat menggunakan bahasa assembly (assembly language). Akan tetapi bahasa
assembly sendiri sangat rumit dan susah untuk dikembangkan.
Dengan
tujuan mengganti bahasa assembly, peneliti di Bell Labs membuat bahasa pemrograman B. Namun bahasa pemrograman B juga memiliki beberapa kekurangan,
yang akhirnya di lengkapi oleh bahasa pemrograman C.
Dengan
bahasa C inilah sistem operasi UNIX ditulis ulang. Pada gilirannya, UNIX
menjadi dasar dari banyak sistem operasi modern saat ini, termasuk Linux, Mac OS (iOS), hingga sistem
operasi Android.
Fitur dan Keunggulan
Bahasa Pemrograman C
Berikut beberapa fitur serta keunggulan bahasa pemrograman C
jika dibandingkan dengan bahasa pemrograman lain:
C sebagai bahasa
pemrograman prosedural
Konsep pemrograman
prosedural adalah sebuah metode pemrograman yang setiap baris
perintah diproses secara berurutan dari baris paling atas hingga baris paling
bawah. Selain itu bisa terdapat fungsi tambahan (function) yang
digunakan untuk menyelesaikan berbagai tugas. Bahasa pemrograman C termasuk ke
dalam kelompok ini.
Selain konsep prosedural,
terdapat juga konsep pemrograman object (object-oriented
programming). Di dalam bahasa pemrograman object, setiap tugas akan
dijalankan menggunakan class dan object.
Contoh bahasa pemrograman object adalah JAVA.
Bagi pemula, sangat disarankan untuk mempelajari bahasa
pemrograman prosedural terlebih dahulu baru kemudian masuk ke dalam bahasa
pemrograman object. Ini juga menjadi alasan untuk belajar bahasa C sebelum
masuk ke bahasa pemrograman object seperti JAVA.
Beberapa bahasa
pemrograman ada yang mendukung konsep prosedural dan object sekaligus,
contohnya bahasa pemrograman C++, Python dan PHP.
Bahasa C sangat cepat dan
efisien
Aplikasi yang dibuat menggunakan bahasa C bisa dieksekusi dengan
sangat cepat serta berukuran kecil. Ini karena C bisa langsung berkomunikasi
dengan hardware, sebuah fitur yang jarang tersedia di bahasa pemrograman modern
seperti JAVA, PHP, maupun Python.
Akan tetapi, hal ini juga
memiliki kelemahan. Bahasa C relatif sederhana dan tidak memiliki fitur-fitur
modern seperti garbage collection dan dynamic
typing.
C adalah portable
language
Maksudnya, bahasa
pemrograman C bisa di-compile ulang supaya berjalan di berbagai sistem operasi tanpa
perlu mengubah kode-kode yang ada. Aplikasi yang dibuat di Windows dengan
bahasa C, bisa dipindahkan ke Linux dengan sedikit atau tanpa modifikasi.
C merupakan “induk” dari
bahasa pemrograman modern
Bahasa pemrograman C banyak
menginspirasi bahasa pemrograman lain, seperti C++, C#, Objective
C, PHP, JAVA, JavaScript dan masih banyak lagi. Dengan
mempelajari bahasa C, anda akan familiar dan lebih mudah saat berpindah ke
bahasa pemrograman lain yang merupakan turunan dari bahasa C.
Haruskah Saya
Mempelajari Bahasa C?
Jawaban
singkatnya: Anda tidak harus belajar bahasa C.
Sama
seperti bahasa Pascal, bahasa C saat ini kebanyakan dipakai sebagai bahasa pengantar untuk
mempelajari algoritma. Dimana algoritma itu sendiri merupakan kumpulan
instruksi untuk memecahkan masalah.
Sepanjang tutorial bahasa C di duniailkom ini kita juga hanya
menampilkan hasil program dalam bentuk teks yang mirip aplikasi DOS. Belum
sampai ke membuat aplikasi “sebenarnya” dengan tampilan grafis, gambar, mouse,
dan efek-efek menarik lain.
Namun ini
bukan berarti C tidak bermanfaat. Seperti yang saya singgung di keunggulan
bahasa C, C merupakan “induk” dari berbagai bahasa pemrograman modern. Dengan mempelajari C, anda juga
mempelajari dasar dari pemrograman.
Pemrograman Bahasa C
Setelah membaca ulasan di
atas, selnjutnya kita akan membahas tentang bahasa C. Bahasa ini adalah salah
satu bahasa pemrograman yang andal dan banyak digunakan. Seperti yang telah
disebutkan sebelumnya, bahasa C dapat berjalan pada berbagai platform, jadi
dengan mempelajari bahasa ini, pengetahuan yang anda proleh dapat digunakan
untuk mmeprogram di komputer dengan arsitektur selain x86.
Alasan Penggunaan Bahasa C
Bahasa C saat ini masih merupakan bahasa pemrograman yang banyak
digunakan dan powerful. Sebelum melangkah lebih jauh, penulis akan menjelaskan
beberapa alasan penggunaan bahasa C.
- Dalam
beberapa aplikasi pemrograman pada sistem operasi windows, kita tidak
dapat atau sangat sulit menggunakan bahasa pemrograman selain C, misalnya
untuk mengaplikasikan sebuah User Interface yang belum memiliki dukungan
library untuk C++ pada visual C++ atau dalam pembuatan driver. Penulis menyebutkan
sangat sulit berarti tidak menutup kemungkinan menggunakan bahasa lain,
bahasa lain tersebut adalah C++, namun dukungan ofisial dari microsoft
untuk penggunaan C++ pada kasus yang disebutkan sebelumnya belum ada
sehingga anda harus membuat semacam "wrapper" sendiri jika ingin
menggunakan C++ dan hal ini sulit dilakukan bagi pemrogram pemula. Perlu
diketahui bahwa Windows saat ini belum merupakan sistem operasi yang
benar-benar object oriented (C++ adalah bahasa pemrograman yang object oriented)
dan "core" dari sistem operasinya sendiri masih
diimplementasikan dalam bahasa C, sehingga fleksibilitas terbesar dalam
membuat software untuk windows akan kita peroleh jika kita menggunakan
bahasa C. Namun demikian, cara ini juga merupakan salah satu cara yang
cukup sulit bagi para pemrogram pemula, namun anda tidak perlu khawatir,
sebab dalam tutorial ini akan dijelaskan prinsip dasarnya.
- Beberapa
software membutuhkan kinerja yang tinggi dari segi kecepatan, hal ini bisa
dicapai dengan mudah jika kita menggunakan bahasa pemrograman yang
"sederhana" seperti C. Penulis sendiri telah membuat beberapa
software dalam dua versi, yaitu C "murni" dan C++ , kemudian
membandingkan kinerjanya, ternyata software yang diimplementasikan dengan
C memiliki kinerja yang lebih tinggi.
- Kelemahan
dari bahasa C yang penulis ketahui sampai saat ini adalah dari segi
kompleksitas pemeliharaan dan pengembangan software yang kita buat, jika
software tersebut sudah cukup kompleks. Sebagai contoh, software ExploChip
pada artikel Tutorial Membuat Patch... dibuat dengan C++, C dan Assembly,
namun C++ merupakan bahasa yang terbanyak digunakan untuk memudahkan
pemeliharaan dan pengembangan.
Pengenalan Sintaks Bahasa C
Sintaks adalah suatu bentuk dasar (biasanya kata) yang dapat
dipahami dan diolah oleh compiler. Pada bagian ini akan di bahas beberapa
sintaks yang umum digunakan dalam bahasa C, selain itu akan dijelaskan
bagaimana cara kerja compiler C secara umum. Sebelum melangkah lebih jauh,
perlu anda ketahui bahwa C adalah bahasa pemrograman yang case sensitive,
sehingga var, Var, dan VAR adalah tiga hal yang berbeda pada bahasa C.
Preprocessor dan Macro
Preprocessor3 adalah bagian dari sebuah
software development tool4 untuk bahasa C yang
bertugas untuk melakukan pengolahan source code sebelum diberikan kepada
compiler untuk diolah lebih lanjut. Preprocessor pada dasarnya menerjemahkan
source code yang kita buat ke bentuk yang dapat dikenali oleh compiler. Dalam
bahasa C, ada beberapa keyword5 yang
sebenarnya tidak dikenali oleh compiler, umumnya keyword ini diawali dengan #,
misalnya #macro,
#define
, #include
,
#pragma dan lain-lain, keyword inilah yang diolah oleh preprocessor.
Preprocessor merupakan salah satu bagian Software Development Tool yang
tergantung kepada vendor yang membuat tool tersebut, namun demikian, kita akan
membahas beberapa keyword yang umum diolah oleh preprocessor (telah di
standarisasi). Keyword yang diolah oleh preprocessor antara lain:
Catatan:
3 Preprocessor juga ada dalam bahasa lain, tetapi yang kita maksud di sini adalah preprocessor untuk bahasa C.
4 Software development Tool misalnya Turbo C, Visual C++, Borland C++ Builder, GNU C dan lain-lain yang dapat mengolah source code C.
5 Kata-kata yang mempunyai arti khusus dan digunakan secara internal oleh compiler.
3 Preprocessor juga ada dalam bahasa lain, tetapi yang kita maksud di sini adalah preprocessor untuk bahasa C.
4 Software development Tool misalnya Turbo C, Visual C++, Borland C++ Builder, GNU C dan lain-lain yang dapat mengolah source code C.
5 Kata-kata yang mempunyai arti khusus dan digunakan secara internal oleh compiler.
#include
,
keyword ini membuat kita seakan-akan telah mengetik isi dari file yang
dicantumkan sesudah keyword tersebut. Misalnya: #include
< stdio.h >
akan membuat preprocessor mengekspansikan file stdio.h
pada tempat keyword #include
tadi
diketikkan. #include
mempunyai dua macam
bentuk yaitu #include
<...>
dan #include
"..."
,
titik-titik tersebut adalah nama file. #include
<...>
akan
membuat preprocessor mencari file yang namanya dicantumkan di dalam kurung pada
direktori- direktori yang telah didefinisikan oleh software development tool
yang kita gunakan, misalnya pada direktory INC, INCLUDE
, dan
lain-lain. #include
"..."
akan
membuat preprocessor mencari file yang namanya dicantumkan di dalam tanda petik
ganda pada direktori file yang memiliki keyword #include
tersebut.
Misalnya anda mengerjakan file test.c yang ada pada direktori bernama test, dan
anda mengetikkan #include
"test.h"
, maka
preprocessor akan mencari file test.h pada direktori test.#define,
keyword
ini mempunyai format: #define
identifier
token-string
opt
.
Identifier adalah nama sebuah konstanta yang akan kita gunakan dalam program
kita, dan token-string
adalah
nilai dari identifier tersebut (nilai ini harus dapat dikenali oleh
compiler), token-string
dapat
merupakan sebuah ekspresi6. Preprocessor akan mengganti setiap kemunculan
identifier dengan nilai pada token-string
.
Jika token-string
dikosongkan,
maka identifier tadi akan hilang dari source code program kita (pada
baris-baris selanjutnya, identifier menjadi tidak dikenali sebab tidak memiliki
nilai lagi). Contoh: #define
a
0xff
akan membuat setiap kemunculan a dalam program, misalnya Function1(a)
diganti
dengan 0xff
(255
desimal), dan jika sesudah baris Function1(a) ada baris #define
a
, maka a sudah tidak akan dikenali lagi pada bagian selanjutnya. Dengan
demikian penggunaan a pada baris-baris selanjutnya adalah ilegal (compiler akan
memberikan pesan kesalahan saat program di buat/ di-compile). Jika pada #define
identifier token-string
opt
, token-string
merupakan
sebuah ekspresi, maka identifier tersebut disebut sebagai makro. Makro akan
diolah preprocessor, setiap kemunculan identifier
pada
source code yang akan diganti dengan ekspresi token-string
(jika
baris source code tsb tidak mengandung #
sebagai
karakter pertamanya), ekspresi ini kemudian diolah oleh compiler.
Catatan:
6 Ekspresi adalah sekumpulan operator (misalnya +, -, dll) dan operand (variabel yang dikenai operasi) yang mengerjakan salah satu kombinasi aktivitas berikut: Menghitung nilai, memindahkan nilai ke dalam suatu objek atau fungsi (fungsi akan dijelaskan lebih lanjut), atau menghasilkan efek samping (misalnya membuat sebuah baris program dieksekusi atau tidak).
6 Ekspresi adalah sekumpulan operator (misalnya +, -, dll) dan operand (variabel yang dikenai operasi) yang mengerjakan salah satu kombinasi aktivitas berikut: Menghitung nilai, memindahkan nilai ke dalam suatu objek atau fungsi (fungsi akan dijelaskan lebih lanjut), atau menghasilkan efek samping (misalnya membuat sebuah baris program dieksekusi atau tidak).
Contoh:
makro
makro dapat mempunyai parameter(nilai input). Berikut ini contohnya:
makro
#define a ((c)*(d))
akan
mengganti setiap kemunculan a dengan nilai hasil perkalian variabel c dan d.
Tanda kurung yang banyak untuk memastikan bahwa makro kita dieksekusi sesuai
dengan yang kita inginkan, sebab ada yang disebut dengan operator precedence,
yaitu urutan pengerjaan operator jika berbagai operator muncul dalam sebuah pernyataan.
Misalnya: a*b+c
, pada ekspresi
ini, yang akan diolah terlebih dulu adalah perkalian a dan b, kemudian hasilnya
dijumlahkan dengan c.makro dapat mempunyai parameter(nilai input). Berikut ini contohnya:
#define
kali(a,b) ((a)*(b))
....
int y = 20;
int z = 90;
int x = kali(y,z);
Pada source code di atas, int adalah tipe data variabel, kita
akan belajar lebih lanjut tentang hal ini. Saat preprocessor menemukan
ekspresi
kali(y,z)
,
maka nilai y dan z dari baris-baris sebelumnya akan menggantikan y dan z
pada kali(y,z)
,
kemudian kali(y,z)
berubah
menjadi ((y)*(z))
sehingga
diperoleh 20x90 = 1800
,
kemudian hasil ini dipindahkan ke x (tanda = artinya pindahkan nilai di sebelah
kanan tanda ini ke variabel yang ada di sebelah kiri tanda ini).#if
, keyword ini digunakan
untuk menentukan pengolahan baris-baris source code sesudahnya, sampai dengan
keyword #endif
. Formatnya adalah
: #if
expression , expression
adalah sebuah ekspresi yang valid (dapat diolah oleh compiler). Jika ekspresi
tersebut benar maka baris-baris source code sesudah #if
akan
diolah dan sebaliknya jika ekspresi tersebut bernilai salah. Keyword ini harus
digunakan bersama dengan keyword #endif
untuk
menandakan batas penggunaan keyword tersebut dalam source code. Contoh:#define TEST 2
#if (TEST > 0)
...
baris source code;
#endif
Pada potongan program diatas, baris source code akan diolah sebab ekspresi
TEST
> 0
adalah benar.#ifdef
,
keyword ini penggunaannya sama dengan #if
.
Formatnya: #ifdef
identifier
,
identifier adalah sebuah konstanta. Jika identifier telah didefinisikan
sebelumnya (dengan keyword #define
) maka
baris-baris source code sesudah #ifdef
akan
diolah oleh kompiler, demikian pula sebaliknya. Keyword ini harus digunakan
bersama dengan keyword #endif
untuk
menandakan batas penggunaan keyword tersebut dalam source code#ifndef
,
keyword ini mempunyai format yang sama dengan #ifdef
, tetapi
cara kerjanya adalah kebalikan dari #ifdef
,
sehingga jika baris- baris program sesudahnya justru diolah jika identifier
tidak didefinisikan sebelumnya. Keyword ini harus digunakan bersama dengan
keyword #endif
untuk menandakan
batas penggunaan keyword tersebut dalam source code#endif
,
keyword ini sebagai pembatas untuk menadakan bagian akhir dari source code yang
akan dikenai efek jika keyword #if
, #ifdef
dan #ifndef
dievaluasi.#undef
, adalah
keyword untuk menonaktifkan identifier yang telah didefinisikan dengan #define
,
efeknya sama dengan #define
identifier
. Dengan
demikian kita dapat mendefinisikan kembali identifier tadi setelah #undef.#else
, keyword
ini digunakan di antara keyword #if
, #ifdef
, #ifndef
dengan
keyword #endif
. Jika ekspresi pada
keyword #if
, #ifdef
, #ifndef
benar
maka source code sesudah #else, tidak akan dieksekusi,demikian pula
sebaliknya.Contoh:#define
TEST 0
#if (TEST > 0)
...
baris source code1;
#else
...
baris source code2;
#endif
Pada potongan program
diatas, baris source code2;
akan
diolah sebab ekspresi TEST > 0
adalah
salah.
Compiler
Compiler adalah bagian dari Software Development Tool yang kita
gunakan, yang bertugas menerjemahkan source code yang telah diolah oleh
prepocessor menjadi bahasa assembly yang selanjutnya akan diolah oleh assembler
untuk dijadikan machine code yang dapat dieksekusi. Bahasa C dikatakan sebagai
bahasa pemrograman yang portable, sebab dengan memberikan switch tertentu
kepada compiler C pada saat kompilasi dilakukan, compiler akan menghasilkan
file assembly yang berbeda, sesuai dengan tipe arsitektur yang kita pilih
(dengan menggunakan switch tersebut), namun kemampuan ini juga tergantung kepada
Software development Tool yang kita gunakan.
Linker
Linker adalah bagian dari Software development Tool yang
bertugas mengubah format machine code yang dihasilkan oleh assembler menjadi
instruksi yang dapat dieksekusi. Jadi sebenarnya assembler tidak menghasilkan
sebuah program yang dapat dieksekusi. Sebuah file yang dapat dieksekusi
mempunyai format header tertentu, dan dari satu sistem operasi ke sistem
operasi yang lain formatnya berbeda-beda. Linker juga mempunyai fungsi lain,
yaitu menyatukan komponen-komponen dari software yang kita buat ke dalam file
executable yang nantinya akan dihasilkan setelah melalui linker, misalnya
software tersebut mempunyai komponen eksternal seperti resource pada windows,
resource sebenarnya bukan bagian dari program yang dieksekusi tetapi ikut
disertakan dalam program karena dibutuhkan , contoh resource: ikon yang akan
ditampilkan pada sebuah program. Komponen lain yang kadang-kadang disatukan
oleh linker adalah dll (dynamic link library) yang disatukan secara "static"
ke dalam file executable, selain itu linker juga menyatukan file objek (obj)
diluar file objek yang kita hasilkan jika dibutuhkan oleh program kita ke dalam
executable yang akan dibentuk.
Pernyataan
dalam bahasa C adalah sebuah baris program yang dapat diproses
oleh compiler. Pernyataan diakhiri dengan tanda
Sekelompok pernyataan yang disatukan dalam sebuah kurung kurawal (kadang di sebut sebagai block of statement atau blok pernyataan ) juga diperlakukan seperti sebuah pernyataan biasa, hal ini terutama berguna saat anda akan mengatur eksekusi sekelompok pernyataan dalam sebuah percabangan seperti contoh di bawah ini:
;
(titik-koma).
Setiap pernyataan dapat berisi beberapa ekspresi, operator maupun operand.
Contoh: return;
Sekelompok pernyataan yang disatukan dalam sebuah kurung kurawal (kadang di sebut sebagai block of statement atau blok pernyataan ) juga diperlakukan seperti sebuah pernyataan biasa, hal ini terutama berguna saat anda akan mengatur eksekusi sekelompok pernyataan dalam sebuah percabangan seperti contoh di bawah ini:
if (a > b)
{
pernyataan 1;
pernyataan 2;
pernyataan 3;
}
jika ekspresi didalam
kurung sesudah if ( ekspresi a > b)
bernilai
benar maka seluruh pernyataan di dalam kurung kurawal akan dieksekusi.
Sebenarnya keyword if hanya dapat mengeksekusi satu pernyataan
sesudah ekspresi yang diuji olehnya ( pada contoh di atas ekspresi a
> b
), namun dengan adanya kurung kurawal, pernyataan 1 s/d
pernyataan 3 seolah-olah dianggap satu pernyataan saja oleh
compiler yang kita gunakan.
Variabel
adalah sebuah simbol yang mewakili sebuah alamat di memory yang
nilainya dapat dimanipulasi melalui nama tersebut dan mempunyai ukuran
tertentu. Ukuran ini disebut tipe data. Tipe data yang berbeda kemungkinan
mempunyai ukuran yang berbeda. Sintaks untuk mendeklarasikan (menyatakan
pertama kali adanya sebuah variabel) adalah:
tipe-data NamaVariabel
Contoh:
int variabel1;
Berikut ini adalah tipe data dan ukurannya.
Tipe data |
Ukuran (byte) |
Contoh |
bool |
1 |
bool a = true ; bool b = false |
int, unsigned int |
4 |
int a = -255 ; unsigned int b =
10 |
char, unsigned char |
1 |
char a = -1 ; unsigned char b =
1 |
long, unsigned long |
4 |
long c = 0xFF ; unsigned long d
= 0xFFC |
short, unsigned short |
2 |
short e = 0xFFF ; unsigned
short f = 067 |
float |
4 |
float g = 0.001 |
double |
8 |
double h = 1.02e8 |
long double |
8 |
long double h = 2.42e10 |
Variabel bertipe
variabel char dengan deklarasi seperti di atas sering di sebut string, sebab menyimpan sekumpulan karakter, nilai variabel ini tidak begitu penting sebab yang kita simpan bukan merupakan nilai yang akan dioperasikan.
Variabel memiliki apa yang disebut variable scope. Variable scope adalah daerah di dalam source code tempat sebuah variabel masih dikenali/terlihat oleh compiler. Misalnya seperti ini: anda mendeklarasikan sebuah variabel di dalam sebuah fungsi di luar fungsi
bool
hanya
mempunyai dua nilai yaitu true atau false, jadi
anda hanya dapat mengisinya dengan nilai ini. Perlu diperhatikan bahwa variabel
bertipe bool
dianggap bernilai
false jika nilainya 0 , dan benar jika nilainya >=
1
. Mungkin anda bertanya, mengapa untuk dua alternatif saja kita
menggunakan 1 byte (8 bit) padahal untuk 2 alternatif hanya dibutuhkan 1 bit,
hal ini disebabkan oleh arsitektur kebanyakan microprocessor saat ini adalah
"byte addessable", maksudnya nilai variabel terkecil yang dapat
ditangani oleh microprocessor tersebut adalah byte. Variabel bertipe int
(integer/bilangan
bulat) dan unsigned int
(unsigned
integer/bilangan bulat positif) hanya dapat diisi dengan bilangan yang bernilai
bulat (tidak ada nilai di belakang koma atau pecahan) termasuk 0. Pada sistem
operasi windows variabel dengan tipe ini memiliki nilai 32 bit (4 byte),
sehingga untuk unsigned int nilai maksimumnya adalah 232 -1
(karena ada 0), int nilainya berada pada kisaran -(216) sampai
216-1 (karena ada 0). Untuk variabel yang tipenya lain tentunya
anda sudah dapat menghitung sendiri nilai kisarannya, karena semuanya analog
dengan tipe data int. Anda hanya perlu mengetahui jumlah bit yang digunakan
variabel tersebut dan untuk yang signed, nilai negatif yang paling kecilnya
adalah - (2(jumlah bit tipe data tsb/2)) dan nilai maksimum
positifnya adalah 2 (jumlah bit tipe data tsb/2)-1
(karena ada 0). Namun demikian, ada tiga tipe variabel yang tidak termasuk ke
dalam golongan yang memenuhi aturan ini, yaitu float,
double
dan long double
. Ketiga
tipe ini adalah tipe variabel floating point, yaitu variable yang
dinyatakan dalam mantissa dan eksponen. Mantissa
adalah faktor pengali, dan eksponen adalah bilangan berpangkat 10 yang
dikalikan dengan mantissa tersebut. Misalnya 1,045x10e5 , pada bilangan ini
mantissa adalah 1,045 sedangkan eksponennya adalah 10e5 (105). Pada
prakteknya variabel tipe floating point ditangani oleh bagian FPU (Floating
Point Unit/Math Coprocessor) pada microprocessor kita. Pada variabel floating
point anda dapat memasukan data dengan nilai pecahan yang dikalikan dengan
eksponesial, misalnya 1,5x1032.Tipe
data floating point nilai maksimum dan minimumnya tergantung pada Software
Development Tool yang kita gunakan, pada Visual C++ , kisarannya sebagai
berikut: float mempunyai nilai antara 10-308 s/d 10308, double
mempunyai nilai antara -1.79769313486231x10308 s/d
-4.94065645841247x10 -324 untuk bilangan
negatif, dan 4.94065645841247x10-324 s/d
1.79769313486231x10308 untuk bilangan positif, dan 0. Pada beberapa sistem long
double dan double mempunyai ukuran berbeda, tetapi pada Microsoft Visual C++,
keduanya adalah identik. Pada saat menentukan tipe data sebuah variabel yang
akan anda gunakan anda harus memperhatikan nilai maksimum atau minimum yang
dapat ditampung oleh tipe data tersebut agar tidak terjadi kesalahan
perhitungan, nilai dari variabel tersebut harus kurang dari atau sama dengan
nilai maksimum yang dapat ditampung oleh tipe data tersebut. Anda juga dapat
memasukkan bilangan bukan desimal(basis 10) ke dalam variabel yang bukan
floating point. Misalnya, anda dapat memasukkan nilai heksa desimal (basis 16)
seperti 0xFF
, bilangan octal (basis
8) seperti 0223
. Selain sifat ini,
variabel dengan tipe data char mempunyai sifat tersendiri, yaitu anda dapat
memasukkan sekumpulan ke dalam variabel tersebut, misalnya pada potongan source
code berikut:char message = "Ini adalah string"
variabel char dengan deklarasi seperti di atas sering di sebut string, sebab menyimpan sekumpulan karakter, nilai variabel ini tidak begitu penting sebab yang kita simpan bukan merupakan nilai yang akan dioperasikan.
Variabel memiliki apa yang disebut variable scope. Variable scope adalah daerah di dalam source code tempat sebuah variabel masih dikenali/terlihat oleh compiler. Misalnya seperti ini: anda mendeklarasikan sebuah variabel di dalam sebuah fungsi di luar fungsi
main(),
maka
variabel tersebut hanya memiliki scope pada fungsi itu saja, sebab di luar
fungsi tersebut variabel tersebut tidak akan dikenali oleh compiler. Variabel
seperti ini biasa disebut variabel lokal. Kasus kedua adalah variabel yang
dideklarasikan diluar semua fungsi, variabel seperti ini mempunyai scope
dikeseluruhan source code yang kita miliki. Variabel seperti ini biasa juga
disebut variabel global sebab variabel ini dikenali di dalam fungsi manapun
dalam program kita, termasuk fungsi main()
.
Implikasi dari adanya variabel global dan lokal adalah:- Anda
tidak dapat menggunakan nama variabel yang sama untuk sebuah variabel
global dan lokal sebab compiler akan menganggap variabel tersebut
dideklarasikan 2 kali dan hal ini tidak dibolehkan oleh compiler C.
- Anda
tidak dapat menggunakan variabel lokal di luar fungsi tempat variabel
tersebut dideklarasikan, sebab variabel tersebut tidak akan dikenali oleh
compiler.
Untuk memperjelas, akan diberikan contoh sebagai berikut:
Pada source code di atas,
#include <stdio.h>
#define UINT unsigned int
/* deklarasi fungsi kali */
UINT kali(UINT a, UINT b);
UINT var_test;
void main()
{
UINT faktor1 = 10;
UINT faktor2 = 20;
UINT hasil ;
hasil = kali(faktor1,faktor2);
printf("%d \n",hasil);
}
UINT kali(UINT a, UINT b)
{
UINT hasil = 30;
UINT c = a*b;
return c;
}
Pada source code di atas,
var_test
adalah
variabel global, sebab variabel ini dideklarasikan di luar semua fungsi.
Variabel faktor1
, faktor2
dan
hasil adalah variabel lokal pada fungsi main()
.
Variabel hasil
yang ada pada
fungsi kali adalah variabel lokal, yang berbeda dengan variabel hasil
yang
ada pada fungsi main()
sebab
scope kedua variabel tersebut adalah berbeda. Anda perlu memperhatikan hal
seperti ini saat anda membuat program, sebab jika anda dengan seenaknya memberi
nama pada variabel yang anda gunakan tanpa memperhatikan scope dari variabel
tersebut, bisa-bisa program anda tidak dapat di-compile.
Operator
Operator adalah karakter atau kumpulan karakter yang
digunakan untuk memanipulasi variabel. Karakter atau kumpulan karakter ini
dikenali secara spesifik oleh compiler sehingga variabel yang diubah-ubah
nilainya(operand) akan dikenai operasi sesuai dengan definisi operasi yang
dimiliki oleh operator tadi. Dalam bahasa C ada tiga golongan besar operator,
yaitu:
unary operator, operator ini hanya bekerja
pada satu operand. Unary operator antara lain:
Operator Unary |
Kegunaan |
- ~ ! |
Operator ini melakukan operasi negasi,
yaitu merubah nilai operand menjadi nilai yang berlawanan tanda. Disebut juga
Negation atau complement operator
|
++ |
Operator ini menaikkan nilai operand 1
satuan, disebut juga increment operator.
|
-- |
Operator ini menurunkan nilai operand 1
satuan, disebut juga decrement operator.
|
* |
Operator ini memberikan nilai yang
tersimpan pada alamat memory yang ditunjuk oleh operand, disebut juga
indirection operator. Biasanya digunakan dalam operasi dengan pointer (akan
dijelaskan lebih lanjut)
|
& |
Operator ini memberikan alamat memory
operand. Biasanya digunakan dalam operasi dengan pointer (akan dijelaskan
lebih lanjut). Disebut juga address of operator.
|
sizeof (operand ) |
Operator ini memberikan ukuran memory yang
digunakan operand dalam byte.
operand adalah operand yang ukurannya akan dicari. |
binary operator, operator ini bekerja pada dua operand sekaligus. Operator binary antara lain:
Operator Binary |
Kegunaan |
Operator Matematis |
|
+ |
Operator ini menjumlahkan nilai operand di
sebelah kiri dengan nilai operand di sebeleh kanan
|
- |
Operator ini mengurangi nilai operand di
sebelah kiri dengan nilai operand di sebeleh kanan
|
* |
Operator ini mengalikan nilai operand
sebelah kiri dengan nilai operand di sebelah kanan
|
/ |
Operator ini membagi nilai operand sebelah
kiri dengan nilai operand di sebelah kanan
|
% |
Operator ini disebut juga modulo operator.
Nilai Operand di sebelah kiri akan dibagi dengan nilai operand di sebelah
kanan, kemudian hasil operasinya adalah sisa dari pembagian tersebut.
Misalnya:
3%2 akan menghasilkan 1 . |
Operator Logic (Logical
Operator) |
|
&& |
Operator ini disebut operator logical and.
Cara kerjanya adalah mengetes ekspresi disebelah kanan dan kirinya, jika
keduanya benar maka nilai yang dihasilkan 1 (true), jika tidak maka nilai
yang dihasilkan adalah 0 (false)
|
|| |
Operator ini disebut operator logical or.
Cara kerjanya adalah mengetes ekspresi disebelah kanan dan kirinya, jika
salah satunya benar maka nilai yang dihasilkan 1, jika tidak maka nilai yang
dihasilkan adalah 0
|
Operator Operasi Bit (Bitwise
Operator) |
|
& |
Operator disebut juga operator bitwise
and. Cara kerjanya adalah melakukan operasi
AND
(&) pada setiap bit kedua operand.
misalnya: 0xA & 0xC akan menghasilkan 0x8 , perhatikan bahwa 0xA =
1010 biner dan 0xC =
1100 biner . Sehingga 1010
& 1100 = 1000 biner atau 0x8 heksadesimal sebab 0&1
= 0 , 1&0 = 0, 0&0 = 0, 1&1 = 1 . |
| |
Operator ini disebut juga operator bitwise
or. Cara kerjanya adalah melakukan operasi
OR
(|) pada setiap bit kedua operand.
misalnya: 0xA | 0xC akan menghasilkan 0xE , perhatikan bahwa 0xA =
1010 biner dan 0xC
= 1100 biner . Sehingga 1010 |
1100 = 1110 biner atau 0xE
heksadesimal sebab 0|1
= 1 , 1|0 = 1, 0|0 = 0, 1|1 = 1. |
^ |
Operator ini disebut juga operator bitwise
xor. Cara kerjanya adalah melakukan operasi
XOR
(^) pada setiap bit kedua operand.
misalnya: 0xA ^ 0xC akan menghasilkan 0x6 , perhatikan bahwa 0xA =
1010 biner dan 0xC =
1100 biner . Sehingga 1010 |
1100 = 0110 biner atau 0x6 heksadesimal sebab 0^1 = 1
, 1^0 = 1, 0^0 = 0, 1^1 = 0. |
Operator Penggeseran Bit (Bit
Shift Operator) |
|
>> |
Operator ini disebut operator geser kanan
(right shift). Cara kerjanya adalah melakukan penggeseran bit ke kanan pada
nilai operand sejumlah bit yang ada di sebelah kanan operator ini.
Misalnya:
0xA >> 3 akan menghasilkan 0x1 , perhatikan bahwa 0xA =
1010 biner , sehingga dengan menggeser bitnya 1 kali ke kanan
diperoleh 101 biner , dan jika digeser 3 kali akan diperoleh 1 biner atau 0x1 heksadesimal |
<< |
Operator ini disebut operator geser kiri
(left shift). Cara kerjanya adalah melakukan penggeseran bit ke kiri pada
nilai operand sejumlah bit yang ada di sebelah kanan operator ini.
Misalnya:
0xA << 3 akan menghasilkan 0x50 , perhatikan bahwa 0xA =
1010 biner , sehingga dengan menggeser bitnya 1 kali ke kiri diperoleh 10100
biner , dan jika digeser 3 kali akan
diperoleh 1010000 biner atau 0x50 heksadesimal . |
Operator Perbandingan
(Relational Operator) |
|
== |
Operator ini bekerja dengan membandingkan
nilai operand di sebelah kanan dan sebelah kiri-nya, jika keduanya identik maka
hasilnya adalah 1 (true). Misalnya:
A = 2; B = 2; if(A == B) ... code1; else ... code2 ; pada source code ini ...code1 akan di eksekusi, sebab A==B bernilai 1 (true). |
!= |
Operator ini bekerja dengan membandingkan
nilai operand di sebelah kanan dan sebelah kiri-nya, jika keduanya berbeda
maka hasilnya adalah 1 (true). Misalnya:
A = 2; B = 2; if(A != B) ... code1; else ... code2 ; pada source code ini ...code2 akan di eksekusi, sebab A!=B bernilai 0 (false). |
<= |
Operator ini bekerja dengan membandingkan
nilai operand di sebelah kanan dan sebelah kiri-nya, jika operand di kiri
bernilai kurang dari atau sama dengan operand di sebelah kanan maka hasilnya
adalah 1 (true). Misalnya:
A = 2; B = 4; if(A <= B) ... code1; else ... code2 ; pada source code ini ...code1 akan di eksekusi, sebab A<=B bernilai 1 (true). |
> |
Operator ini bekerja dengan membandingkan
nilai operand di sebelah kanan dan sebelah kiri-nya, jika operand di kiri
bernilai lebih dari operand di sebelah kanan maka hasilnya adalah 1 (true). Misalnya:
A = 3; B = 1; if(A > B) ... code1; else ... code2 ; pada source code ini ...code1 akan di eksekusi, sebab A
> B bernilai 1 (true). |
>= |
Operator ini bekerja dengan membandingkan
nilai operand di sebelah kanan dan sebelah kiri-nya, jika operand di kiri
bernilai lebih dari atau sama dengan operand di sebelah kanan maka hasilnya
adalah 1 (true). Misalnya:
A = 4; B = 2; if(A >= B) ... code1; else ... code2 ; pada source code ini ...code1 akan di eksekusi, sebab A>=B bernilai 1 (true). |
< |
Operator ini bekerja dengan membandingkan
nilai operand di sebelah kanan dan sebelah kiri-nya, jika operand di kiri
bernilai kurang dari operand di sebelah kanan maka hasilnya adalah 1 (true).
Misalnya:
A = 2; B = 4; if(A < B) ... code1; else ... code2 ; pada source code ini ...code1 akan di eksekusi, sebab A
< B bernilai 1 (true). |
ternary operator, operator ini bekerja pada tiga
operand sekaligus.
Operator |
Kegunaan |
Ekspresi1 ? Ekspresi2 :
Ekspresi3 |
Cara kerja dari operator ini adalah
mengecek nilai
ekspresi1 , jika nilainya benar, maka yang akan dievaluasi adalah ekspresi2 , jika salah maka yang akan dievaluasi adalah ekspresi3 . Berikut ini contoh untuk memperjelas:int z; int x = 2; int y = 3; z = (x > y) ? x : y ; pada source code di atas, nilai z akan sama dengan y, sebab ekspresi1 nilainya salah, sehingga yang akan dievaluasi
adalah ekspresi3 . |
Percabangan
Percabangan (Control Flow) adalah teknik yang digunakan untuk
mengalihkan eksekusi program saat suatu ekspresi yang diuji bernilai benar atau
salah. Pertama, akan dibahas percabangan dengan if, else if, dan else. Bentuk
percabangan ini adalah yang paling sederhana. Format penggunaannya adalah:
pada sourcecode ini, pertama-tama, if akan mengecek
Selanjutnya adalah percabangan dengan
pada source code diatas,
if (ekspresi1)
...
sourcecode1;
else if (ekspresi2)
...
sourcecode2;
else
...
sourcecode3;
pada sourcecode ini, pertama-tama, if akan mengecek
ekspresi1
,
jika benar maka sourcecode1;
akan
dieksekusi, jika tidak, maka eksekusi program berpindah ke else
if (ekspresi2), else if
akan mengecek ekspresi2
,
jika ekspresi2
benar
maka sourcecode2
akan
dieksekusi, jika salah maka eksekusi program berpindah ke sourcecode3.
Pada
format di atas, else if
sebenarnya
opsional (boleh ada boleh juga tidak), jika anda hanya memiliki dua alternatif
"jawaban" maka bagian else if
tidak
perlu digunakan.Selanjutnya adalah percabangan dengan
switch
. switch
digunakan
untuk percabangan dengan banyak alternatif pilihan, sebenarnya hal ini juga
dapat dilakukan dengan if , else if ,
else
, tetapi switch lebih efisien dan lebih mudah jika kita sudah
menguasainya. Format penggunaannya adalah:switch (ekspresi)
{case (ekspresi1):
...
sourcecode1;
break;
case (ekspresi2):
...
sourcecode2;
break;
case (ekspresi3):
...
sourcecode3;
break;
default:
...
sourcecode4;
break;
}
pada source code diatas,
ekspresi
biasanya
merupakan sebuah variabel yang dapat memiliki banyak macam nilai (misalnya
variabel bertipe int), nilai ekspresi
akan
dicocokkan (matching) dengan nilai ekspresi1
, ekspresi2
dan ekspresi3
, jika
ternyata ekspresi
bernilai sama
dengan salah satunya maka source code dibawahnya akan dieksekusi,
misalnya: ekspresi
bernilai
sama dengan ekspresi1
maka source
code1
akan dieksekusi. Jika ternyata tidak ada nilai yang sama
dengan ekspresi
maka yng
dieksekusi adalah source code sesudah default
. default
dan
pernyataan sesudahnya adalah opsional (dapat digunakan, dan dapat tidak
digunakan). Satu hal lagi, setelah setiap alternatif pernyataan source code,
anda harus menggunakan keyword break;
,
tujuannya adalah agar eksekusi program keluar dari percabangan switch
sehingga
source code yang ada di bawahnya tidak dieksekusi. Misalnya: anda lupa
memberikan break; setelah sourcecode2
, maka
saat ekspresi
bernilai
sama dengan ekspresi2
eksekusi
program tidak akan keluar dari percabangan switch
setelah sourcecode2
tetapi
akan terus melanjutkan eksekusi ke sourcecode3
,
setelah keyword break
(sesudah sourcecode3
)
barulah eksekusi keluar dari percabangan dengan switch ini. Hal ini tentunya
bukan hal yang anda harapkan, jadi teliti lah saat menggunakan switch. Masih
ada bentuk percabangan lain dalam C, tetapi tidak akan di bahas di sini sebab
jarang digunakan dan dengan kedua teknik percabangan yang ada di atas sudah
cukup untuk sebagian besar kasus yang kita hadapi sehari-hari.
Perulangan
Perulangan adalah teknik pemrograman yang digunakan
untuk mengatasi pernyataan program yang harus dikerjakan secara berulang-ulang.
Perulangan dalam C dapat diimplementasikan dengan beberapa keyword, yaitu
pada source code di atas
pada source code di atas,
Perulangan dengan while mempunyai format sebagai berikut:
pada source code di atas, pertama-tama keyword
for,
do .. while , while
. Ketiga keyword ini lah yang
paling sering digunakan. Perulangan menggunakan for
mempunyai
format sebagai berikut.for( ekspresi1 ; ekspresi2 ;ekspresi3 )
{
...
source_code_ulang;
}
pada source code di atas
ekspresi1
adalah
ekspresi yang akan dievaluasi pertama kali , kemudian ekspresi2
dievaluasi,
jika nilainya benar maka source_code_ulang;
dieksekusi,
setelah itu ekspresi3
akan
dieksekusi, kemudian jalannya program kembali lagi ke pernyataan for dan ekspresi2
kembali
dievaluasi (ekspresi1
tidak
lagi dieksekusi), jika benar maka source_code_ulang;
dieksekusi,
setelah itu ekspresi3
akan
dieksekusi, kemudian jalannya program kembali lagi ke pernyataan for
,
hal ini dilakukan berulang-ulang selama ekspresi2
masih
bernilai benar. Berikut contoh potongan programnya:for(int i = 0; i < 4 : i++)
{
printf("loop
masih dieksekusi");
}
pada source code di atas,
ekspresi1
adalah
int i = 0 , ekspresi ini mendeklarasikan sebuah variabel bertipe int dan
memberikan variabel tersebut nilai 0. Ekspresi ini hanya satu kali dieksekusi,
yaitu saat keyword for pertama kali dipanggil. Kemudian nilai i dievaluasi
apakah kurang dari 4 (ekspresi2
adalah i
< 4
), saat pertama kali dieksekusi ekspresi ini bernilai benar
sebab i < 4
, kemudian kita memanggil
fungsi printf("..")
untuk
menampilkan tulisan ke layar, setelah itu nilai i ini dinaikkan 1 satuan
menjadi 2 pada ekspresi3
(ekspresi3
adalah i++
),
langkah-langkah ini diulang sampai nilai i menjadi 4. Saat i
= 3,
pengulangan terakhir akan membuat nilai i menjadi 4
(sebab ekspresi3
di
eksekusi), jalannya program kembali ke keyword for
,
kemudian ekspresi2
dieksekusi,
sekarang ekspresi tersebut bernilai salah sebab i = 4 , sehingga eksekusi
program akan keluar dari perulangan ini, dan melanjutkan ke source code sesudah
kurung kurawal penutup pada contoh di atas.Perulangan dengan while mempunyai format sebagai berikut:
while(
test_expression )
{
...
source_code;
}
pada source code di atas, pertama-tama keyword
while
dipanggil,
kemudian test_expression dievaluasi, jika nilainya benar, maka source_code
akan
dieksekusi sampai test_expression
bernilai
salah. Jika test_expression
bernilai
salah maka jalannya program akan melewati perulangan ini begitu saja
(melanjutkan ke source code sesudah kurung kurawal penutup pada contoh di
atas). Berikut ini source code yang menggunakan while dan mengerjakan hal yang
sama dengan source code untuk perulangan menggunakan for.int i = 0;
while(i < 4)
{
i++;
printf("loop masih dieksekusi");
}
Perulangan dengan do...while
, pada
dasarnya sama dengan perulangan dengan while, hanya saja pernyataan yang ada di
antara keyword do dan while akan dieksekusi minimal satu kali, sebab pengetesan
ekspresi dilakukan setelah peryataan tersebut dieksekusi. Berikut ini source
code yang menggunakan do...while
dan
mengerjakan hal yang sama dengan source code untuk perulangan menggunakan
for. int i = 0;
do
{
printf("loop masih dieksekusi");
i++;
}
while(i < 4)
Obrolan
bebas:
"Sebelum anda bosan, penulis ingin memberitahukan bahwa bahasa C diciptakan oleh seorang hacker bernama Dennis Ritchie yang bekerja di Bell Telephone Laboratories pada 1972. Compiler C yang mendukung paling banyak arsitektur komputer saat ini adalah GNU C yang terdapat di banyak varian sistem operasi UNIX, termasuk Linux. Ada beberapa implementasi bahasa C yang mungkin akan membuat anda tertarik, yaitu: kernel dari sistem operasi Linux, karena source code-nya free, anda dan juga penulis bisa belajar banyak dari sana, kemudian, saat ini sudah ada beberapa cellphone yang dapat diisi dengan program aplikasi yang dibuat dengan bahasa C, dan yang terpenting adalah 'kekuatan' dari software apapun yang anda buat hanya dibatasi oleh imajinasi anda :)."
"Sebelum anda bosan, penulis ingin memberitahukan bahwa bahasa C diciptakan oleh seorang hacker bernama Dennis Ritchie yang bekerja di Bell Telephone Laboratories pada 1972. Compiler C yang mendukung paling banyak arsitektur komputer saat ini adalah GNU C yang terdapat di banyak varian sistem operasi UNIX, termasuk Linux. Ada beberapa implementasi bahasa C yang mungkin akan membuat anda tertarik, yaitu: kernel dari sistem operasi Linux, karena source code-nya free, anda dan juga penulis bisa belajar banyak dari sana, kemudian, saat ini sudah ada beberapa cellphone yang dapat diisi dengan program aplikasi yang dibuat dengan bahasa C, dan yang terpenting adalah 'kekuatan' dari software apapun yang anda buat hanya dibatasi oleh imajinasi anda :)."
Fungsi dan Struktur Program C
Komponen utama bahasa C adalah sebuah bentuk yang dikenal
sebagai fungsi. Program C yang paling sederhana sekalipun harus mempunyai
minimal sebuah fungsi, yaitu fungsi
Format dasar "deklarasi" sebuah fungsi adalah:
main()
. Fungsi
adalah sekelompok perintah (bahasa C) yang dapat dipanggil untuk mengerjakan
sebuah pekerjaan tertentu. Format dasar "definisi" sebuah fungsi
adalah:return_type function_name(param1_type parameter1,
param2_type parameter2, ...)
{
...
source_codes ;
return hasil_perhitungan;
}
Format dasar "deklarasi" sebuah fungsi adalah:
return_type function_name(param1_type parameter1,
param2_type parameter2, ...);
Catatan:
Sebenarnya ada beberapa hal yang perlu anda perhatikan pada bentuk umum di atas, tanda
fungsi ini dapat menerima 2 atau lebih parameter, dan jumlah parameter tersebut terserah anda saat memanggil fungsi tersebut, asal lebih dari atau sama dengan 2. Dalam tutorial ini kita tidak akan mempelajari fungsi seperti ini, kita hanya akan mempelajari fungsi dengan jumlah parameter yang pasti.
Sebenarnya ada beberapa hal yang perlu anda perhatikan pada bentuk umum di atas, tanda
...
pada return_type
function_name(param1_type parameter1, param2_type parameter2, ...)
maksudnya
adalah sebuah fungsi dapat mempunyai lebih dari dua parameter, tergantung
bagaimana anda mendeklarasikan dan mendefinisikan sebuah fungsi. Anda perlu
berhati-hati dengan sintaks ini, sebab dalam bahasa C sebuah fungsi yang
dideklarasikan atau didefinisikan dengan ...
sebagai
parameter terakhirnya berarti fungsi tersebut dapat memiliki jumlah parameter
yang "tidak terbatas", misalnya fungsi yang dideklarasikan sebagai
berikut:void test(int a, char b , ...);
fungsi ini dapat menerima 2 atau lebih parameter, dan jumlah parameter tersebut terserah anda saat memanggil fungsi tersebut, asal lebih dari atau sama dengan 2. Dalam tutorial ini kita tidak akan mempelajari fungsi seperti ini, kita hanya akan mempelajari fungsi dengan jumlah parameter yang pasti.
return_type
adalah tipe data dari hasil_perhitungan
. hasil_perhitungan
dalam literatur biasa disebut "return value". Sebuah fungsi dapat mengembalikan
(menghasilkan) sebuah nilai (dalam fungsi di atas nilai yang dikembalikan
adalah hasil_perhitungan
), namun dapat
juga tidak mengembalikan apa-apa. Jika sebuah fungsi tidak mengembalikan nilai
apa pun maka return_type
harus
bertipe void dan fungsi tersebut tidak boleh mengandung keyword return
sebuah_nilai
, dengan sebuah_nilai
adalah nilai tertentu, sekalipun nilai itu
adalah 0. parameter1
dan parameter2
adalah nilai input yang akan diolah oleh fungsi. function_name
adalah nama dari fungsi yang kita definisikan. param1_type
dan param2_type
adalah tipe data dari parameter1
dan parameter2
. Sebuah fungsi juga boleh tidak mempunyai parameter sama
sekali, fungsi tanpa parameter adalah valid bagi compiler C. Untuk membuat sebuah
program C yang menggunakan fungsi (selain fungsi main()
)dapat berjalan dengan baik, anda harus menempatkan
"definisi" fungsi tersebut sebelum fungsi main()
atau jika anda tidak ingin menaruh definisi fungsi
tersebut sebelum main()
maka
letakkan "deklarasi" fungsi tersebut sebelum main()
seperti pada contoh yang akan di bahas. Hal ini
diperlukan sebab fungsi yang anda buat kemungkinan tidak akan dikenali jika
anda tidak mendeklarasikannya atau mendefinisikannya sebelum fungsi main()
. Selanjutnya kita akan membedah sebuah program C yang sangat
sederhana untuk memahami konsep di atas.#include < stdio.h >
#define UINT unsigned int
/* deklarasi fungsi kali */
UINT kali(UINT a, UINT b);
void main()
{
UINT faktor1;
UINT faktor2;
UINT hasil ;
printf("Ketikkan nilai untuk faktor1 ");
scanf("%d", &faktor1);
if(faktor1 >= 0 && faktor1 <= 9 )
{
printf("Ketikkan nilai untuk faktor2 ");
scanf("%d", &faktor2);
if(faktor2 >= 0 && faktor2 <= 9)
{
printf("faktor1 = %d ; faktor2 = %d \n", faktor1,
faktor2);
hasil = kali(faktor1, faktor2);
printf("Hasil perkalian keduanya adalah %d\n", hasil);
}
else
{
printf("Anda mengetikkan karakter bukan bilangan \n");
return;
}
}
else
{
printf("Anda mengetikkan karakter bukan bilangan \n");
return;
}
}
/* definisi fungsi kali */
UINT kali(UINT a, UINT b)
{
UINT c = a*b;
return c;
}
contoh output dari program di atas adalah:
Ketikkan nilai untuk faktor1 2
Ketikkan nilai untuk faktor2 3
faktor1 = 2 ; faktor2 = 3
Hasil perkalian keduanya adalah 6
sebelum membahas source code di atas, akan dijelaskan bagaimana cara membuat program dengan source code di atas pada Microsoft Visual C++ 6.
- Buka
menu File|New pada Microsoft Visual C++ 6, kemudian pilih tab Projects dan
pilih Win32 Console Application. Pada bagian Project Name ketikkan nama
project yang anda inginkan, kemudian klik OK.
- Pilih
An empty project pada dialog yang muncul kemudian klik Finish, pada dialog
baru yang muncul klik OK.
- Sekarang
anda telah memiliki sebuah project yang masih kosong, untuk membuat dari
source code program di atas, buka kembali menu File|New dan pilih tab
Files, kemudian pilih C++ Source File, pastikan check box Add to project
dalam keadaan di-cek, dan nama project yang muncul pada kotak di bawahnya
adalah nama project anda tadi. Kemudian ketikkan nama source file yang
anda inginkan dengan extensi .c pada kotak file name, sebab Visual C++
akan secara otomatis memberi extensi .cpp jika anda tidak memberikan
extensi pada nama file yang anda masukkan.
- Kemudian
copy source code di atas ke file yang baru anda buat.
- Compile
file tsb dengan menekan Control+F5 atau memilih menu Build|Execute
"nama file".exe . Sekarang anda sudah dapat melihat outputnya
pada sebuah console windows (dos prompt pada windows 98).
| |
Operator ini disebut juga operator bitwise
or. Cara kerjanya adalah melakukan operasi
OR
(|) pada setiap bit kedua operand.
misalnya: 0xA | 0xC akan menghasilkan 0xE , perhatikan bahwa 0xA =
1010 biner dan 0xC
= 1100 biner . Sehingga 1010 |
1100 = 1110 biner atau 0xE
heksadesimal sebab 0|1
= 1 , 1|0 = 1, 0|0 = 0, 1|1 = 1. |
^ |
Operator ini disebut juga operator bitwise
xor. Cara kerjanya adalah melakukan operasi
XOR
(^) pada setiap bit kedua operand.
misalnya: 0xA ^ 0xC akan menghasilkan 0x6 , perhatikan bahwa 0xA =
1010 biner dan 0xC =
1100 biner . Sehingga 1010 |
1100 = 0110 biner atau 0x6 heksadesimal sebab 0^1 = 1
, 1^0 = 1, 0^0 = 0, 1^1 = 0. |
Operator Penggeseran Bit (Bit
Shift Operator) |
|
>> |
Operator ini disebut operator geser kanan
(right shift). Cara kerjanya adalah melakukan penggeseran bit ke kanan pada nilai
operand sejumlah bit yang ada di sebelah kanan operator ini. Misalnya:
0xA
>> 3 akan menghasilkan 0x1 , perhatikan bahwa 0xA =
1010 biner , sehingga dengan menggeser bitnya 1 kali ke kanan
diperoleh 101 biner , dan jika digeser 3 kali akan diperoleh 1 biner atau 0x1 heksadesimal |
<< |
Operator ini disebut operator geser kiri
(left shift). Cara kerjanya adalah melakukan penggeseran bit ke kiri pada
nilai operand sejumlah bit yang ada di sebelah kanan operator ini.
Misalnya:
0xA << 3 akan menghasilkan 0x50 , perhatikan bahwa 0xA =
1010 biner , sehingga dengan menggeser bitnya 1 kali ke kiri
diperoleh 10100 biner , dan jika digeser 3 kali akan diperoleh 1010000 biner atau 0x50 heksadesimal . |
Operator Perbandingan
(Relational Operator) |
|
== |
Operator ini bekerja dengan membandingkan
nilai operand di sebelah kanan dan sebelah kiri-nya, jika keduanya identik
maka hasilnya adalah 1 (true). Misalnya:
A = 2; B = 2; if(A == B) ... code1; else ... code2 ; pada source code ini ...code1 akan di eksekusi, sebab A==B bernilai 1 (true). |
!= |
Operator ini bekerja dengan membandingkan
nilai operand di sebelah kanan dan sebelah kiri-nya, jika keduanya berbeda
maka hasilnya adalah 1 (true). Misalnya:
A = 2; B = 2; if(A != B) ... code1; else ... code2 ; pada source code ini ...code2 akan di eksekusi, sebab A!=B bernilai 0 (false). |
<= |
Operator ini bekerja dengan membandingkan
nilai operand di sebelah kanan dan sebelah kiri-nya, jika operand di kiri
bernilai kurang dari atau sama dengan operand di sebelah kanan maka hasilnya
adalah 1 (true). Misalnya:
A = 2; B = 4; if(A <= B) ... code1; else ... code2 ; pada source code ini ...code1 akan di eksekusi, sebab A<=B bernilai 1 (true). |
> |
Operator ini bekerja dengan membandingkan
nilai operand di sebelah kanan dan sebelah kiri-nya, jika operand di kiri
bernilai lebih dari operand di sebelah kanan maka hasilnya adalah 1 (true).
Misalnya:
A = 3; B = 1; if(A > B) ... code1; else ... code2 ; pada source code ini ...code1 akan di eksekusi, sebab A
> B bernilai 1 (true). |
>= |
Operator ini bekerja dengan membandingkan
nilai operand di sebelah kanan dan sebelah kiri-nya, jika operand di kiri
bernilai lebih dari atau sama dengan operand di sebelah kanan maka hasilnya
adalah 1 (true). Misalnya:
A = 4; B = 2; if(A >= B) ... code1; else ... code2 ; pada source code ini ...code1 akan di eksekusi, sebab A>=B bernilai 1 (true). |
< |
Operator ini bekerja dengan membandingkan
nilai operand di sebelah kanan dan sebelah kiri-nya, jika operand di kiri
bernilai kurang dari operand di sebelah kanan maka hasilnya adalah 1 (true).
Misalnya:
A = 2; B = 4; if(A < B) ... code1; else ... code2 ; pada source code ini ...code1 akan di eksekusi, sebab A
< B bernilai 1 (true). |
ternary operator, operator ini bekerja pada tiga
operand sekaligus.
Operator |
Kegunaan |
Ekspresi1 ? Ekspresi2 :
Ekspresi3 |
Cara kerja dari operator ini adalah
mengecek nilai
ekspresi1 , jika nilainya benar, maka yang akan dievaluasi adalah ekspresi2 , jika salah maka yang akan dievaluasi adalah ekspresi3 . Berikut ini contoh untuk memperjelas:int z; int x = 2; int y = 3; z = (x > y) ? x : y ; pada source code di atas, nilai z akan sama dengan y, sebab ekspresi1 nilainya salah, sehingga yang akan dievaluasi
adalah ekspresi3 . |
Percabangan
Percabangan (Control Flow) adalah teknik yang digunakan untuk mengalihkan
eksekusi program saat suatu ekspresi yang diuji bernilai benar atau salah.
Pertama, akan dibahas percabangan dengan if, else if, dan else. Bentuk
percabangan ini adalah yang paling sederhana. Format penggunaannya adalah:
pada sourcecode ini, pertama-tama, if akan mengecek
Selanjutnya adalah percabangan dengan
pada source code diatas,
if (ekspresi1)
...
sourcecode1;
else if (ekspresi2)
...
sourcecode2;
else
...
sourcecode3;
pada sourcecode ini, pertama-tama, if akan mengecek
ekspresi1
,
jika benar maka sourcecode1;
akan
dieksekusi, jika tidak, maka eksekusi program berpindah ke else
if (ekspresi2), else if
akan mengecek ekspresi2
,
jika ekspresi2
benar
maka sourcecode2
akan
dieksekusi, jika salah maka eksekusi program berpindah ke sourcecode3.
Pada
format di atas, else if
sebenarnya
opsional (boleh ada boleh juga tidak), jika anda hanya memiliki dua alternatif "jawaban"
maka bagian else if
tidak perlu
digunakan.Selanjutnya adalah percabangan dengan
switch
. switch
digunakan
untuk percabangan dengan banyak alternatif pilihan, sebenarnya hal ini juga
dapat dilakukan dengan if , else if ,
else
, tetapi switch lebih efisien dan lebih mudah jika kita sudah
menguasainya. Format penggunaannya adalah:switch (ekspresi)
{case (ekspresi1):
...
sourcecode1;
break;
case (ekspresi2):
...
sourcecode2;
break;
case (ekspresi3):
...
sourcecode3;
break;
default:
...
sourcecode4;
break;
}
pada source code diatas,
ekspresi
biasanya
merupakan sebuah variabel yang dapat memiliki banyak macam nilai (misalnya
variabel bertipe int), nilai ekspresi
akan
dicocokkan (matching) dengan nilai ekspresi1
, ekspresi2
dan ekspresi3
, jika
ternyata ekspresi
bernilai sama
dengan salah satunya maka source code dibawahnya akan dieksekusi,
misalnya: ekspresi
bernilai
sama dengan ekspresi1
maka source
code1
akan dieksekusi. Jika ternyata tidak ada nilai yang sama
dengan ekspresi
maka yng
dieksekusi adalah source code sesudah default
. default
dan
pernyataan sesudahnya adalah opsional (dapat digunakan, dan dapat tidak
digunakan). Satu hal lagi, setelah setiap alternatif pernyataan source code,
anda harus menggunakan keyword break;
, tujuannya
adalah agar eksekusi program keluar dari percabangan switch
sehingga
source code yang ada di bawahnya tidak dieksekusi. Misalnya: anda lupa
memberikan break; setelah sourcecode2
, maka
saat ekspresi
bernilai
sama dengan ekspresi2
eksekusi
program tidak akan keluar dari percabangan switch
setelah sourcecode2
tetapi
akan terus melanjutkan eksekusi ke sourcecode3
,
setelah keyword break
(sesudah sourcecode3
)
barulah eksekusi keluar dari percabangan dengan switch ini. Hal ini tentunya
bukan hal yang anda harapkan, jadi teliti lah saat menggunakan switch. Masih
ada bentuk percabangan lain dalam C, tetapi tidak akan di bahas di sini sebab
jarang digunakan dan dengan kedua teknik percabangan yang ada di atas sudah
cukup untuk sebagian besar kasus yang kita hadapi sehari-hari.
Perulangan
Perulangan adalah teknik pemrograman yang digunakan
untuk mengatasi pernyataan program yang harus dikerjakan secara berulang-ulang.
Perulangan dalam C dapat diimplementasikan dengan beberapa keyword, yaitu
pada source code di atas
pada source code di atas,
Perulangan dengan while mempunyai format sebagai berikut:
pada source code di atas, pertama-tama keyword
for,
do .. while , while
. Ketiga keyword ini lah yang
paling sering digunakan. Perulangan menggunakan for
mempunyai
format sebagai berikut.for( ekspresi1 ; ekspresi2 ;ekspresi3 )
{
...
source_code_ulang;
}
pada source code di atas
ekspresi1
adalah
ekspresi yang akan dievaluasi pertama kali , kemudian ekspresi2
dievaluasi,
jika nilainya benar maka source_code_ulang;
dieksekusi,
setelah itu ekspresi3
akan
dieksekusi, kemudian jalannya program kembali lagi ke pernyataan for dan ekspresi2
kembali
dievaluasi (ekspresi1
tidak
lagi dieksekusi), jika benar maka source_code_ulang;
dieksekusi,
setelah itu ekspresi3
akan
dieksekusi, kemudian jalannya program kembali lagi ke pernyataan for
,
hal ini dilakukan berulang-ulang selama ekspresi2
masih
bernilai benar. Berikut contoh potongan programnya:for(int i = 0; i < 4 : i++)
{
printf("loop
masih dieksekusi");
}
pada source code di atas,
ekspresi1
adalah
int i = 0 , ekspresi ini mendeklarasikan sebuah variabel bertipe int dan
memberikan variabel tersebut nilai 0. Ekspresi ini hanya satu kali dieksekusi,
yaitu saat keyword for pertama kali dipanggil. Kemudian nilai i dievaluasi
apakah kurang dari 4 (ekspresi2
adalah i
< 4
), saat pertama kali dieksekusi ekspresi ini bernilai benar
sebab i < 4
, kemudian kita memanggil
fungsi printf("..")
untuk
menampilkan tulisan ke layar, setelah itu nilai i ini dinaikkan 1 satuan
menjadi 2 pada ekspresi3
(ekspresi3
adalah i++
),
langkah-langkah ini diulang sampai nilai i menjadi 4. Saat i
= 3,
pengulangan terakhir akan membuat nilai i menjadi 4 (sebab ekspresi3
di
eksekusi), jalannya program kembali ke keyword for
,
kemudian ekspresi2
dieksekusi,
sekarang ekspresi tersebut bernilai salah sebab i = 4 , sehingga eksekusi
program akan keluar dari perulangan ini, dan melanjutkan ke source code sesudah
kurung kurawal penutup pada contoh di atas.Perulangan dengan while mempunyai format sebagai berikut:
while(
test_expression )
{
...
source_code;
}
pada source code di atas, pertama-tama keyword
while
dipanggil,
kemudian test_expression dievaluasi, jika nilainya benar, maka source_code
akan
dieksekusi sampai test_expression
bernilai
salah. Jika test_expression
bernilai
salah maka jalannya program akan melewati perulangan ini begitu saja
(melanjutkan ke source code sesudah kurung kurawal penutup pada contoh di
atas). Berikut ini source code yang menggunakan while dan mengerjakan hal yang
sama dengan source code untuk perulangan menggunakan for.int i = 0;
while(i < 4)
{
i++;
printf("loop masih dieksekusi");
}
Perulangan dengan do...while
, pada
dasarnya sama dengan perulangan dengan while, hanya saja pernyataan yang ada di
antara keyword do dan while akan dieksekusi minimal satu kali, sebab pengetesan
ekspresi dilakukan setelah peryataan tersebut dieksekusi. Berikut ini source
code yang menggunakan do...while
dan
mengerjakan hal yang sama dengan source code untuk perulangan menggunakan
for. int i = 0;
do
{
printf("loop masih dieksekusi");
i++;
}
while(i < 4)
Obrolan
bebas:
"Sebelum anda bosan, penulis ingin memberitahukan bahwa bahasa C diciptakan oleh seorang hacker bernama Dennis Ritchie yang bekerja di Bell Telephone Laboratories pada 1972. Compiler C yang mendukung paling banyak arsitektur komputer saat ini adalah GNU C yang terdapat di banyak varian sistem operasi UNIX, termasuk Linux. Ada beberapa implementasi bahasa C yang mungkin akan membuat anda tertarik, yaitu: kernel dari sistem operasi Linux, karena source code-nya free, anda dan juga penulis bisa belajar banyak dari sana, kemudian, saat ini sudah ada beberapa cellphone yang dapat diisi dengan program aplikasi yang dibuat dengan bahasa C, dan yang terpenting adalah 'kekuatan' dari software apapun yang anda buat hanya dibatasi oleh imajinasi anda :)."
"Sebelum anda bosan, penulis ingin memberitahukan bahwa bahasa C diciptakan oleh seorang hacker bernama Dennis Ritchie yang bekerja di Bell Telephone Laboratories pada 1972. Compiler C yang mendukung paling banyak arsitektur komputer saat ini adalah GNU C yang terdapat di banyak varian sistem operasi UNIX, termasuk Linux. Ada beberapa implementasi bahasa C yang mungkin akan membuat anda tertarik, yaitu: kernel dari sistem operasi Linux, karena source code-nya free, anda dan juga penulis bisa belajar banyak dari sana, kemudian, saat ini sudah ada beberapa cellphone yang dapat diisi dengan program aplikasi yang dibuat dengan bahasa C, dan yang terpenting adalah 'kekuatan' dari software apapun yang anda buat hanya dibatasi oleh imajinasi anda :)."
Fungsi
dan Struktur Program C
Komponen utama bahasa C adalah sebuah bentuk yang dikenal sebagai
fungsi. Program C yang paling sederhana sekalipun harus mempunyai minimal
sebuah fungsi, yaitu fungsi
Format dasar "deklarasi" sebuah fungsi adalah:
main()
. Fungsi
adalah sekelompok perintah (bahasa C) yang dapat dipanggil untuk mengerjakan
sebuah pekerjaan tertentu. Format dasar "definisi" sebuah fungsi
adalah:return_type function_name(param1_type parameter1,
param2_type parameter2, ...)
{
...
source_codes ;
return hasil_perhitungan;
}
Format dasar "deklarasi" sebuah fungsi adalah:
return_type function_name(param1_type parameter1, param2_type
parameter2, ...);
Catatan:
Sebenarnya ada beberapa hal yang perlu anda perhatikan pada bentuk umum di atas, tanda
fungsi ini dapat menerima 2 atau lebih parameter, dan jumlah parameter tersebut terserah anda saat memanggil fungsi tersebut, asal lebih dari atau sama dengan 2. Dalam tutorial ini kita tidak akan mempelajari fungsi seperti ini, kita hanya akan mempelajari fungsi dengan jumlah parameter yang pasti.
Sebenarnya ada beberapa hal yang perlu anda perhatikan pada bentuk umum di atas, tanda
...
pada return_type
function_name(param1_type parameter1, param2_type parameter2, ...)
maksudnya
adalah sebuah fungsi dapat mempunyai lebih dari dua parameter, tergantung
bagaimana anda mendeklarasikan dan mendefinisikan sebuah fungsi. Anda perlu
berhati-hati dengan sintaks ini, sebab dalam bahasa C sebuah fungsi yang
dideklarasikan atau didefinisikan dengan ...
sebagai
parameter terakhirnya berarti fungsi tersebut dapat memiliki jumlah parameter
yang "tidak terbatas", misalnya fungsi yang dideklarasikan sebagai
berikut:void test(int a, char b , ...);
fungsi ini dapat menerima 2 atau lebih parameter, dan jumlah parameter tersebut terserah anda saat memanggil fungsi tersebut, asal lebih dari atau sama dengan 2. Dalam tutorial ini kita tidak akan mempelajari fungsi seperti ini, kita hanya akan mempelajari fungsi dengan jumlah parameter yang pasti.
return_type
adalah tipe data dari hasil_perhitungan
. hasil_perhitungan
dalam literatur biasa disebut "return value". Sebuah fungsi dapat
mengembalikan (menghasilkan) sebuah nilai (dalam fungsi di atas nilai yang
dikembalikan adalah hasil_perhitungan
), namun dapat juga tidak mengembalikan apa-apa. Jika sebuah
fungsi tidak mengembalikan nilai apa pun maka return_type
harus bertipe void dan fungsi tersebut tidak boleh
mengandung keyword return sebuah_nilai
, dengan sebuah_nilai
adalah nilai tertentu, sekalipun nilai itu
adalah 0. parameter1
dan parameter2
adalah nilai input yang akan diolah oleh fungsi. function_name
adalah nama dari fungsi yang kita definisikan. param1_type
dan param2_type
adalah tipe data dari parameter1
dan parameter2
. Sebuah fungsi juga boleh tidak mempunyai parameter sama
sekali, fungsi tanpa parameter adalah valid bagi compiler C. Untuk membuat
sebuah program C yang menggunakan fungsi (selain fungsi main()
)dapat berjalan dengan baik, anda harus menempatkan
"definisi" fungsi tersebut sebelum fungsi main()
atau jika anda tidak ingin menaruh definisi fungsi
tersebut sebelum main()
maka
letakkan "deklarasi" fungsi tersebut sebelum main()
seperti pada contoh yang akan di bahas. Hal ini
diperlukan sebab fungsi yang anda buat kemungkinan tidak akan dikenali jika
anda tidak mendeklarasikannya atau mendefinisikannya sebelum fungsi main()
. Selanjutnya kita akan membedah sebuah program C yang sangat
sederhana untuk memahami konsep di atas.#include < stdio.h >
#define UINT unsigned int
/* deklarasi fungsi kali */
UINT kali(UINT a, UINT b);
void main()
{
UINT faktor1;
UINT faktor2;
UINT hasil ;
printf("Ketikkan nilai untuk faktor1 ");
scanf("%d", &faktor1);
if(faktor1 >= 0 && faktor1 <= 9 )
{
printf("Ketikkan nilai untuk faktor2 ");
scanf("%d", &faktor2);
if(faktor2 >= 0 && faktor2 <= 9)
{
printf("faktor1 = %d ; faktor2 = %d \n", faktor1,
faktor2);
hasil = kali(faktor1, faktor2);
printf("Hasil perkalian keduanya adalah %d\n", hasil);
}
else
{
printf("Anda mengetikkan karakter bukan bilangan \n");
return;
}
}
else
{
printf("Anda mengetikkan karakter bukan bilangan \n");
return;
}
}
/* definisi fungsi kali */
UINT kali(UINT a, UINT b)
{
UINT c = a*b;
return c;
}
contoh output dari program di atas adalah:
Ketikkan nilai untuk faktor1 2
Ketikkan nilai untuk faktor2 3
faktor1 = 2 ; faktor2 = 3
Hasil perkalian keduanya adalah 6
sebelum membahas source code di atas, akan dijelaskan bagaimana cara membuat program dengan source code di atas pada Microsoft Visual C++ 6.
- Buka
menu File|New pada Microsoft Visual C++ 6, kemudian pilih tab Projects dan
pilih Win32 Console Application. Pada bagian Project Name ketikkan nama
project yang anda inginkan, kemudian klik OK.
- Pilih
An empty project pada dialog yang muncul kemudian klik Finish, pada dialog
baru yang muncul klik OK.
- Sekarang
anda telah memiliki sebuah project yang masih kosong, untuk membuat dari
source code program di atas, buka kembali menu File|New dan pilih tab
Files, kemudian pilih C++ Source File, pastikan check box Add to project
dalam keadaan di-cek, dan nama project yang muncul pada kotak di bawahnya
adalah nama project anda tadi. Kemudian ketikkan nama source file yang
anda inginkan dengan extensi .c pada kotak file name, sebab Visual C++
akan secara otomatis memberi extensi .cpp jika anda tidak memberikan
extensi pada nama file yang anda masukkan.
- Kemudian
copy source code di atas ke file yang baru anda buat.
- Compile
file tsb dengan menekan Control+F5 atau memilih menu Build|Execute
"nama file".exe . Sekarang anda sudah dapat melihat outputnya
pada sebuah console windows (dos prompt pada windows 98).
Catatan:
Sebenarnya anda juga dapat menjalankan program yang dihasilkan dalam mode debug dengan menekan F5 atau memilih menu Build|Start Debug|Go, namun anda tidak akan sempat melihat outputnya.
Sebenarnya anda juga dapat menjalankan program yang dihasilkan dalam mode debug dengan menekan F5 atau memilih menu Build|Start Debug|Go, namun anda tidak akan sempat melihat outputnya.
Sekarang kita
akan membahas arti dari source code di atas. Pada baris pertama anda
melihat
pernyataan ini mengetes input yang diberikan user (yang kita peroleh dari fungsi
Jika input tersebut memenuhi syarat percabangan di atas (ekspresi sesudah if bernilai benar) maka input dari user akan ditampilkan, kemudian fungsi UINT kali(UINT , UINT) akan dipanggil dengan parameter-parameternya adalah input dari user (
#include
<stdio.h>
, baris ini maksudnya adalah preprocessor harus
menempatkan isi dari file tersebut diawal file yang kita buat sebelum compiler
mengolahnya. stdio.h adalah file yang disebut sebagai file header (extensi *.h)
yang mengandung definisi fungsi-fungsi yang kita butuhkan untuk menampilkan
program kita (fungsi printf( , )
) dan fungsi-fungsi untuk mengambil data yang dimasukkan user
melalui keyboard (fungsi scanf ( , )
). Setelah itu pada baris selanjutnya, kita mendefinisikan
tipe data unsigned int dengan nama yang lebih singkat yaitu UINT. Kemudian,
fungsi int kali(int a, int b)
dideklarasikan.
Pada deklarasi sebuah fungsi, yang dibutuhkan sebenarnya hanya tipe data yang
dikembalikan oleh fungsi (tipe data return value), nama fungsi tersebut dan tipe data semua parameternya,
jadi a dan b sebenarnya tidak dibutuhkan, kita memberikan simbol ini hanya untuk
mempermudah saat membaca source code. Kemudian pada baris selanjutnya fungsi
main didefinisikan7. Fungsi main
adalah fungsi yang pertama kali dipanggil oleh sistem operasi saat program kita
dimulai8. Pada contoh
di atas, main didefinisikan sebagai fungsi yang tidak punya kembalian ( return value), sebab keyword void berarti tidak ada return value sama
sekali. Fungsi main juga didefinisikan tidak mempunyai parameter. Pada baris
selanjutnya kita mendefinisikan 3 buah variabel unsigned int, kemudian ada
sebuah ekspresi yang diuji:if
(faktor1 >= 0 && faktor1 <=9)
pernyataan ini mengetes input yang diberikan user (yang kita peroleh dari fungsi
scanf
), jika inputnya adalah nilai numerik antara 0 dan 9 maka
blok pernyataan di bawah pernyataan if tersebut akan dieksekusi, jika tidak
maka blok pernyataan tersebut akan dilewati, dan program kita akan mengeksekusi
blok pernyataan sesudah else. Blok pernyataan ini akan menampilkan pesan
kemudian mengakhiri program dengan pernyataan return;9. Jika input dari user memenuhi syarat
percabangan if yang pertama maka user kembali diminta memberikan input karakter
dari keyboard, input ini kemudian diuji dengan ekspresi:if
(faktor2 >= 0 && faktor2 <=9)
Jika input tersebut memenuhi syarat percabangan di atas (ekspresi sesudah if bernilai benar) maka input dari user akan ditampilkan, kemudian fungsi UINT kali(UINT , UINT) akan dipanggil dengan parameter-parameternya adalah input dari user (
faktor1
dan faktor2
) dan hasil yang diperoleh dari fungsi tersebut dipindahkan
ke variabel yang diberi nama hasil, isi dari variabel ini kemudian ditampilkan
pada baris selanjutnya. Jika ternyata input kedua dari user tidak memenuhi
syarat maka program akan mengeksekusi blok pernyataan sesudah keyword else yang
ada di dalam blok pernyataan sesudah if (faktor1 >= 0 &&
faktor1 <=9)
, sehingga program akan menampilkan pesan
kesalahan dan program kemudian diakhiri.
catatan:
7 Anda harus membedakan antara definisi dan deklarasi sebuah fungsi, deklarasi sebuah fungsi digunakan untuk memberikan "tanda pengenal" bagi sebuah fungsi agar fungsi tersebut dapat dikenali saat dipanggil, definisi sebuah fungsi adalah "ungkapan teknis" tentang apa yang harus dilakukan oleh sebuah fungsi saat fungsi tersebut dipanggil.
8 Fungsi semacam ini disebut entry point. Sebenarnya anda dapat memberikan entry point yang bukan fungsi
9 Perhatikan bahwa pernyataan return ; dan pernyataan return 0 ; adalah berbeda, pernyataan yang pertama mengakhiri sebuah pemanggilan fungsi tanpa mengembalikan nilai apa-apa, sedangkan pernyataan yang kedua mengembalikan nilai yaitu 0.
Kata-kata yang dibatasi oleh karakter /* dan */ pada source code di atas adalah komentar (comment) yang berguna sebagai dokumentasi source code, kata-kata yang ada di antara karakter ini akan diabaikan oleh compiler sehingga ada atau tidaknya kata-kata tersebut tidak berpengaruh
7 Anda harus membedakan antara definisi dan deklarasi sebuah fungsi, deklarasi sebuah fungsi digunakan untuk memberikan "tanda pengenal" bagi sebuah fungsi agar fungsi tersebut dapat dikenali saat dipanggil, definisi sebuah fungsi adalah "ungkapan teknis" tentang apa yang harus dilakukan oleh sebuah fungsi saat fungsi tersebut dipanggil.
8 Fungsi semacam ini disebut entry point. Sebenarnya anda dapat memberikan entry point yang bukan fungsi
main()
pada
Microsoft Visual C++ dengan mengatur salah satu switch pada linker-nya dan
memberikan nama fungsi yang anda inginkan pada parameter yang diminta oleh
switch tersebut untuk dijadikan entry point.9 Perhatikan bahwa pernyataan return ; dan pernyataan return 0 ; adalah berbeda, pernyataan yang pertama mengakhiri sebuah pemanggilan fungsi tanpa mengembalikan nilai apa-apa, sedangkan pernyataan yang kedua mengembalikan nilai yaitu 0.
Kata-kata yang dibatasi oleh karakter /* dan */ pada source code di atas adalah komentar (comment) yang berguna sebagai dokumentasi source code, kata-kata yang ada di antara karakter ini akan diabaikan oleh compiler sehingga ada atau tidaknya kata-kata tersebut tidak berpengaruh
Fungsi untuk Input dan Output
Pada tutorial ini ada 2 buah fungsi input dan output yang
digunakan, penulis akan menjelaskannya agar anda tidak bingung saat mempelajari
source code yang diberikan. Fungsi yang pertama adalah fungsi output, yaitu
fungsi yang digunakan untuk menampilkan hasil yang diperoleh dari program kita
ke layar komputer, fungsi tersebut adalah
pada source code di atas, di antara tanda petik ganda diketikkan kata-kata yang ingin ditampilkan. Tanda
Fungsi yang kedua adalah
pada source code di atas, kita mengambil input dari user yang bertipe integer, sehingga kode yang digunakan adalah
int
printf(const char* [format],[argument]...)
. Anda tidak perlu
bingung menggunakan fungsi yang agak kompleks ini, anda cukup mengganti [format]
dengan
petik ganda dan di antara petik ganda tersebut anda tuliskan kata-kata yang
ingin ditampilkan. [argument]
adalah
opsional. Berikut ini contoh pengunaannya untuk menampilkan sebuah bilangan
desimal:int test = 10;
printf("inilah bilangan yang ingin ditampilkan:
%d",test);
pada source code di atas, di antara tanda petik ganda diketikkan kata-kata yang ingin ditampilkan. Tanda
%d
adalah
sebuah kode khusus untuk memberitahukan fungsi printf bahwa kita ingin
menampilkan bilangan integer (untuk tanda yang harus digunakan silahkan lihat
dokumentasi compiler yang anda gunakan, untuk Visual C++ gunakan MSDN) pada
posisi tersebut, bilangan yang ingin kita tampilkan kemudian diletakkan pada
parameter [argument]
dari
fungsi printf. Jika anda ingin menggunakan lebih banyak angka lagi (yang
berbeda posisinya dan dipisahkan karakter lain) maka anda cukup menmbah
lagi [argument]
dan
meletakkan penanda seperti %d
di
atas pada posisi yang anda inginkan.Fungsi yang kedua adalah
int scanf(const char*
[format], [argument]...)
. Fungsi ini adalah fungsi input, yang kita
gunakan untuk menerima input dari user melalui keyboard. Cara penggunanya mirip
dengan fungsi printf, bedanya terletak pada parameter kedua, parameter [argument]
d
ari fungsi ini adalah alamat dari variabel yang ingin kita isi.
Parameter pertama ([format]
), biasanya adalah tanda
petik ganda yang diantaranya diisi dengan kode jenis varabel yang akan kita isi
pada parameter kedua ([argument]
).
Contoh:int nilai1;
scanf("%d", &nilai1);
pada source code di atas, kita mengambil input dari user yang bertipe integer, sehingga kode yang digunakan adalah
%d
.
Parameter kedua scanf adalah alamat dari variabel yang kita miliki sehingga
digunakan address of operator10 untuk
mengambil alamat dari variabel tersebut. Jadi, secara keseluruhan, kita
mengambil input dari user dan memasukkannya ke variabel nilai1.
10 Address
of operator akan dijelaskan lebih rinci pada bagian pointer.
Pointer dan Array
Pointer adalah salah satu konsep yang paling sulit dipahami oleh
programer pemula dalam bahasa C dan C++. Untuk memahami dengan baik bagaimana
pointer bekerja, anda harus bisa membayangkan pergerakan variabel-variabel
antara microprocessor dan memori utama, dan akan lebih baik jika anda tahu
bagaimana sistem operasi semacam windows mengorganisasikan memori. Semoga hal
ini tidak membuat anda merasa rendah diri. Penulis sendiri yang pada awalnya
adalah "hardware mania" sebelum memulai belajar programming merasakan
bahwa konsep ini lebih mudah untuk dipahami, dibandingkan orang-orang yang
tidak mengerti hardware dengan baik.
Pointer pada hakikatnya adalah variabel yang menyimpan alamat variabel lain yang tipe data-nya sama dengan tipe data pointer tersebut. Untuk mempermudah memahami pointer, terlebih dahulu akan dijelaskan bagaimana pengorganisasian memori dalam sebuah komputer oleh sistem operasi yang berjalan pada komputer tersebut. Sistem operasi modern umumnya menggunakan apa yang dikatakan swap file atau page file. Page file adalah bagian dari media penyimpan eksternal (diluar motherboard) yang diperlakukan seperti RAM. Dalam sistem operasi seperti ini setiap program mempunyai wilayah memori sendiri (memory space) yang hanya dapat digunakan oleh program itu sendiri, tidak dapat digunakan oleh program lain. Memory space ini adalah bagian dari RAM namun bisa juga sebagian berada pada swap file, hal ini diatur oleh bagian manajemen memori dari sistem operasi. Wilayah memory ini dibagi ke dalam beberapa komponen lagi, yaitu:
Pointer pada hakikatnya adalah variabel yang menyimpan alamat variabel lain yang tipe data-nya sama dengan tipe data pointer tersebut. Untuk mempermudah memahami pointer, terlebih dahulu akan dijelaskan bagaimana pengorganisasian memori dalam sebuah komputer oleh sistem operasi yang berjalan pada komputer tersebut. Sistem operasi modern umumnya menggunakan apa yang dikatakan swap file atau page file. Page file adalah bagian dari media penyimpan eksternal (diluar motherboard) yang diperlakukan seperti RAM. Dalam sistem operasi seperti ini setiap program mempunyai wilayah memori sendiri (memory space) yang hanya dapat digunakan oleh program itu sendiri, tidak dapat digunakan oleh program lain. Memory space ini adalah bagian dari RAM namun bisa juga sebagian berada pada swap file, hal ini diatur oleh bagian manajemen memori dari sistem operasi. Wilayah memory ini dibagi ke dalam beberapa komponen lagi, yaitu:
- Global
namespace, bagian ini adalah bagian memory space yang dapat diakses oleh
program yang kita miliki dengan bebas.
- Code
Space, bagian ini menyimpan kode program yang akan dieksekusi (machine
code) yang kita hasilkan dari source code program yang sudah di-compile..
Bagian ini adalah bagian yang read only, sebab kita hanya dapat
mengeksekusi sebuah program, bukan merubah kode program itu sendiri saat
dia dijalankan.
- Stack,
yaitu bagian dari memory yang berfungsi untuk menyimpan data sementara,
saat sebuah fungsi sedang dipanggil dan diproses.
- Register,
yaitu bagian dari Microprocessor yang kita miliki yang dapat menyimpan
data sementara ketika program sedang dijalankan11.
Register-register inilah yang memelihara keadaan sistem kita agar tetap
berjalan sebagaimana mestinya. Tentang register akan dijelaskan lebih
lanjut pada pemrograman assembly. Yang perlu kita ketahui saat ini adalah
beberapa register yang bertugas menyimpan alamat kode program yang sedang
dieksekusi saat ini, register ini disebut sebagai instruction
pointer, selain itu ada register yang berfungsi menunjukkan alamat
stack yang digunakan saat ini, register ini disebut stack pointer dan
ada pula register yang bertugas menyimpan sementara alamat yang dimiliki
oleh stack pointer, register ini disebut stack frame.
- Free
store, adalah bagian memory di luar bagian memory yang telah di sebut di
atas.
11 Register
adalah bagian inti dari microprocessor yang kita miliki, disinilah aktivitas
utama yang terjadi saat komputer kita jalankan. Pada x86 32 bit ada beberapa
register yang digunakan secara intensif dan ada juga yang tidak. Penjelasan
lebih rinci tentang register-register ini dapat anda lihat pada tutorial
pemrograman assembly.
Sebelum
melangkah lebih jauh, akan dijelaskan apa yang terjadi ketika sebuah fungsi
dipanggil. Berikut ini adalah proses yang terjadi :
- Pertama,
alamat kode instruksi yang ditunjuk oleh instruction pointer dinaikkan
satu instruksi, sehingga instruction pointer menunjuk ke alamat kode
instruksi yang akan dieksekusi setelah fungsi yang dimaksud selesai
dieksekusi. Alamat ini kemudian di simpan pada stack.
- Kemudian,
nilai stack pointer dinaikkan untuk menyediakan ruang bagi return value
dari fungsi yang akan kita eksekusi.
- Alamat
kode instruksi pertama dari fungsi yang ingin kita eksekusi kemudian di
pindahkan ke instruction pointer, sehingga fungsi tersebut adalah perintah
yang akan dieksekusi selanjutnya.
- Alamat
stack saat ini yang ada pada register stack pointer kemudian di copy ke
register stack frame pointer, mulai saat ini, data apapun yang dimasukkan
ke stack dianggap lokal terhadap fungsi yang kita panggil.
- Seluruh
parameter fungsi kemudian disimpan atau tepatnya di copy ke stack
- Instruction
pointer kemudian mengeksekusi kode instruksi pertama yang telah ditunjuk
pada langkah 3, sehingga fungsi dieksekusi.
- Variabel
lokal yang didefinisikan di dalam fungsi di simpan di stack, misalnya
variabel c pada fungsi kali pada source code sebelumnya.
- Fungsi
telah selesai dieksekusi, hasil perhitungan dari fungsi tersebut kemudian
diletakkan pada bagian stack yang telah disediakan pada langkah 2.
- Alamat
yang disimpan oleh register stack frame pointer kemudian di restore
kembali ke register stack pointer, sehingga stack efektif saat ini tidak
mengandung parameter fungsi dan variabel yang lokal terhadap fungsi.
- Return
value dari fungsi di pindahkan ke variabel yang menerima hasil fungsi tersebut.
- Isi
instruction pointer yang di simpan di stak pada langkah 1 kemudian
dipindahkan ke instruction pointer , sehingga program kembali dilanjutkan.
Setelah membaca uraian di atas kita tahu bahwa ada beberapa
alasan mengapa pointer diperlukan, yaitu:
- Dalam
kasus tertentu kita perlu mengubah isi dari sebuah variabel yang
sebenarnya, kita tidak bisa melakukan hal ini dengan fungsi seperti yang
telah kita pelajari sebab fungsi tersebut hanya memanipulasi
"kopian" dari variabel yang sebenarnya ingin kita manipulasi
(yang di simpan di stack ketika fungsi tersebut diproses )
- Jika
kita bisa merubah secara langsung variabel yang ingin kita manipulasi maka
hal itu adalah lebih efisien dibandingkan mengkopi dan memanipulasinya,
kemudian mengkopi kembali hasil manipulasi tersebut dari stack ke variabel
aslinya.
- Dalam
kasus sebuah fungsi yang harus mengembalikan 2 atau lebih return value.
Jelas hal ini tidak mungkin dilakukan dengan metode yang telah kita
ketahui, sebab sebuah fungsi hanya mungkin mempunyai 1 return value (baca
kembali bagian fungsi).
Berikut ini adalah sintaks untuk mendeklarasikan pointer:
pada contoh ini dideklarasikan sebuah pointer ke sebuah variabel bertipe int. Sebuah pointer harus menunjuk ke alamat memory tertentu, jika tidak maka pointer tersebut bisa menimbulkan bug, pointer seperti ini disebut stray pointer. Dengan demikian jika anda belum mengisi sebuah pointer dengan alamat memori tertentu maka inisialisasi pointer tersebut dengan nilai 0 sehingga pointer tersebut menjadi null pointer . Null pointer adalah pointer yang tidak berbahaya, sehingga tidak akan menimbulkan bug seperti stray pointer. Untuk itu contoh di atas harus diperbaiki sebagai berikut:
Beberapa operator dalam C yang bisa punya banyak makna dan kegunaan, tergantung konteks penggunaannya. Operator jenis ini antara lain & dan * . Berikut adalah contoh untuk memperjelas:
Pada baris /* operasi 1 */, pernyataan: int * pA = &A mempunyai arti: kita mendeklarasikan pA sebagai pointer ke variabel bertipe int, hal ini diwakili oleh sintaks int * pA , kemudian pointer ini kita buat menunjuk ke alamat variabel A. Alamat variabel A ditunjukkan dengan sintaks &A, operator & pada sintaks ini disebut sebagai adddress of operator, karena memberikan alamat variabel yang ada di sebelah kanannya yaitu alamat variabel A. Alamat ini kemudian kita pindahkan ke variabel pA yang baru dideklarasikan dengan operator = . Pada baris /* operasi 2 */, operator * berfungsi sebagai operator kali biasa, mengalikan variabel di sebelah kiri dan kanannya. Pada baris /* operasi 3 */, operator & juga berfungsi sebagai operator bitwise AND biasa (sebab fungsi dasarnya memang seperti itu), yaitu melakukan operasi bitwise AND antara variabel di sebelah kiri dan kanannya. Pada baris /* operasi 4 */, operator * disebut sebagai indirection operator sebab pada ekspresi *pA operator ini bekerja mengakses isi dari alamat memori yang ditunjukkan oleh pointer pA, jadi pernyataan : *pA = C mempunyai arti, pindahkan isi variabel C ke variabel yang ditunjuk oleh pointer pA, atau dengan kata lain, pindah isi variabel C ke varabel A (sebab pA menunjuk ke alamat memory variabel A).
Selanjutnya kita akan membahas sebuah contoh program yang menggunakan pointer.
Jika anda mengeksekusi program di atas, akan diperoleh output sebagai berikut:
Dari output ini tampak jelas bahwa fungsi tukar1 benar-benar mempertukarkan isi dari var1 dan var2 , sementara fungsi tukar2 tidak demikian. Di sini lah kegunaan pointer mulai tampak. Pada fungsi tukar1, parameter-parameter yang digunakan adalah alamat variabel-variabel yang ingin kita rubah. Anda juga telah membaca sebelumnya tentang bagaimana sebuah fungsi bekerja, dari uraian tsb diketahui bahwa saat kita tidak menggunakan pointer sebagai parameter fungsi (biasa disebut passing by value) maka yang diubah bukan parameter yang kita masukkan, melainkan "kopian" dari parameter tersebut yang ada di stack, sehingga pada saat fungsi selesai dieksekusi parameter semula tidak berubah. Tidak demikian hal nya jika kita menggunakan pointer sebagai parameter (biasa disebut passing by pointer), karena yang kita jadikan paramater adalah alamat dari variabel tersebut, maka saat kita menggunakan indirection operator, variabel yang kita peroleh adalah variabel aslinya, and dapat melihat aplikasinya pada fungsi tukar1. Fungsi ini tidak penulis jelaskan lebih jauh sebab comment yang diberikan serta penjelassan sintaks pointer sebelumnya penulis anggap sudah memadai. Karena keterbatasan waktu, penjelasan tentang pointer hanya sampai di sini.
Sekarang kita akan membahas mengenai Array. Array adalah sekelompok variabel yang berbeda, dengan tipe data yang sama yang diperlakukan sebagai satu variabel dan dapat diakses dengan menggunakan nama dari array tersebut. Sintaks untuk mendeklarasikan array adalah:
output dari program di atas adalah:
Pada program di atas, kita mendeklarasikan array dengan tipe data unsigned int, dengan jumlah komponen sebanyak 10 buah. Kemudian komponen-komponen dari array tersebut diisi dengan nilai variabel komponen dalam sebuah perulangan menggunakan for. Perlu anda ketahui bahwa setiap komponen array dapat diakses dengan sebuah nilai yang disebut indeks. Indeks menunjukkan letak komponen tersebut di dalam array. Indeks paling kecil adalah 0, yaitu indeks yang menunjukkan komponen pertama dari array. Indeks 1 menunjukkan komponen ke-2, dan seterusnya. Perhatikan bahwa untuk mengakses komponen pertama dari array
Nama sebuah array sebenarnya merupakan pointer ke elemen pertama dari array tersebut, sehingga anda dapat mengakses elemen array tesebut dengan sebuah trik yang disebut dengan pointer arithmetic. Trik ini memanfaatkan nama array yang diperlakukan sebagai pointer. Berikut contohnya: (program sebelumnya diubah untuk memberikan output yg sama)
Output yang dihasilkan oleh program ini sama dengan output program sebelumnya. Perhatikan bahwa untuk menunjuk dan memanipulasi komponen dari
data_type * pointer_name;
data_type
adalah tipe data dari
variabel yang ditunjuk oleh pointer tersebut, pointer_name dalah nama dari
pointer yang kita inginkan. Contoh:int * pInt;
pada contoh ini dideklarasikan sebuah pointer ke sebuah variabel bertipe int. Sebuah pointer harus menunjuk ke alamat memory tertentu, jika tidak maka pointer tersebut bisa menimbulkan bug, pointer seperti ini disebut stray pointer. Dengan demikian jika anda belum mengisi sebuah pointer dengan alamat memori tertentu maka inisialisasi pointer tersebut dengan nilai 0 sehingga pointer tersebut menjadi null pointer . Null pointer adalah pointer yang tidak berbahaya, sehingga tidak akan menimbulkan bug seperti stray pointer. Untuk itu contoh di atas harus diperbaiki sebagai berikut:
int * pInt = 0;
Beberapa operator dalam C yang bisa punya banyak makna dan kegunaan, tergantung konteks penggunaannya. Operator jenis ini antara lain & dan * . Berikut adalah contoh untuk memperjelas:
int A = 9;
int B = 3;
int C;
int * pA = &A ; /* operasi 1 */
C = A*B; /* operasi 2 */
C = A & B; /* operasi 3 */
*pA = C; /* operasi 4 */
Pada baris /* operasi 1 */, pernyataan: int * pA = &A mempunyai arti: kita mendeklarasikan pA sebagai pointer ke variabel bertipe int, hal ini diwakili oleh sintaks int * pA , kemudian pointer ini kita buat menunjuk ke alamat variabel A. Alamat variabel A ditunjukkan dengan sintaks &A, operator & pada sintaks ini disebut sebagai adddress of operator, karena memberikan alamat variabel yang ada di sebelah kanannya yaitu alamat variabel A. Alamat ini kemudian kita pindahkan ke variabel pA yang baru dideklarasikan dengan operator = . Pada baris /* operasi 2 */, operator * berfungsi sebagai operator kali biasa, mengalikan variabel di sebelah kiri dan kanannya. Pada baris /* operasi 3 */, operator & juga berfungsi sebagai operator bitwise AND biasa (sebab fungsi dasarnya memang seperti itu), yaitu melakukan operasi bitwise AND antara variabel di sebelah kiri dan kanannya. Pada baris /* operasi 4 */, operator * disebut sebagai indirection operator sebab pada ekspresi *pA operator ini bekerja mengakses isi dari alamat memori yang ditunjukkan oleh pointer pA, jadi pernyataan : *pA = C mempunyai arti, pindahkan isi variabel C ke variabel yang ditunjuk oleh pointer pA, atau dengan kata lain, pindah isi variabel C ke varabel A (sebab pA menunjuk ke alamat memory variabel A).
Selanjutnya kita akan membahas sebuah contoh program yang menggunakan pointer.
#include < stdio.h >
#define UINT unsigned int
void tukar1(UINT* pVar1, UINT* pVar2);
void tukar2(UINT Var1, UINT Var2);
int main()
{
UINT var1 = 4;
UINT var2 = 8;
UINT
* pVar1 = &var1;
printf("nilai var1 saat ini : %d \n", var1);
printf("nilai var2 saat ini : %d \n", var2);
tukar2 (var1,var2);
printf("nilai var1 setelah tukar2: %d
\n",var1);
printf("nilai var2 setelah tukar2: %d
\n",var2);
tukar1(pVar1, &var2);
printf("nilai var1 setelah tukar1: %d \n",
var1);
printf("nilai var2 setelah tukar1: %d \n",
var2);
return 0;
}
void
tukar2(UINT Var1, UINT Var2)
{
/* karena fungsi ini passing by value maka yang kita
rubah nilainya saat ini adalah copy variabel var1 dan
var2
yang ada di stack */
UINT temp;
temp = Var1; /* copy isi var1 pada temp */
Var1 = Var2; /* copy isi var2 ke var1 */
Var2 = temp; /* copy isi temp ke var2 */
}
void
tukar1(UINT* pVar1, UINT* pVar2)
{
UINT temp;
temp = (*pVar1); /* copy isi var1 pada temp*/
(*pVar1) = (*pVar2); /* copy isi var2 ke var1 */
*pVar2 = temp; /* copy isi temp ke var2 */
}
Jika anda mengeksekusi program di atas, akan diperoleh output sebagai berikut:
nilai var1 saat ini : 4
nilai var2 saat ini : 8
nilai var1 setelah tukar2: 4
nilai var2 setelah tukar2: 8
nilai var1 setelah tukar1: 8
nilai var2 setelah tukar1: 4
Dari output ini tampak jelas bahwa fungsi tukar1 benar-benar mempertukarkan isi dari var1 dan var2 , sementara fungsi tukar2 tidak demikian. Di sini lah kegunaan pointer mulai tampak. Pada fungsi tukar1, parameter-parameter yang digunakan adalah alamat variabel-variabel yang ingin kita rubah. Anda juga telah membaca sebelumnya tentang bagaimana sebuah fungsi bekerja, dari uraian tsb diketahui bahwa saat kita tidak menggunakan pointer sebagai parameter fungsi (biasa disebut passing by value) maka yang diubah bukan parameter yang kita masukkan, melainkan "kopian" dari parameter tersebut yang ada di stack, sehingga pada saat fungsi selesai dieksekusi parameter semula tidak berubah. Tidak demikian hal nya jika kita menggunakan pointer sebagai parameter (biasa disebut passing by pointer), karena yang kita jadikan paramater adalah alamat dari variabel tersebut, maka saat kita menggunakan indirection operator, variabel yang kita peroleh adalah variabel aslinya, and dapat melihat aplikasinya pada fungsi tukar1. Fungsi ini tidak penulis jelaskan lebih jauh sebab comment yang diberikan serta penjelassan sintaks pointer sebelumnya penulis anggap sudah memadai. Karena keterbatasan waktu, penjelasan tentang pointer hanya sampai di sini.
Sekarang kita akan membahas mengenai Array. Array adalah sekelompok variabel yang berbeda, dengan tipe data yang sama yang diperlakukan sebagai satu variabel dan dapat diakses dengan menggunakan nama dari array tersebut. Sintaks untuk mendeklarasikan array adalah:
tipe_data nama_array[jumlah_komponen];
tipe_data
adalah tipe data dari
variabel yang menjadi komponen array tersebut. nama_array
adalah
nama yang kita berikan untuk array tersebut. jumlah_komponen
adalah
jumlah komponen (variabel) yang dimiliki oleh array tersebut. Berikut ini contoh
penggunaannya:#include < stdio.h >
#define UINT unsigned int
void
main()
{
UINT
komponen = 5;
UINT arr_Test[10];
UINT c;
for(
c = 0 ; c < 10 ; c++)
{
arr_Test[c] = komponen;
printf("Isi dari komponen ke[%d], adalah: %d
\n",c,arr_Test[c]);
komponen++;
}
}
output dari program di atas adalah:
Isi dari komponen ke[0], adalah: 5
Isi dari komponen ke[1], adalah: 6
Isi dari komponen ke[2], adalah: 7
Isi dari komponen ke[3], adalah: 8
Isi dari komponen ke[4], adalah: 9
Isi dari komponen ke[5], adalah: 10
Isi dari komponen ke[6], adalah: 11
Isi dari komponen ke[7], adalah: 12
Isi dari komponen ke[8], adalah: 13
Isi dari komponen ke[9], adalah: 14
Pada program di atas, kita mendeklarasikan array dengan tipe data unsigned int, dengan jumlah komponen sebanyak 10 buah. Kemudian komponen-komponen dari array tersebut diisi dengan nilai variabel komponen dalam sebuah perulangan menggunakan for. Perlu anda ketahui bahwa setiap komponen array dapat diakses dengan sebuah nilai yang disebut indeks. Indeks menunjukkan letak komponen tersebut di dalam array. Indeks paling kecil adalah 0, yaitu indeks yang menunjukkan komponen pertama dari array. Indeks 1 menunjukkan komponen ke-2, dan seterusnya. Perhatikan bahwa untuk mengakses komponen pertama dari array
arr_Test
, digunakan sintaks arr_Test
[0]
(sebab nilai awal variabel c adalah 0), dan seterusnya. Satu hal yang perlu
anda waspadai saat menggunakan array, yaitu pastikan bahwa anda tidak mengakses
indeks array yang melebihi jumlah komponen array tersebut, sebab hal ini akan
menjadi bug pada program anda. Misalnya anda mendeklarasikan sebuah array
mempunyai 9 komponen, maka indeks maksimum yang dapat anda gunakan adalah
nama_array[8], sebab indeks dimulai dari 0.Nama sebuah array sebenarnya merupakan pointer ke elemen pertama dari array tersebut, sehingga anda dapat mengakses elemen array tesebut dengan sebuah trik yang disebut dengan pointer arithmetic. Trik ini memanfaatkan nama array yang diperlakukan sebagai pointer. Berikut contohnya: (program sebelumnya diubah untuk memberikan output yg sama)
#include < stdio.h >
#define UINT unsigned int
void
main()
{
UINT komponen = 5;
UINT arr_Test[10];
UINT* pArr = arr_Test;
UINT c;
for( c = 0 ; c < 10 ; c++)
{
*pArr = komponen;
printf("Isi dari komponen ke[%d], adalah: %d \n",c,arr_Test[c]);
pArr++;
komponen++;
}
}
Output yang dihasilkan oleh program ini sama dengan output program sebelumnya. Perhatikan bahwa untuk menunjuk dan memanipulasi komponen dari
arr_Test
kita menggunakan
pointer pArr
. Sintaks pArr++
artinya
naikkan nilai alamat memori yang ditunjukkan pArr
satu
satuan, satu satuan di sini adalah sejumlah byte dari ukuran tipe data pointer
tersebut, karena tipe datanya integer maka alamat yang ditunjuk pointer
tersebut dinaikkan sebanyak 4 byte (pada windows). Menaikkan nilai pArr
satu
satuan sama saja artinya dengan menunjuk ke komponen selanjutnya dalam sebuah
array, inilah yang disebut pointer arithmetic. Komponen pembentuk sebuah array
diletakkan pada alamat yang berurutan di memory, hal inilah yangmenyebabkan kita
dapat melakukan pointer arithmetic. Sampai di sini anda telah mengerti tentang
pointer dan array, tidak terlalu sulit bukan ?
Obrolan
bebas:
"Anda mungkin sudah lelah mengikuti tutorial ini, ... apalagi penulis :(. Jadi... kita break sebentar. Penulis ingin ngobrol sesuatu soal programming. Mungkin anda mengenal John Carmack, programer yang ada di balik ID Software, pembuat game Quake III Arena, RTCW (Return to The Castle Wolfenstein) dan Doom III. Kadang penulis berpikir, bahasa dan tool seperti apa yang digunakan John Carmack untuk membuat game-nya ? sebab sebagian besar atau malah semua game buatan ID software tersedia untuk hampir semua platform komputer, mulai dari Apple sampai PC. Kalau kita pikir, pastilah 'code base' dari semua game itu sama, tidak mungkin dia membuat game dengan 'code base' yang berbeda-beda, sebab biaya pengembangannya akan sangat mahal. Jadi ... apa jawabannya ? "
"Anda mungkin sudah lelah mengikuti tutorial ini, ... apalagi penulis :(. Jadi... kita break sebentar. Penulis ingin ngobrol sesuatu soal programming. Mungkin anda mengenal John Carmack, programer yang ada di balik ID Software, pembuat game Quake III Arena, RTCW (Return to The Castle Wolfenstein) dan Doom III. Kadang penulis berpikir, bahasa dan tool seperti apa yang digunakan John Carmack untuk membuat game-nya ? sebab sebagian besar atau malah semua game buatan ID software tersedia untuk hampir semua platform komputer, mulai dari Apple sampai PC. Kalau kita pikir, pastilah 'code base' dari semua game itu sama, tidak mungkin dia membuat game dengan 'code base' yang berbeda-beda, sebab biaya pengembangannya akan sangat mahal. Jadi ... apa jawabannya ? "
Struct dan Union
Struct adalah bentuk yang sangat penting anda pahami jika anda
ingin memprogram menggunakan C pada sistem operasi windows, sebab sebagian
besar komponen windows mulai dari user interface sampai driver menggunakan
bentuk ini, dan sebagian lagi memanfaatkan union. Pada bagian sebelumnya kita
telah mengenal bentuk penyimpanan data dalam C yaitu dengan menggunakan
variabel dan dengan menggunakan array. Sekarang kita akan mempelajari metode
penyimpanan data yang lebih umum yaitu struct dan union. Pada penyimpanan data
dengan array yang kita pelajari sebelumnya, kita hanya dapat menyimpan data
dengan menggunakan 1 macam tipe data yaitu tipe data dari array tersebut.
Penyimpanan data menggunakan struct memberi kita fleksibilitas yang lebih baik,
karena kita dapat menyimpan data dengan tipe data yang berbeda ke dalam 1
struct. Struct pada dasarnya merupakan sebuah tipe data baru yang didefinisikan
oleh programer yang membuatnya. Sintaks yang digunakan untuk mendeklarasikan
sebuah struct adalah:
pada sintaks di atas, tipe_data adalah tipe data dari elemen struct, yang telah dikenali secara internal oleh compiler, misalnya int. Pada sintaks di atas,
Anda dapat menggunakan sintaks yang mempersingkat pembuatan variabel bertipe struct tertentu dengan menggunakan keyword typedef12. Dengan keyword ini, anda tidak perlu lagi memberikan kata struct di depan nama struct tersebut. Sintaksnya sbb:
dengan teknik ini anda tinggal menggunakan sintaks:
untuk membuat sebuah variabel dengan tipe-data
Sintaks seperti ini banyak digunakan dalam pemrograman C pada windows. Untuk mengakses isi dari elemen sebuah struct anda dapat menggunakan member of operator , yaitu:
jika variabel yang anda miliki ternyata adalah sebuah pointer, misalnya:
Hal yang lain yang perlu anda perhatikan adalah, anda tidak dapat langsung menggunakan sebuah struct tanpa membuat objek dari struct tersebut, sebab
struct nama_struct{
tipe_data elemen_1;
tipe_data elemen_2;
...
tipe_data
elemen_n;}variabel_struct1,variabel_struct2,.. ;
pada sintaks di atas, tipe_data adalah tipe data dari elemen struct, yang telah dikenali secara internal oleh compiler, misalnya int. Pada sintaks di atas,
variabel_struct1
dan variabel_struct2
adalah
variabel dengan tipe data struct nama_struct, variabel ini tidak wajib, jika
anda lebih suka membuat variabel dengan tipe data struct ini di tempat lain,
anda dapat membuatnya pada baris program sesudah deklarasi struct ini. Anda
harus menggunakan sintaks:struct nama_struct variabel_struct;
Anda dapat menggunakan sintaks yang mempersingkat pembuatan variabel bertipe struct tertentu dengan menggunakan keyword typedef12. Dengan keyword ini, anda tidak perlu lagi memberikan kata struct di depan nama struct tersebut. Sintaksnya sbb:
typedef struct nama_struct{
tipe_data
nama_elemen_1;
tipe_data
nama_elemen_2;
...
tipe_data
nama_elemen_n;}nama_alias, *nama_alias_pointer;
dengan teknik ini anda tinggal menggunakan sintaks:
nama_alias variabel_struct;
untuk membuat sebuah variabel dengan tipe-data
struct
nama_struct
. Pada sintaks di atas *nama_alias_pointer
adalah
opsional, keyword ini dapat anda gunakan jika anda ingin membuat variabel
bertipe pointer ke struct nama_struct
. Untuk
melakukannya, anda tinggal menggunakan sintaks:nama_alias_pointer pointer_struct;
Sintaks seperti ini banyak digunakan dalam pemrograman C pada windows. Untuk mengakses isi dari elemen sebuah struct anda dapat menggunakan member of operator , yaitu:
.
(titik).
Misalnya untuk mengakses elemen_1
pada
variabel variabel_struct1
anda
akan menggunakan sintaks:variabel_struct1
.elemen_1
jika variabel yang anda miliki ternyata adalah sebuah pointer, misalnya:
pointer_struc
maka
untuk mengakses elemennya, anda harus menggunakan member of operator dalam
bentuk lain, yaitu ->
.
Sebagai contoh, untuk mengakses elemen_2
pada
variabel pointer_struct anda akan menggunakan sintaks:pointer_struct->elemen_2
Hal yang lain yang perlu anda perhatikan adalah, anda tidak dapat langsung menggunakan sebuah struct tanpa membuat objek dari struct tersebut, sebab
struct
nama_struct
juga adalah tipe data seperti halnya int, bukan merupakan
variabel, jadi seperti pada int, anda harus membuat variabel dulu sebelum
menggunakannya.
12 typedef
dapat digunakan untuk mengganti makro
adalah:
#define
untuk
mempersingkat penulisan tipe data, misalnya, sintaks yang ekivalen dengan#define UINT unsigned int
adalah:
typedef unsigned int UINT ;
Selanjutnya
kita akan membahas sebuah program yang memanfaatkan struct. Berikut ini source
code program tersebut:
#include < stdio.h >
#include < malloc.h >
#include < string.h >
typedef unsigned int UINT;
typedef struct Microprocessor{
UINT kecepatan;
UINT harga;
char nama[20];} uP, *puP; /* deklarasi
struktur */
void harga_per_MHz(puP pProc); /* deklarasi
fungsi */
void main()
{
puP Duron = malloc(sizeof(uP));/*
alokasikan memori */
uP Celeron;
Duron->harga = 350000;
Duron->kecepatan = 1100;
strcpy(Duron->nama, "Duron");
Celeron.harga = 700000;
Celeron.kecepatan = 2000;
strcpy(Celeron.nama, "Celeron");
harga_per_MHz(Duron);
harga_per_MHz(&Celeron);
free(Duron);/* bebaskan memori yang
dialokasikan */
}
void harga_per_MHz(puP pProc) /* definisi
fungsi */
{
UINT harga_MHz =
(pProc->harga)/(pProc->kecepatan) ;
printf("harga per MHz dari %s adalah
%d \n",
pProc->nama, harga_MHz);
}
Output dari program di atas adalah:
harga per MHz dari Duron adalah 318
harga per MHz dari Celeron adalah 350
Pada source code di atas ada dua file header yang baru kita gunakan, yaitu malloc.h dan string.h. File malloc.h digunakan untuk menyediakan kemampuan bagi program kita untuk mengalokasikan memori secara dinamis menggunakan fungsi malloc() dan free. Fungsi
malloc(size_t
size)
adalah fungsi untuk
mengalokasikan memori sebesar size
byte. Alokasi memori dinamis ini
diperlukan karena puP Duron
adalah sebuah pointer, dan seperti yang
dijelaskan sebelumya, setiap pointer harus diinisialisasi untuk menunjuk alamat
memori tertentu atau diinisialisasi dengan 0 (dideklarasikan dengan nilai nol)
agar pointer tersebut tidak menjadi stray pointer, yang dapat menimbulkan bug.
Memori yang dialokasikan secara dinamis harus "dibebaskan" setelah
digunakan dan tidak diperlukan lagi dengan fungsi free()
, jika tidak maka memori tersebut tidak akan
dapat dipakai lagi selama program kita masih berjalan, hal ini lah yang
disebut memory leak. Memory leak adalah salah satu bug yang paling
berbahaya, apalagi jika bug ini terjadi pada blok pernyataan yang mengalami
perulangan, karena akan membuat sistem kita kehilangan "free memory"
(memory yang dapat dipakai oleh aplikasi lain) dalam jumlah besar, dan bisa
menimbulkan hang. Jadi berhati- hatilah saat menggunakan alokasi memori
dinamis, pastikan bahwa setiap fungsi malloc(size_t
size)
diimbangi oleh
fungsi free()
. File string.h digunakan untuk menyediakan
kemampuan memindahkan string (kelompok karakter) dari satu variabel ke variabel
lain atau dari sebuah string ke variabel yang dapat menyimpan string. Hal ini
dilakukan dengan fungsi strcpy()
. Pada sourcecode di atas kita memindahkan
string ke elemen nama
dari variabel bertipe struct Microprocessor
yang kita buat.Sekarang kita akan membahas source code di atas dengan lebih detail. Pada bagian awal program, kita mendeklarasikan sebuah struct dengan nama
Microprocessor
, struct ini mengandung 3 elemen, yaitu
kecepatan, harga dan nama. Pada deklarasi struct itu juga kita memberi 2 nama
alias untuk struct ini, yaitu uP yang merupakan nama alias "biasa",
dan puP yang merupakan pointer ke struct dengan tipe Microprocessor. Setelah itu
dideklarasikan sebuah fungsi tanpa return value yang mempunyai satu parameter
dengan tipe pointer ke struct Microprocessor (fungsi harga_per_MHz), fungsi ini
menggunakan passing by pointer seperti yang sudah kita bahas sebelumnya. Pada
definisi fungsi ini tampak bahwa fungsi ini akan menghitung harga per-MHz untuk
setiap variabel (bertipe struct Microprocessor) melalui pointer ke variabel
tersebut yang menjadi parameter inputnya. Hasil perhitungan ini kemudian di
tampilkan ke user. Pada fungsi main()
, kita mendeklarasikan 2 buah variabel bertipe
struct Microprocessor, 1 secara langsung, yaitu Celeron
, dan satu secara tidak langsung, yaitu Duron
. Kemudian kedua variabel ini diisi seluruh
elemennya dengan nilai yang kita inginkan dengan menggunakan operator yang
sesuai, setelah itu fungsi harga_per_MHz(...)
dipanggil untuk menampilkan harga per MHz
dari setiap variabel ini. Fungsi harga_per_MHz
menggunakan parameter bertipe pointer ke
struct, itulah sebabnya saat kita memanggil fungsi ini pada variabel Celeron
, harus digunakan & (address of operator)
agar kita memberikan masukan yang tepat ke fungsi tersebut, yaitu pointer ke
struct yang kita miliki. Address of operator akan memberikan alamat dari suatu
variabel, hal ini sama saja artinya dengan memberikan pointer ke variabel yang
kita inginkan. Pembahasan mengenai struct hanya sampai di sini saja, untuk
mengetahui lebih lanjut anda dapat membaca referensi yang ada pada akhir
tulisan ini.Sekarang kita akan membahas sebuah bentuk yang dinamakan union. Union pada dasarnya mirip dengan struct, bahkan sintaks untuk deklarasinya sama saja. Yang membedakan struct dan union adalah cara kerjanya. Dalam sebuah struct, seluruh elemen struct tersebut berisi sesuatu pada suatu saat, sedangkan dalam sebuah union, pada satu saat hanya ada ada 1 elemen yang dapat digunakan. Dalam sebuah union biasanya elemennya mempunyai tipe data yang berbeda-beda. Bagi anda yang pernah menggunakan bahasa pemrograman Visual Basic, union akan tampak analog dengan variant. Union mempunyai cara kerja yang mirip "variabel template", karena kita dapat memasukkan variabel dengan tipe data yang telah kita definisikan sebagai elemen union tersebut ke dalam union tersebut pada saat run time (saat program sedang berjalan) dan pada satu saat hanya satu elemen saja yang dapat digunakan. Di bawah ini adalah sintaks untuk mendeklarasikan union :
union nama_union{
tipe_data
elemen_1;
tipe_data
elemen_2;
...
tipe_data
elemen_n;}variabel_union1,variabel_union2,.. ;
atau dengan menggunakan keyword typedef:
typedef union nama_union{
tipe_data
elemen_1;
tipe_data
elemen_2;
...
tipe_data
elemen_n;}nama_alias, *nama_alias_ponter;
Catatan:
nama_union maupun nama_struct pada deklarasi sebuah struct atau union adalah opsional, anda dapat menggunakan sebuah nama untuk sebuah struktur dan dapat mengabaikannya, tergantung dari kemauan anda.
nama_union maupun nama_struct pada deklarasi sebuah struct atau union adalah opsional, anda dapat menggunakan sebuah nama untuk sebuah struktur dan dapat mengabaikannya, tergantung dari kemauan anda.
Selanjutnya
kita akan membahas sebuah penggunaan union. Berikut ini adalah sebuah contoh
implementasinya.
Output dari program di atas adalah:
Contoh di atas adalah contoh penggunaan union yang umum, yaitu sebagai variabel template. Pada contoh di atas, dideklarasikan sebuah struct dengan nama data_holder dan nama alias generic_tag yang salah satu komponennya adalah union dengan nama shared_tag, union ini dapat menyimpan data dengan tipe char, float atau integer (int). Didefinisikan beberapa konstanta yang digunakan sebagai "pengenal" untuk data yang dimasukkan ke union ini, yaitu CHARACTER, FLOAT, INTEGER. Pada fungsi
#include < stdio.h >
#define CHARACTER 'C'
#define INTEGER 'I'
#define FLOAT 'F'
typedef struct data_holder{
char type;
union shared_tag {
char c;
int i;
float f;
} shared;
}generic_tag;
void print_function( generic_tag generic );
void main()
{
generic_tag var;
var.type =
CHARACTER;
var.shared.c = '$';
print_function( var );
var.type =
FLOAT;
var.shared.f = (float) 12345.67890;
print_function( var );
var.type =
'x';
var.shared.i = 111;
print_function( var );
}
void print_function( generic_tag generic )
{
printf("\n\nThe generic value is...");
switch( generic.type )
{
case CHARACTER: printf("%c", generic.shared.c);
break;
case INTEGER: printf("%d", generic.shared.i);
break;
case FLOAT: printf("%f", generic.shared.f);
break;
default: printf("an unknown type: %c\n",
generic.type);
break;
}
}
Output dari program di atas adalah:
The
generic value is...$
The generic value is...12345.678711
The generic value is...an unknown type: x
Contoh di atas adalah contoh penggunaan union yang umum, yaitu sebagai variabel template. Pada contoh di atas, dideklarasikan sebuah struct dengan nama data_holder dan nama alias generic_tag yang salah satu komponennya adalah union dengan nama shared_tag, union ini dapat menyimpan data dengan tipe char, float atau integer (int). Didefinisikan beberapa konstanta yang digunakan sebagai "pengenal" untuk data yang dimasukkan ke union ini, yaitu CHARACTER, FLOAT, INTEGER. Pada fungsi
main()
, didefinisikan sebuah variabel struct data_holder dengan
nama var. Elemen type dari struct ini kemudian isinya diubah-ubah pada saat
yang bersamaan, tergantung data yang dimasukkan ke elemen shared yang merupakan
sebuah variabel union. Setelah itu, isi dari union yang ada pada var
ditampilkan kepada user dengan menggunakan fungsi print_function. Fungsi ini
bekerja dengan cara mengecek tipe data yang telah dimasukkan ke var melalui
elemen type yang dimiliki var saat ini. Pengecekan ini dilakukan melalui sebuah
peryataan menggunakan switch. Jika anda masih kesulitan memahami penggunaan
union, hal itu tidak terlalu mengganggu, sebab feature ini jarang digunakan,
tujuan penulis hanya ingin memperkenalkan union kepada anda :).
Lebih Lanjut Tentang Fungsi
Pada bagian ini kita akan membahas penggunaan fungsi dengan
memanfaatkan pointer. Nama sebuah fungsi pada dasarnya adalah pointer ke alamat
fungsi tersebut. Untuk mempermudah pemahaman konsep ini, marilah kita coba
implementasi berikut:
Contoh output program di atas adalah:
#include < stdio.h >
#define FALSE 0
#define TRUE 1
void tukar(int * pX, int * pY);
void kuadrat(int * pX, int * pY);
void reset(int * pX, int * pY);
void main()
{
int keluar = FALSE;
int inrange = TRUE;
int var1;
int var2;
int pilihan;
void (*ptr_func) (int * , int *);
while (keluar != TRUE)
{
if (keluar == TRUE)
break;
printf("variabel pertama : ");
scanf("%d", &var1);
printf("variabel
pertama : ");
scanf("%d", &var2);
printf("Ketikkan
fungsi yang anda pilih (1-3) ");
scanf("%d", &pilihan);
switch(pilihan)
{
case 1:
ptr_func = tukar ;
inrange = TRUE;
break;
case 2:
ptr_func = kuadrat;
inrange = TRUE;
break;
case 3:
ptr_func = reset;
inrange = TRUE;
break;
default:
printf("Fungsi yang anda pilih tidak
didefinisikan\n");
inrange = FALSE;
break;
}
if(inrange)
{
printf("Variabel 1 dan 2 sebelum fungsi di panggil:
\n");
printf("Variabel 1: %d ; variabel 2: %d \n\n",
var1, var2);
ptr_func(&var1, &var2);
printf("Variabel
1 dan 2 setelah fungsi di panggil: \n");
printf("Variabel 1: %d ; variabel 2: %d \n\n",
var1, var2);
}
printf("Apakah anda ingin mengakhiri program (1 =
ya, 0 = tidak) ");
scanf("%d",&keluar);
}
}
void tukar(int * pX, int * pY)
{
int temp;
printf("tukar function called \n");
printf("Menukar variabel 1 dan variabel 2\n");
temp = *pX;
*pX = *pY;
*pY = temp;
}
void kuadrat(int * pX, int * pY)
{
printf("kuadrat function called \n");
*pX
= (*pX)*(*pX);
*pY = (*pY)*(*pY);
}
void reset(int * pX, int * pY)
{
printf("reset function called \n");
*pX = 0;
*pY = 0;
}
Contoh output program di atas adalah:
variabel pertama : 3
variabel pertama : 4
Ketikkan fungsi yang anda pilih (1-3) 1
Variabel 1 dan 2 sebelum fungsi di panggil:
Variabel 1: 3 ; variabel 2: 4
tukar
function called
Menukar variabel 1 dan variabel 2
Variabel 1 dan 2 setelah fungsi di panggil:
Variabel 1: 4 ; variabel 2: 3
Apakah
anda ingin mengakhiri program (1 = ya, 0 = tidak) 1
Peringatan
!
Berhati-hatilah saat menjalankan program di atas, sebab program ini tidak bug free, masukkan input sesuai dengan rentang nilai yang diminta. Jika anda menyalahi aturan ini maka bisa saja muncul bug yang akan membuat komputer anda hang.
Berhati-hatilah saat menjalankan program di atas, sebab program ini tidak bug free, masukkan input sesuai dengan rentang nilai yang diminta. Jika anda menyalahi aturan ini maka bisa saja muncul bug yang akan membuat komputer anda hang.
Contoh di atas
mengeksploitasi kemampuan bahasa C menggunakan pointer fungsi. Pointer fungsi
seperti yang telah dijelaskan diatas, adalah pointer juga, tetapi alamat yang
ditunjuk oleh pointer tersebut bukan alamat variabel, tetapi alamat sebuah fungsi.
Format deklarasi sebuah pointer fungsi adalah:
maka and mendeklarasikan sebuah fungsi dengan return value bertipe pointer ke
namun hal ini tidak ada bedanya, sebab keduanya diperlakukan sama saja oleh bagi compiler C. Contoh di atas mungkin cukup sulit dipahami, anda perlu melihat kembali bagian pointer jika masih bingung dengan sintaks yang digunakan. Sintaks
Secara garis besar, program di atas mula-mula mengeset variabel keluar menjadi
return_type
(*pointer_fungsi) (tipe_data1 , tipe_data2 );
return_type
adalah tipe data dari return value (nilai yang
dikembalikan/ dihasilkan sebuah fungsi, anda masih ingat kan ?), pointer_fungsi
adalah nama dari pointer fungsi yang diinginkan, tipe_data1
adalah tipe data dari parameter pertama fungsi yang
ditunjuk oleh pointer fungsi yang kita deklarasikan, tipe_data2
adalah tipe data parameter kedua dari fungsi yang
ditunjuk oleh pointer fungsi yang kita deklarasikan. Jumlah tipe data parameter
yang digunakan bisa saja 0 atau bukan 2, tergantung dari format fungsi yang
ditunjuk oleh pointer fungsi yang kita buat. Pointer fungsi dapat menunjuk ke
berbagai macam fungsi, asalkan fungsi-fungsi tersebut mempunyai return type dan
tipe data parameter yang sama persis, seperti yang diperlihatkan pada contoh di
atas, pointer ke fungsi yang diberi nama ptr_func
menunjuk ke tiga macam fungsi yang berbeda, yaitu
fungsi tukar, kuadrat dan reset, tergantung pilihan yang diketikkan user.
Mungkin anda bertanya-tanya mengapa begitu banyak tanda kurung, hal ini
dibutuhkan, sebab jika anda menuliskannya seperti inireturn_type
* pointer_fungsi (tipe_data1 , tipe_data2 );
maka and mendeklarasikan sebuah fungsi dengan return value bertipe pointer ke
return_type
, bukan pointer fungsi seperti yang kita inginkan. Anda juga
mungkin bertanya, mengapa kita tidak perlu menggunakan indirection operator (*)
untuk memanggil fungsi yang kita inginkan dari pointer-nya. Anda bisa saj
melakukan- nya jika anda menginginkannya, seperti ini:(*ptr_func)(&var1,&var2);
namun hal ini tidak ada bedanya, sebab keduanya diperlakukan sama saja oleh bagi compiler C. Contoh di atas mungkin cukup sulit dipahami, anda perlu melihat kembali bagian pointer jika masih bingung dengan sintaks yang digunakan. Sintaks
*pX =
(*pX)*(*pX);
maksudnya adalah kalikan nilai yang ditunjuk oleh
pointer pX dengan nilainya sendiri, kemudian kopi nilai tersebut ke variabel
itu sendiri (variabel yang ditunjuk oleh pX).Secara garis besar, program di atas mula-mula mengeset variabel keluar menjadi
FALSE
sehingga saat perulangan while(keluar
!= TRUE)
mulai dieksekusi, program akan
berulang-ulang menampilkan tampilan yang ada di dalam while, sampai user
memilih untuk keluar (keluar == TRUE
) , pada saat itu, perintah break yang ada di dalam looping
while (di bawah if (keluar == TRUE)
) akan dieksekusi, sehingga program keluar dari looping
tersebut. Di dalam looping inilah terdapat penggunaan pointer fungsi.
Obrolan
bebas:
"Sampai saat ini kita telah mempelajari banyak konsep yang sangat penting, mulai dari variabel 'biasa' sampai pointer fungsi, dan penulis yakin pasti cukup melelahkan dan membingungkan :( . Tapi anda tidak perlu merasa tertekan , karena konsep itu semua digunakan jika anda berniat menjadi programer yang hebat. Setelah memahami tutorial ini, mudah-mudahan anda tidak bermasalah lagi dengan apa yang disebut pemrograman C. Setelah membaca tutorial assembly nanti, pemahaman anda tentang bahasa C akan menjadi setingkat lebih tinggi sebab banyak hal, seperti pointer fungsi yang baru saja di bahas sebenarnya datang dari penggunaannya dalam pemrograman assembly. Mungkin anda juga penasaran, mengapa tutorial ini belum juga masuk ke pemrograman windows. Anda perlu bersabar sebelum sampai ke sana, sebab hal itu adalah salah satu hal yang penulis sendiri rasakan sangat sulit dipahami jika konsep-konsep seperti yang dijelaskan di sini tidak dikuasai dengan baik. penulis sendiri butuh waktu 1 bulan untuk benar-benar memahami apa yang dilakukan setiap baris dari pemrograman dengan bahasa C pada windows dengan menggunakan windows API :( . So keep fighting till the end"
"Sampai saat ini kita telah mempelajari banyak konsep yang sangat penting, mulai dari variabel 'biasa' sampai pointer fungsi, dan penulis yakin pasti cukup melelahkan dan membingungkan :( . Tapi anda tidak perlu merasa tertekan , karena konsep itu semua digunakan jika anda berniat menjadi programer yang hebat. Setelah memahami tutorial ini, mudah-mudahan anda tidak bermasalah lagi dengan apa yang disebut pemrograman C. Setelah membaca tutorial assembly nanti, pemahaman anda tentang bahasa C akan menjadi setingkat lebih tinggi sebab banyak hal, seperti pointer fungsi yang baru saja di bahas sebenarnya datang dari penggunaannya dalam pemrograman assembly. Mungkin anda juga penasaran, mengapa tutorial ini belum juga masuk ke pemrograman windows. Anda perlu bersabar sebelum sampai ke sana, sebab hal itu adalah salah satu hal yang penulis sendiri rasakan sangat sulit dipahami jika konsep-konsep seperti yang dijelaskan di sini tidak dikuasai dengan baik. penulis sendiri butuh waktu 1 bulan untuk benar-benar memahami apa yang dilakukan setiap baris dari pemrograman dengan bahasa C pada windows dengan menggunakan windows API :( . So keep fighting till the end"
Selanjutnya
kita akan membahas sebuah program yang menggunakan pointer ke fungsi yang mirip
dengan yang banyak digunakan dalam pemrograman windows.
#include < stdio.h >
typedef unsigned int UINT;
typedef UINT (*FPTR) (UINT var1, UINT var2);
typedef struct Input { FPTR pFunc;
UINT param1;
UINT param2;} INPUT ;
UINT kali(UINT faktor1, UINT faktor2)
{
return (faktor1 * faktor2);
}
void Hitung(INPUT input)
{
int hasil = input.pFunc(input.param1, input.param2);
printf("Hasil perhitungan adalah: %d \n",
hasil);
}
void main()
{
INPUT in;
in.pFunc = kali;
in.param1 = 10;
in.param2 = 20;
Hitung(in);
}
Output dari program di atas adalah:
Hasil perhitungan adalah: 200
Program di atas menggunakan beberapa sintaks yang "baru" misalnya sintaks untuk mempersingkat penulisan pointer fungsi, yaitu:
typedef UINT (*FPTR) (UINT var1, UINT var2);
sintaks ini maksudnya adalah, FPTR adalah sebuah sintaks untuk menyatakan pointer fungsi yang return value-nya bertipe UINT dan memiliki dua parameter bertipe UINT. Selanjutnya dideklarasikan sebuah struct dengan nama
Input
dengan
elemen-elemen:- Sebuah
variabel bertipe pointer ke fungsi (FPTR)
- Dua
buah variabel bertipe UINT (unsigned int)
Kemudian dideklarasikan dua buah fungsi yaitu
fungsi
Kali
dan Hitung
. Fungsi Kali
bekerja dengan mengalikan kedua parameter
inputnya. Fungsi Hitung
adalah sebuah fungsi yang menerima input
berupa objek bertipe struct Input
, mengalikan kedua elemen struct tersebut yang
bertipe UINT dan kemudian menampilkan hasilnya. Pada fungsi main()
, dibuat sebuah objek bertipe struct Input,
kemudian objek tersebut dijadikan parameter
untuk memanggil fungsi Hitung. Sampai di sini anda sudah memiliki sebagian
besar skill yang dibutuhkan untuk melakukan pemrograman C pada Windows dengan
menggunakan Windows API (Windows Application Programming Interface).
Arsitektur Driver Windows 2000/XP
Penulis mohon maaf karena semestinya ada bagian pendahuluan yang
menerangkan tentang Windows API (Application Programming Interface) sebelum
masuk kepada bagian ini, tetapi akibat keterbatasan waktu maka bagian tersebut
belum sempat disertakan. Anda tidak perlu khawatir sebab hal tersebut tidak akan
mengurangi pemahaman anda terhadap source code driver yang dibahas. Dalam
beberapa saat ke depan mudah-mudahan bagian tersebut dapat disertakan dalam
tulisan ini setelah tulisan ini diupdate :). Berikut ini kita akan membahas
source code driver pada artikel Tutorial Membuat Patch dalam bentuk Driver Pada
Windows 2000/XP.
/*
patch.c -- prototipe Patch
project started 9 Feb 2003 by - Pinczakko -
*/
#include "ntddk.h"
#define FILE_DEVICE_UNKNOWN 0x00000022
#define PCI_ADDR_PORT 0xCF8
#define PCI_DATA_PORT 0xCFC
#define REG_ADDR 0x80000050
#define MASK 0x00000040
void tUnloadDriver(PDRIVER_OBJECT
DriverObject);
NTSTATUS tDispatchCreate(IN PDEVICE_OBJECT
DeviceObject,
IN PIRP Irp);
NTSTATUS tDispatchClose(IN PDEVICE_OBJECT
DeviceObject,
IN PIRP Irp);
void PatchPCI(ULONG reg_addr, ULONG mask);
NTSTATUS DriverEntry(IN PDRIVER_OBJECT
DriverObject,
IN PUNICODE_STRING RegistryPath)
/*++
Routine Description:
This routine is called when the driver is
loaded by NT.
Arguments:
DriverObject - Pointer to driver object
created by system.
RegistryPath - Pointer to the name of the services node
for this driver.
Return Value:
The function value is the final status from
the initialization operation.
--*/
{
NTSTATUS ntStatus;
UNICODE_STRING uszDriverString;
UNICODE_STRING uszDeviceString;
PDEVICE_OBJECT pDeviceObject;
// Point uszDriverString at the driver name
RtlInitUnicodeString(&uszDriverString,
L"\\Device\\Patch");
// Create and initialize device object
ntStatus = IoCreateDevice(DriverObject,
0,
&uszDriverString,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&pDeviceObject);
if(ntStatus != STATUS_SUCCESS)
return ntStatus;
// Point uszDeviceString at the device name
RtlInitUnicodeString(&uszDeviceString,
L"\\DosDevices\\Patch");
// Create symbolic link to the user-visible
name
ntStatus = IoCreateSymbolicLink(&uszDeviceString,
&uszDriverString);
if(ntStatus != STATUS_SUCCESS)
{
// Delete device object if not successful
IoDeleteDevice(pDeviceObject);
return ntStatus;
}
//Patch the chipset on driver loading stage
PatchPCI(REG_ADDR ,MASK);
// Load structure to point to IRP handlers...
DriverObject->DriverUnload = tUnloadDriver;
DriverObject->MajorFunction[IRP_MJ_CREATE] =
tDispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] =
tDispatchClose;
// Return success
return ntStatus;
}
NTSTATUS tDispatchCreate(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information=0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_SUCCESS);
}
NTSTATUS tDispatchClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information=0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_SUCCESS);
}
void tUnloadDriver(PDRIVER_OBJECT
DriverObject)
{
UNICODE_STRING uszDeviceString;
IoDeleteDevice(DriverObject->DeviceObject);
RtlInitUnicodeString(&uszDeviceString,
L"\\DosDevices\\Patch");
IoDeleteSymbolicLink(&uszDeviceString);
}
void PatchPCI(ULONG reg_addr, ULONG mask)
{
//Patch the chipset
__asm
{
pushfd ;//save all flags and regs
pushad
mov eax,reg_addr ;//fetch the address of the
regs to be patched
mov dx,PCI_ADDR_PORT ;//fetch the input port addr of PCI
cfg space
out dx,eax
mov dx,PCI_DATA_PORT
in eax,dx
or eax,mask ;//mask the regs value (activate certn. bits)
out dx,eax
popad ;//restore all flags
popfd
}
}
Warning !
Jangan mencoba menginstalasi driver yang dihasilkan oleh source code di atas pada sistem anda, karena dapat membuat sistem anda rusak.
Jangan mencoba menginstalasi driver yang dihasilkan oleh source code di atas pada sistem anda, karena dapat membuat sistem anda rusak.
Pada program di atas, entry point program ada pada fungsi
DriverEntry , fungsi ini dipanggil oleh Windows saat driver yang dihasilkan
dari source code ini di-load oleh windows saat start-up. Windows memanggil
fungsi ini dengan menyertakan beberapa parameter, yaitu: sebuah struct dengan
tipe PDRIVER_OBJECT dan sebuah struct dengan tipe PUNICODE_STRING. Keyword IN
sebenarnya diabaikan oleh compiler saat source code ini di-compile. Keyword
tersebut hanya digunakan untuk memperjelas saat kita membaca source code. Kita
akan membahas Source code ini mulai dari bagian awal. Pada awal source code
terdapat beberapa definisi konstanta, tentang arti definisi ini telah
dijelaskan pada artikel Tutorial Membuat Patch dalam bentuk Driver Pada Windows
2000/XP. Namun, konstanta: FILE_DEVICE_UNKNOWN perlu dijelaskan di sini.
Konstanta ini digunakan sebagai pengenal bagi driver yang kita buat, kita
menggunakan FILE_DEVICE_UNKNOWN karena driver kita bukan merupakan driver
spesifik untuk device tertentu yang telah dikenali secara internal oleh
Windows, misalnya Hard drive atau mouse. Selanjutnya 3 buah fungsi minimum yang
harus dimiliki oleh sebuah driver, nama dari fungsi-fungsi ini tidak harus
seperti yang diperlihatkan pada source code di atas, sebab ketiga fungsi ini
ditunjuk oleh pointer yang ada dalam fungsi DriverEntry , jadi jika anda
merubah namanya, anda hanya perlu merubah nama pointer fungsi yang ada pada
fungsi DriverEntry. Selanjutnya kita melangkah ke inti dari program ini yaitu
fungsi DriverEntry. Fungsi ini sebenarnya adalah fungsi inisialisasi driver.
Inisialisasi tersebut kita lakukan dengan cara melakukan apa yang kita inginkan
pada fungsi ini, saat membuat patch, kita ingin mem-patch beberapa register,
dan hal itulah yang kita lakukan pada source code ini dengan memanggil fungsi
PatchPCI. Pada awal fungsi ini didefinisikan beberapa variabel, yaitu:
NTSTATUS adalah sebuah tipe data yang digunakan secara internal oleh Windows untuk menangani fungsi-fungsi yang berkaitan dengan driver, tipe data ini adalah tipe data 32 bit. Variabel ntStatus adalah variabel yang digunakan untuk mengecek apakah proses loading (inisialisasi) driver ini berhasil, jika berhasil maka variabel ini akan bernilai STATUS_SUCCESS setelah fungsi IoCreateDevice dipanggil. Sedangkan kedua variabel bertipe UNICODE_STRING digunakan untuk mengatur nama driver ini yang akan muncul di registry saat driver ini telah berhasil di-load. Variabel pDeviceObject adalah variabel yang digunakan untuk menyimpan pointer ke struct bertipe DEVICE_OBJECT yang dihasilkan setelah kita berhasil me-load driver kita (ntStatus bernilai STATUS_SUCCESS), atau dengan kata lain pointer ke driver kita.
Fungsi IoCreateDevice adalah fungsi inti yang menginisialisasi driver ini. Fungsi ini digunakan untuk "membuat driver", cara kerjanya adalah sebagai berikut:
NTSTATUS ntStatus;
UNICODE_STRING uszDriverString;
UNICODE_STRING uszDeviceString;
PDEVICE_OBJECT pDeviceObject;
NTSTATUS adalah sebuah tipe data yang digunakan secara internal oleh Windows untuk menangani fungsi-fungsi yang berkaitan dengan driver, tipe data ini adalah tipe data 32 bit. Variabel ntStatus adalah variabel yang digunakan untuk mengecek apakah proses loading (inisialisasi) driver ini berhasil, jika berhasil maka variabel ini akan bernilai STATUS_SUCCESS setelah fungsi IoCreateDevice dipanggil. Sedangkan kedua variabel bertipe UNICODE_STRING digunakan untuk mengatur nama driver ini yang akan muncul di registry saat driver ini telah berhasil di-load. Variabel pDeviceObject adalah variabel yang digunakan untuk menyimpan pointer ke struct bertipe DEVICE_OBJECT yang dihasilkan setelah kita berhasil me-load driver kita (ntStatus bernilai STATUS_SUCCESS), atau dengan kata lain pointer ke driver kita.
Fungsi IoCreateDevice adalah fungsi inti yang menginisialisasi driver ini. Fungsi ini digunakan untuk "membuat driver", cara kerjanya adalah sebagai berikut:
- Parameter
pertama dari fungsi ini adalah "template driver" yang disediakan
oleh windows bagi driver yang akan "dibuat". "template
driver" ini disediakan windows dalam bentuk parameter pertama bagi
fungsi DriverEntry yang kita buat (yang akan dipanggil oleh windows saat
loading driver). "template driver" ini sebenarnya sebuah struct
yang isinya pointer ke fungsi yang kita definisikan sendiri pada
baris-baris program selanjutnya. "template driver" inilah yang
kita modifikasi pada baris :
DriverObject->DriverUnload = tUnloadDriver;
DriverObject->MajorFunction[IRP_MJ_CREATE] = tDispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = tDispatchClose;
dengan source code ini, kita membuat "template driver" yang diberikan oleh windows menunjuk ke fungsi-fungsi yang kita inginkan. Fungsi tUnloadDriver dipanggil saat driver kita akan di-unload, saat windows akan shutdown, pada fungsi ini yang kita lakukan hanyalah cleanup memory dan resources yang digunakan oleh driver ini. Fungsi tDispatchCreate dipanggil pada saat ada software pada user mode yang membuka akses ke driver kita, karena kita tidak beururusan dengan software di user mode maka dalam driver ini, fungsi ini hanya mengembalikan nilai STATUS_SUCCESS. Fungsi tDispatchClose dipanggil pada saat ada software pada user mode yang menutup akses ke driver kita, karena kita tidak beururusan dengan software di user mode maka dalam driver ini, fungsi ini hanya mengembalikan nilai STATUS_SUCCESS - Parameter
kedua adalah jumlah memory yang dibutuhkan oleh driver, namun kita tidak
membutuhkan memory apapun untuk driver ini sehingga parameter tersebut 0.
- Parameter
ke-3 adalah nama dari driver kita yang akan tampak oleh user mode
application. Dalam kasus ini kita tidak perlu membahasnya karena tidak ada
user mode application yang menggunakan driver kita.
- Parameter
ke-4 adalah tipe device dari driver kita, karena driver ini tidak memiliki
device maka digunakan FILE_DEVICE_UNKNOWN. Jika device yang kita buat
adalah device yang dikenali windows, misalnya hard drive maka nilai
variabel ini akan berbeda. Untuk penjelasan lebih lanjut silahkan membaca
file help Windows 2000 Driver Development Kit.
- Parameter
ke-5 adalah karakteristi device yang secara internal dikenali oleh windows,
tetapi device kita tidak dikenali, sehingga harus diberi nilai 0.
- Parameter
ke-6 adalah parameter yang berkaitan dengan kemampuan driver kita diakses
dari usermode, jika dapat diakses oleh beberapa aplikasi pada saat
bersamaan maka nilainya FALSE. Sebenarnya dalam kasus seperti ini, nilai
parameter ini tidak punya pengaruh sebab kita tidak berurusan dengan
software di user mode.
- Parameter
terakhir adalah pointer ke driver yang dihasilkan oleh fungsi ini. Pointer
ini adalah pointer ke struct DEVICE_OBJECT yang dihasilkan oleh fungsi
ini. Struct ini adalah struct yang menyimpan karakteristik driver kita.
Fungsi PatchPCI akan anda pahami setelah membaca bagian Tutorial Bahasa Assembly, jadi tidak akan dibahas di sini. Fungsi RtlInitUnicodeString digunakan untuk menyalin string, mirip fungsi strcpy pada pemrograman C yang telah kita pelajari. Dengan penjelasan ini semoga anda sudah memahami arsitektur driver windows 2000/XP secara umum.
Obrolan
bebas:
"Selamat. Sekarang anda telah memiliki sebagian besar kemampuan dasar yang dibutuhkan untuk menjadi seorang programer bahasa C yang profesional, yang anda butuhkan adalah berlatih membuat beberapa program agar anda semakin memahami bagaimana bahasa ini digunakan :). Bagian selanjutnya akan mengajari anda cara memprogram dengan bahasa assembly. Ada mitos yang mengatakan bahwa programming menggunakan asssembly sangat susah. Menurut penulis, mitos tersebut adalah keliru. Jika anda mau berusaha dan membuang jauh-jauh mitos itu, maka belajar assembly akan lebih mudah dibandingkan belajar bahasa C, sebab sintaks yang harus kita pelajari lebih sedikit. Satu-satunya hal yang akan menjadi tantangan adalah anda harus berusaha memahami arsitektur microprocessornya. Jadi... selamat berjuang and always have fun :)"
"Selamat. Sekarang anda telah memiliki sebagian besar kemampuan dasar yang dibutuhkan untuk menjadi seorang programer bahasa C yang profesional, yang anda butuhkan adalah berlatih membuat beberapa program agar anda semakin memahami bagaimana bahasa ini digunakan :). Bagian selanjutnya akan mengajari anda cara memprogram dengan bahasa assembly. Ada mitos yang mengatakan bahwa programming menggunakan asssembly sangat susah. Menurut penulis, mitos tersebut adalah keliru. Jika anda mau berusaha dan membuang jauh-jauh mitos itu, maka belajar assembly akan lebih mudah dibandingkan belajar bahasa C, sebab sintaks yang harus kita pelajari lebih sedikit. Satu-satunya hal yang akan menjadi tantangan adalah anda harus berusaha memahami arsitektur microprocessornya. Jadi... selamat berjuang and always have fun :)"
Pemrograman Bahasa Assembly
Pemrograman bahasa assembly sangat erat kaitannya dengan
hardware yang digunakan, oleh karena itu tutorial ini diawali dengan penjelasan
tentang arsitektur x86. Kita tidak akan mempelajari pemrograman assembly yang
rumit, yang akan kita pelajari hanya bagaimana cara membuat file *.com atau
yang biasa disebut file flat binary.
http://sizofrenperi.blogspot.com/2013/03/komponen-elemen-dasar-c.html https://fr-system.co.id/artikel-Tutorial_Pemrog.frsystem
Komentar
Posting Komentar