Bab. 9 Struktur, Union, Manipulasi
Bit, dan Enumerasi
Tujuan
Instruksional
|
|
·
Definisi struktur.
·
Menginisialisasi
struktur.
·
Mengakses anggota
struktur.
·
Menggunakan
struktur dengan fungsi.
·
typdef.
|
·
union.
·
Operator bitwise.
·
Bidang bit.
·
Konstanta
enumerasi.
|
9.1 Introduksi
Struktur, kadangkala dikenal dengan
agregat, merupakan sekumpulan variabel yang berelasi di bawah satu nama.
Struktur dapat memuat variabel-variabel bertipe data berbeda, berbeda dari
array yang memuat elemen-elemen bertipe sama. Struktur umumnya digunakan untuk
mendefinisikan rekaman agar disimpan di dalam file (lihat Bab 10, Pemrosesan
File). Pointer dan struktur memfasilitasi formasi atas struktur data kompleks seperti
senarai berantai (linked list),
antrian (queue), tumpukan (stack), dan pohon (tree).
9.2 Definisi Struktur
Struktur merupakan tipe data
terderivasi, yang dikonstruksi menggunakan beberapa objek bertipe data berbeda.
Perhatikan definisi struktur berikut:
struct kartu {
char *muka;
char *jenis;
};
Katakunci struct mengawali definisi struktur. Pengenal kartu adalah nama dari definisi struktur
dan digunakan dengan katakunci struct dalam
mendeklarasikan variabel bertipe struktur. Pada contoh ini, tipe struktur
adalah struct kartu. Variabel-variabel yang dideklarasikan
di dalam kurung kurawal definisi struktur adalah anggota-anggota struktur.
Anggota struktur yang sama harus memiliki nama yang unik, tetapi tipe struktur
berbeda dapat memuat nama anggota yang sama tanda terjadi konflik penamaan.
Setiap definisi struktur harus diakhiri dengan tanda titik-koma.
Definisi dari struct kartu memuat anggota muka dan jenis, keduanya
bertipe char *. Anggota struktur dapat berupa
variabel bertipe data primitif (seperti int, float, dll), atau agregat, seperti array dan
struktur lainnya. Seperti Anda lihat pada Bab 5, setiap elemen suatu array
harus bertipe data sama. Anggota struktur dapat memiliki berbagai tipe data.
Sebagai contoh, struct berikut memuat
dua anggot array karakter untuk nama pertama dan nama terakhir karyawan, sebuah
anggota int untuk usia karyawan, sebuah anggota char yang memuat ‘L’ atau ‘P’ untuk jenis kelamin karyawan, dan
sebuah anggota double untuk gaji
harian karyawan:
struct karyawan {
char namaPertama[ 20 ];
char namaTerakhir[ 20 ];
int usia;
char jenisKelamin;
double
gajiHarian;
};
Struktur
Referensi-Diri
Suatu struktur tidak bisa memuat
instans dari dirinya sendiri. Sebagai contoh, suatu variabel bertipe struct karyawan tidak dapat dideklarasikan di dalam
definisi untuk struct karyawan. Tetapi, suatu pointer ke struct karyawan dapat dimuat di dalam definisi untuk struct karyawan. Sebagai contoh,
struct karywan2 {
char namaPertama[ 20 ];
char namaTerakhir[ 20 ];
int usia;
char jenisKelamin;
double
gajiHarian;
struct
karyawan2 orang; /* ERROR */
struct
karyawan2 *ePtr; /* pointer */
};
struct karyawan2 memuat suatu instans dari dirinya
sendiri (orang), yang merupakan sebuah error. Karena ePtr merupakan suatu pointer (ke tipe struct karyawan2), hal tersebut diijinkan di dalam
definisi. Suatu struktur yang memuat suatu anggota berupa sebuah pointer yang
menunjuk ke tipe struktur yang sama dikenal dengan struktur referensi-diri.
Mendefinisikan
Variabel Bertipe Struktur
Definisi struktur tidak mencadangkan
memori; tetapi, setiap definisinya menciptakan suatu tipe data baru yang
dipakai untuk mendefinisikan variabel. Variabel struktur didefinisikan seperti
variabel bertipe data lain. Definisi
struct kartu aKartu, tumpukan[ 52 ], *kartuPtr;
mendeklarasikan aKartu sebagai sebuah variabel bertipe struct kartu, mendeklarasikan tumpukan sebagai suatu array dengan 52 elemen
bertipe struct kartu, dan mendeklarasikan *kartuPtr sebagai sebuah pointer ke struct kartu. Beberapa variabel bertipe struktur
dapat pula dideklarasikan dengan menempatkan daftar nama variabel yang
dipisahkan koma di antara sepasang kurung kurawal dan diakhiri dengan tanda titik-koma. Sebagai
contoh, definisi sebelumnya dapat juga dijadikan definisi struct kartu sebagai berikut:
struct kartu {
char *muka;
char *jenis;
} aKartu, tumpukan[ 52 ], *kartuPtr;
Operasi Yang
Dapat Dilakukan Pada Struktur
Beberapa operasi yang valid dilakukan
pada struktur adalah sebagai berikut: menugaskan variabel struktur kepada
variabel struktur bertipe sama, mengambil alamat (&) atas suatu variabel
struktur, mengakses anggota struktur, dan menggunakan operator sizeof untuk menentukan ukuran suatu variabel
struktur.
Struktur tidak bisa dibandingkan
menggunakan operator == dan !=, karena anggota struktur tidak disimpan di dalam
memori yang bertetangga. Kadangkala terdapat “lubang” di dalam suatu struktur,
karena komputer bisa jadi menyimpan beberapa tipe data spesifik seperti half word, word, atau double word. Word adalah unit memori standar yang
dipakai untuk menyimpan data di dalam komputer, biasanya 2 byte atau 4 byte.
Perhatikan definisi struktur berikut, dimana di dalamnya contoh1 dan contoh2 keduanya bertipe struct sampel dideklarasikan:
struct sampel {
char c;
int i;
} contoh1, contoh2;
Gambar 9.1 menunjukkan sebuah contoh
penyimpanan pada sebuah komputer dengan word
2-byte atas suatu variabel bertipe struct sampel yang ditugasi
karakter ‘a’ dan integer 97 (representasi bit atas nilai tersebut ditunjukkan
pada gambar). Jika anggota struktur disimpan di awal batas word, maka terdapat lubang 1-byte (byte 1 di dalam gambar). Nilai
di dalam lubang 1-byte tersebut tidak terdefinisi. Bahkan jika nilai-nilai
anggota dari contoh1 dan contoh2 sama, kedua struktur tersebut belum
tentu sama, karena lubang 1-byte tak-terdefinisi tersebuat belum tentu memiliki
nilai yang identik.
Gambar 9.1 | Kondisi penyimpanan suatu variabel
bertipe struct sampel menunjukkan area tak-terdefinisi di
dalam memori
9.3 Menginisialisasi Struktur
Struktur dapat diinisialisasi
menggunakan daftar penginisialisasi, sama seperti array. Untuk menginisialisasi
suatu array, setelah nama variabel dicantumkan tanda sama dengan dan daftar
penginisialisasi yang diapit oleh sepasang kurung kurawal dan dipisahkan dengan
koma. Sebagai contoh, deklarasi
struct kartu aKartu = { "Three", "Hearts" };
menciptakan variabel aKartu menjadi bertipe struct kartu (seperti didefinisikan pada Bagian
9.2) dan menginisialisasi anggota muka dengan “Three” dan anggota jenis dengan “Hearts”. Jika terdapat penginisialisasi lebih
sedikit di dalam list daripada jumlah anggota di dalam struktur, maka anggota
yang tersisa secara otomatis diinisialisasi dengan 0 (atau NULL jika anggota
adalah pointer). Variabel struktur yang didefinisikan di luar suatu definisi
fungsi (secara eksternal) diinisialisasi dengan 0 atau NULL jika tidak secara
eksplisit diinisialisasi di dalam definisi eksternal. Variabel struktur juga
dapat diinisialisasi di dalam statemen penugasan dengan menugaskan sebuah
variabel struktur bertipe sama, atau dengan menugaskan nilai kepada anggota
struktur secara individual.
9.4 Mengakses Anggota Struktur
Dua operator dipakai untuk mengakses
anggota struktur: operator keanggotaan struktur (.), yang juga disebut dengan
operator dot, dan operator pointer struktur (->), yang juga dikenal dengan
operator anak-panah. Operator keanggotaan struktur mengakses sebuah anggota
struktur melalui nama variabel struktur. Sebagai contoh, untuk menampilkan
anggota jenis dari variabel struktur aKartu yang didefinisikan pada Bagian 9.3,
digunakan statemen
printf( "%s", aKartu.jenis ); /* menampilkan Hearts */
Operator pointer struktur, memuat tanda
minus (-) dan tanda lebih besar dari (>) dengan tanpa spasi, mengakses
anggota struktur melalui sebuah pointer yang menunjuk ke struktur. Diasumsikan
bahwa pointer kartuPtr telah
dideklarasikan untuk menunjuk ke struct kartu dan bahwa
alamat struktur aKartu ditugaskan
kepada kartuPtr. Untuk menampilkan anggota jenis dari struktur aKartu menggunakan
pointer kartuPtr, digunakan statemen
printf( "%s", kartuPtr->jenis ); /* menampilkan Hearts */
Ekspresi kartuPtr->jenis ekivalen dengan (*kartuPtr).jenis, yang mendereferensi pointer dan mengakses anggota jenis menggunakan
operator anggota struktur. Sepasang kurung dibutuhkan di sini karena operator
keanggotaan struktur (.) memiliki derajat keutamaan lebih tinggi daripada
operator dereferensi pointer (*). Operator pointer struktur dan operator
keanggotaan struktur, bersama dengan sepasang kurung (untuk memanggil fungsi)
dan sepasang kurung siku ([ ]) yang digunakan untuk pensubskriptan array,
memiliki derajat keutamaan operator tertinggi dan berasosiasi dari kiri ke
kanan.
Program pada Gambar 9.2
mendemonstrasikan kegunaan operator keanggotaan struktur dan operator pointer
struktur. Dengan menggunakan operator keanggotaan struktur, anggota struktur aKartu dapat ditugasi nilai “Ace” dan “Spades” (baris 18 dan
19). Pointer kartuPtr ditugasi alamat
dari struktur aKartu (baris 21).
Fungsi tampil menampilkan anggota variabel struktur aKartu menggunakan operator keanggotaan
struktur dengan nama variabel aKartu, menggunakan
operator pointer struktur dengan pointer kartuPtr, dan menggunakan operator keanggotaan struktur dengan pointer
terdereferensi kartuPtr (baris 23
sampai 25).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
/* Gambar 9.2: gambar09_02.c
Menggunakan operator keanggotaan struktur dan
operator pointer struktur */
#include <stdio.h>
/* definisi struktur kartu */
struct kartu {
char
*muka; /* mendefinisikan pointer muka */
char
*jenis; /* mendefinisikan pointer jenis */
}; /* akhir struktur kartu */
int main( void )
{
struct
kartu aKartu; /* mendefinisikan satu variabel kartu */
struct
kartu *kartuPtr; /* mendefinisikan sebuah pointer ke struct card */
/*
menempatkan string ke aKartu */
aKartu.muka = "Ace";
aKartu.jenis = "Spades";
kartuPtr = &aKartu; /* menugaskan alamat aKartu ke kartuPtr */
printf( "%s%s%s\n%s%s%s\n%s%s%s\n", aKartu.muka, " dari
", aKartu.jenis,
kartuPtr->muka, " dari ", kartuPtr->jenis,
(
*kartuPtr ).muka, " dari ", ( *kartuPtr ).jenis );
return
0; /* indikasi terminasi sukses */
} /* akhir main */
|
Ace dari Spades
Ace dari Spades
Ace dari Spades
Gambar 9.2 | Operator
keanggotaan struktur dan operator pointer struktur
9.5 Menggunakan Struktur Dengan Fungsi
Struktur dapat dilewatkan kepada fungsi
dengan melewatkan anggota struktur individual, dengan melewatkan keseluruhan
struktur, atau dengan melewatkan sebuah pointer ke struktur. Ketika struktur
atau anggota struktur individual dilewatkan kepada sebuah fungsi, artinya
terjadi pelewatan dengan nilai. Oleh karena itu, anggota struktur dari suatu
pemanggil tidak dapat dimodifikasi oleh fungsi terpanggil. Untuk melewatkan
struktur dengan referensi, alamat dari variabel struktur yang dilewatkan. Array
struktur, seperti array lainnya, secara otomatis dilewatkan dengan referensi.
9.6 typedef
Katakunci typedef menyediakan suatu mekanisme dalam menciptakan sinonim (atau alias) bagi
tipe data yang sebelumnya terdefinisi. Nama untuk tipe struktur seringkali
didefinisikan dengan typedef untuk
menciptakan nama yang lebih pendek. Sebagai contoh, statemen
typedef struct kartu Kartu;
mendefinisikan nama tipe baru Kartu sebagai sinonim untuk tipe struct kartu. Programer C sering menggunakan typedef untuk mendefinisikan sebuah tipe struktur. Sebagai contoh, definisi
berikut
typedef struct {
char *muka;
char *jenis;
} Kartu;
Kartu sekarang dapat dipakai untuk mendeklarasikan variabel
bertipe struct Kartu. Deklarasi
Kartu tumpukan[ 52 ];
mendeklarasikan sebuah array yang
memuat 52 struktur Kartu
(variabel-variabel bertipe struct Kartu). Penciptaan
sebuah nama baru dengan typedef tidak berarti
menciptakan suatu tipe data baru; typedef hanya
menciptakan nama tipe baru, yang bisa dipakai sebagai nama alias bagi nama tipe
tertentu.
Seringkali typedef dipakai untuk menciptakan sinonim bagi tipe-tipe data dasar. Sebagai
contoh, suatu program yang memerlukan integer 4-byte bisa menggunakan tipe int pada suatu sistem dan tipe long pada sistem lainnya. Program yang didesain untuk memiliki fleksibilitas
seringkali menggunakan typedef dalam
menciptakan alias bagi integer 4-byte, seperti Integer. Alias Integer dapat diubah
sekali saja agar program dapat bekerja pada kedua sistem.
9.7 Contoh: Pengacakan Kartu
Program pada Gambar 9.3 didasarkan pada
simulasi pengacakan kartu. Program ini menyajikan setumpuk kartu sebagai sebuah
array yang memuat struktur. Keluaran program ditampilkan pada Gambar 9.4.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
/* Gambar 9.3: gambar09_03.c
Pengacakan kartu menggunakan struktur */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* definisi struktur kartu */
struct kartu {
const
char *muka; /* mendefinisikan pointer muka */
const
char *jenis; /* mendefinisikan pointer jenis */
}; /* akhir struktur kartu */
typedef struct kartu Kartu; /* nama tipe baru untuk
struct kartu */
/* prototipe */
void isiTumpukan( Kartu * const wTumpukan, const
char * wMuka[],
const char *
wJenis[] );
void acak( Kartu * const wTumpukan );
void tangani( const Kartu * const
wTumpukan );
int main( void )
{
Kartu deck[ 52 ]; /* mendefinisikan array Kartu */
/*
menginisialisasi array pointer */
const
char *muka[] = { "Ace", "Deuce", "Three",
"Four", "Five",
"Six",
"Seven", "Eight", "Nine", "Ten",
"Jack",
"Queen", "King"};
/*
menginisialisasi array pointer */
const
char *jenis[] = { "Hearts", "Diamonds",
"Clubs", "Spades"};
srand( time( NULL ) ); /* randomisasi */
isiTumpukan( deck, muka, jenis ); /* mengisi tumpukan dengan Kartu */
acak( deck ); /* mengacak Kartu dalam urutan acak */
tangani( deck ); /* menangani/menyebar semua 52 Kartu */
return
0; /* indikasi terminasi sukses */
} /* akhir main */
/* place strings into Kartu structures */
void isiTumpukan(Kartu * const wTumpukan , const char
* wMuka[],
const
char * wJenis[] )
{
int
i; /* kounter */
/*
loop menjelajahi wTumpukan */
for
( i = 0; i <= 51; i++ ) {
wTumpukan[ i ].muka = wMuka[ i % 13 ];
wTumpukan[ i ].jenis = wJenis[ i / 13 ];
} /*
akhir for */
} /* akhir fungsi isiTumpukan */
/* mengacak kartu */
void acak( Kartu * const wTumpukan )
{
int
i; /* kounter */
int
j; /* variabel untuk menampung nilai acak antara 0-51 */
Kartu temp; /* mendefinisikan struktur temporer untuk menukar Kartu */
/*
loop menjelajahi wTumpukan secara acak menukar Kartu */
for
( i = 0; i <= 51; i++ ) {
j
= rand() % 52;
temp = wTumpukan[ i ];
wTumpukan[ i ] = wTumpukan[ j ];
wTumpukan[ j ] = temp;
} /*
akhir for */
} /* akhir fungsi acak */
/* tangani/membagi/menyebar kartu */
void tangani(const Kartu * const
wTumpukan)
{
int
i; /* kounter */
/*
loop menjelajahi wTumpukan */
for
( i = 0; i <= 51; i++ ) {
printf( "%5s of %-8s%s", wTumpukan[ i ].muka, wTumpukan[ i
].jenis,
( i + 1 ) % 4 ? " " : "\n" );
} /*
akhir for */
} /* akhir fungsi tangani */
|
Gambar 9.3 | Simulasi
pengacakan dan pembagian kartu
Nine of Diamonds Six of Diamonds Four of Hearts Seven of Spades
Ace of Spades Ace of
Clubs Ten of Clubs Seven of Hearts
Nine of Spades Ace of Hearts King of Spades Jack of Hearts
Six of Clubs Jack of
Clubs Three of Diamonds Deuce of
Diamonds
Queen of Clubs King of Diamonds Six of Spades King of Hearts
Jack of Diamonds Deuce of Spades Ten of Spades Deuce of Clubs
Eight of Clubs Ten of Diamonds Nine of Clubs Queen of Diamonds
Queen of Hearts Seven of Diamonds King of Clubs Four of Spades
Nine of Hearts Four of Clubs Ten of Hearts Five of Hearts
Three of Clubs Five of Diamonds Eight of Hearts Seven of Clubs
Six of Hearts Eight of
Diamonds Jack of Spades Three of Hearts
Eight of Spades Ace of Diamonds Three of Spades Five of Spades
Queen of Spades Five of Clubs Four of Diamonds Deuce of Hearts
Gambar 9.4 | Keluaran
program simulasi pengacakan dan pembagian kartu
Pada program, fungsi isiTumpukan (baris 42-52) menginisialisasi array Kartu dengan urutan dari Ace sampai King untuk setiap jenis
kartu. Array Kartu dilewatkan
(pada baris 36) kepada fungsi acak (baris 55-68),
dimana algoritma pengacakan diimplementasikan. Fungsi acak mengambil sebuah array yang memuat 52 struktur Kartu sebagai argumen. Loop fungsi menjelajahi 52 kartu
(subskript array 0 sampai 51) menggunakan suatua statemen for pada baris 62-67. Untuk setiap kartu, sebuah angka dari 0
sampai 51 dipilih secara acak. Selanjutnya, struktur Kartu sekarang dan struktur Kartu yang dipilih secara acak ditukar di dalam array (baris 64 sampai 66).
Total 52 penukaran dilakukan dalam sebuah pass atas keseluruhan array, dan
array yang memuat struktur-struktur Kartu menjadi
teracak!.
9.8 Union
Union merupakan sebuah tipe data
terderivasi, seperti struktur, dengan anggota-anggota yang saling berbagi
memori penyimpanan. Pada berbagai situasi di dalam sebuah program, beberapa
variabel bisa saja tak relevan dan beberapa variabel lainnya saling relevan.
Oleh karena itu, union berbagi bersama memori daripada memboroskan memori pada
variabel yang tidak sedang dipakai. Anggota suatu union dapat berupa sembarang
tipe data. Jumlah byte yang dipakai untuk menyimpan sebuah union sedikitnya
cukup menampung anggota terbesar. Pada banyak kasus, union memuat dua atau
lebih tipe data. Hanya satu anggota, dan oleh karena itu satu tipe data, yang
dapat direferensi pada suatu waktu. Adalah tanggung jawab Anda untuk memastikan
bahwa data di dalam suatu union direferensi dengan tipe data yang sesuai.
Deklarasi Union
Sebuah union dideklarasikan dengan
katakunci union dengan format yang sama dengan
struktur. Definisi union
union angka {
int x;
double
y;
};
mengindikasikan bahwa angka adalah suatu tipe data union dengan anggota int x dan double y. Definisi union normalnya ditempatkan
di dalam header dan disertakan di dalam semua file sumber yang menggunakan tipe
union tersebut.
Operasi Yang
Dapat Diterapkan Pada Union
Beberapa operasi yang dapat diterapkan
pada union adalah sebagai berikut: penugasan sebuah union kepada union lainnya
yang bertipe sama, pengambilan alamat (&) suatu variabel union, dan pengaksesan anggota union menggunakan operator
keanggotaan struktur dan operator pointer struktur. Union tidak dapat
dibandingkan menggunakan operator == dan != karena alasan yang sama dengan struktur (yang tidak bisa
dibandingkan).
Menginisialisasi
Union Dalam Deklarasi
Dalam sebuah deklarasi, union dapat
diinisialisasi dengan suatu nilai bertipe sama dengan anggota union pertama.
Sebagai contoh, dengan union sebelumnya, deklarasi
union angka nilai = { 10 };
adalah suatu inisialisasi yang benar
atas variabel union nilai karena union
diinisialisasi dengan sebuah nilai int, tetapi
deklarasi berikut akan memotong bagian pecahan pada nilai penginisialisasi dan
normalnya menghasilkan peringatan dari kompiler:
union angka nilai = { 1.43 };
Mendemonstrasikan
Union
Program pada Gambar 9.5 menggunakan
variabel nilai (baris 13) yang bertipe union angka untuk menampilkan nilai yang disimpan
di dalam union sebagai int dan double. Keluaran program menunjukan bahwa
representasi internal atas nilai double bisa berbeda
dari representasi int.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
/* Gambar 9.5: gambar09_05.c
Contoh sebuah union */
#include <stdio.h>
/* definisi anggota union */
union angka {
int x;
double y;
}; /* akhir union angka */
int main( void )
{
union
angka nilai; /* mendefinisikan variabel union */
nilai.x = 100; /* menempatkan sebuah integer pada union */
printf( "%s\n%s\n%s\n %d\n\n%s\n %f\n\n\n",
"Menempatkan suatu nilai di dalam anggota integer",
"dan menampilkan kedua anggota union.",
"int:", nilai.x,
"double:", nilai.y );
nilai.y = 100.0; /* menempatkan sebuah double pada union yang sama */
printf( "%s\n%s\n%s\n %d\n\n%s\n %f\n",
"Menempatkan suatu nilai di dalam anggota pecahan",
"dan menampilkan kedua anggota union.",
"int:", nilai.x,
"double:", nilai.y );
return
0; /* indikasi terminasi sukses */
} /* akhir main */
|
Menempatkan suatu nilai di dalam
anggota integer
dan menampilkan kedua anggota union.
int:
100
double:
-92559592117433136000000000000000000000000000000000000000000000.000000
Menempatkan suatu nilai di dalam
anggota pecahan
dan menampilkan kedua anggota union.
int:
0
double:
100.000000
Gambar 9.5 | Menampilkan
nilai suatu union di dalam kedua tipe data anggota
9.9 Operator Bitwise
Operator bitwise dalam C adalah AND
bitwise (&), OR inklusif bitwise (|), OR ekslusif bitwise (^), geser kiri
(<<), geser kanan (>>), dan komplemen (~). Operator AND bitwise, OR
inklusif bitwise, dan OR ekslusif bitwise membandingkan kedua operandnya bit
demi bit. Operator AND bitwise menetapkan setiap bit dalam hasil menjadi 1 jika
kedua bit operandnya bernilai 1. Operator inklusif OR menetapkan setiap bit
dalam hasil menjadi 1 jika salah satu atau kedua bit operandnya bernilai 1.
Operator ekslusif bitwise OR menetapkan setiap bit dalam hasil menjadi 1 jika
hanya salah satu operandnya bernilai 1. Operator geser-kiri menggeser ke kiri
bit-bit operand kiri sebesar sejumlah bit yang dispesifkasi dalam operand
kanannya. Operator geser-kanan menggeser ke kanan bit-bit operand kiri sebesar
sejumlah bit yang dispesifkasi dalam operand kanannya. Operator komplemen
menetapkan semua bit 0 menjadi 1 di dalam hasil dan menetapkan semua bit 1
menjadi 0 di dalam bit hasil. Diskusi detil atas setiap operator bitwise akan
disajikan dalam beberapa contoh berikut. Semua operator bitwise disimpulkan
pada Gambar 9.6.
Operator
|
Penjelasan
|
& AND bitwise
| OR inklusif bitwise
^ OR ekslusif bitwise
<< geser-kiri
>> geser-kanan
~ komplemen
|
Menetapkan setiap bit dalam hasil
menjadi 1 jika kedua bit operandnya bernilai 1.
Menetapkan setiap bit dalam hasil
menjadi 1 jika salah satu atau kedua bit operandnya bernilai 1.
Menetapkan setiap bit dalam hasil
menjadi 1 jika hanya salah satu operandnya bernilai 1.
Menggeser ke kiri bit-bit operand
kiri sebesar sejumlah bit yang dispesifkasi dalam operand kanannya.
menggeser ke
kanan bit-bit operand kiri sebesar sejumlah bit yang dispesifkasi dalam
operand kanannya.
Menetapkan semua bit 0 menjadi 1 di
dalam hasil dan menetapkan semua bit 1 menjadi 0 di dalam bit hasil.
|
Gambar 9.6 Operator-operator bitwise
Menampilkan
Integer Tak-Bertanda Dalam Bit
Penggunaan operator bitwise sangat
berguna untuk menampilkan nilai-nilai dalam representasi binernya untuk
mengilustrasikan efek operator tersebut. Program pada Gambar 9.7 menampilkan
sebuah nilai unsigned dalam
representasi binernya dalam setiap grup delapan bit. Sebagai contoh,
diasumsikan bahwa integer unsigned disimpan di
dalam memori 4-byte (32 bit).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
/* Gambar 9.7: gambar09_07.c
Menampilkan sebuah integer tak-bertanda
dalam bit */
#include <stdio.h>
void tampilBit( unsigned nilai ); /* prototype
*/
int main( void )
{
unsigned
x; /* variabel untuk menampung masukan pengguna */
printf( "Masukkan sebuah integer tak-bertanda: " );
scanf( "%u", &x );
tampilBit( x );
return
0; /* indikasi terminasi sukses */
} /* akhir main */
/* menampilkan bit-bita dari nilai integer
tak-bertanda */
void tampilBit( unsigned nilai )
{
unsigned
c; /* kounter */
/*
mendefinisikan tampilMask dan menggeser ke kiri 31 bit */
unsigned
tampilMask = 1 << 31;
printf( "%10u = ", nilai );
/*
loop menjelajahi bit */
for
( c = 1; c <= 32; c++ ) {
putchar( nilai & tampilMask ? '1' : '0' );
nilai <<= 1; /* menggeser nilai ke kiri sejauh 1 */
if
( c % 8 == 0 ) { /* menampilkan spasi setelah 8 bit */
putchar( ' ' );
}
/* akhir if */
} /*
akhir for */
putchar( '\n' );
} /*
akhir fungsi tampilBit */
|
asukkan sebuah integer tak-bertanda:
65000
65000 = 00000000 00000000 11111101 11101000
Masukkan sebuah integer tak-bertanda:
33333
33333 = 00000000 00000000 10000010 00110101
Gambar 9.7 | Menampilkan
bit-bit atas suatu integer tak-bertanda
Fungsi tampilBit (baris 19-39) menggunakan operator AND bitwise untuk mengkombinasikan
variabel nilai dengan variabel tampilMask (baris 32). Seringkali, operator AND
bitwise digunakan dengan sebuah operand yang dikenal dengan mask, yaitu sebuah
nilai integer dengan beberapa bit spesifik ditetapkan bernilai 1. Mask dipakai
untuk menyembunyikan beberapa bit di dalam sebuah nilai ketika memilih bit-bit
lain. Dalam fungsi tampilBit, variabel mask tampilMask ditugasi nilai
1 << 31 (10000000 00000000 00000000 00000000)
Operator geser-kiri menggeser nilai 1
dari bit paling-kanan ke bit paling-kiri di dalam tampilMask dan mengisi bit-bit 0 dari kanan. Baris 32
putchar( nilai & tampilMask ? '1' : '0' );
menentukan apakah 1 atau 0 ditampilkan
untuk bit paling-kiri dari variabel nilai. Ketika nilai dan tampilMask dikombinasikan
menggunakan &, semua bit
kecuali bit paling-kiri di dalam variabel nilai disembunyikan, karena sembarang bit bila diANDkan dengan 0 menghasilkan
0. Jika bit paling-kiri bernilai 1, maka nilai & tampilMask dievaluasi menjadi bernilai tak-nol (true) dan 1 ditampilkan; sebaliknya, 0 ditampilkan. Variabel nilai kemudian digeser ke kiri sejauh satu bit dengan ekspresi nilai <<=1 (ini ekivalen dengan nilai = nilai << 1). Langkah-langkah ini diulangi untuk
setiap bit di dalam variabel nilai (unsigned). Gambar 9.8 menyimpulkan hasil
kombinasi dua bit dengan operator AND bitwise.
Gambar 9.8 | Hasil dari kombinasi dua bit dengan
operator AND bitwise &
Membuat Fungsi
tampilBit Menjadi Lebih Baik
Pada baris 24 pada Gambar 9.7, integer
31 dipakai untuk mengindikasikan bahwa nilai 1 harus digeser ke bit paling-kiri
di dalam variabel tampilMask. Sama halnya,
pada baris 29, integer 32 dipakai untuk mengindikasikan bahwa loop harus
beriterasi 32 kali, sekali untuk setiap bit di dalam variabel nilai. Diasumsikan bahwa integer unsigned selalu disimpan di dalam 32 bit (4 byte) memori. Kebanyakan komputer saat
ini menggunakan word 32-bit. Programer C cenderung bekerja dengan banyak
arsitektur perangkat keras, dan kadangkala integer unsigned akan disimpan di dalam jumlah bit yang lebih besar atau lebih kecil.
Program pada 9.7 dapat dibuat menjadi
lebih portabel dan skalabel dengan mengganti integer 31 pada baris 24 dengan ekspresi
CHAR_BIT * sizeof( unsigned ) - 1
dan mengganti integer 32 pada baris 29
dengan ekspresi
CHAR_BIT * sizeof( unsigned )
Konstanta simbolik CHAR_BIT (yang didefinisikan di dalam <limits.h>) merepresentasikan jumlah bit di dalam
suatu byte (normalnya 8). Seperti yang telah Anda pelajari pada Bagian 6.7,
operator sizeof menentukan jumlah byte yang digunakan
untuk menyimpan suatu objek atau tipe. Pada sebuah komputer yang menggunakan
word 32-bit, ekspresi sizeof(unsigned) dievaluasi bernilai 4, jadi dua ekspresi sebelumnya dievaluasi menjadi 31
dan 32. Pada sebuah komputer yang menggunakan word 16-bit, ekspresi sizeof(unsigned) dievaluasi bernilai 2, jadi dua
ekspresi sebelumnya dievaluasi menjadi 15 dan 16.
Menggunakan AND
Bitwise, OR Inklusif, OR Ekslusif, dan Komplemen
Gambar 9.9 mendemonstrasikan kegunaan
operator AND bitwise, operator OR inklusif bitwise, operator OR eksklusif
bitwise, dan operator komplemen bitwise. Program menggunakan fungsi tampilBit (baris 53-74) untuk menampilkan
nilai-nilai integer unsigned. Keluaran
ditampilkan pada Gambar 9.10.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
/* Gambar 9.9: gambar09_09.c
Menggunakan AND bitwise, OR inklusif bitwise, OR eksklusif
bitwise dan komplemen bitwise */
#include <stdio.h>
void tampilBit( unsigned nilai ); /* prototipe
*/
int main( void )
{
unsigned
angka1;
unsigned
angka2;
unsigned
mask;
unsigned
tetapkanBit;
/*
mendemonstrasikan AND bitwise (&) */
angka1 = 65535;
mask
= 1;
printf( "Hasil dari kombinasi berikut\n" );
tampilBit( angka1 );
tampilBit( mask );
printf( "menggunakan operator AND bitwise & adalah\n"
);
tampilBit(angka1 & mask);
/*
mendemonstrasikan OR inklusif bitwise (|) */
angka1 = 15;
tetapkanBit = 241;
printf( "\nHasil dari kombinasi berikut\n" );
tampilBit( angka1 );
tampilBit( tetapkanBit );
printf( "menggunakan operator OR inklusif | adalah\n"
);
tampilBit(angka1 | tetapkanBit);
/*
mendemonstrasikan OR eksklusif bitwise (^) */
angka1 = 139;
angka2 = 199;
printf( "\nHasil dari kombinasi berikut\n" );
tampilBit( angka1 );
tampilBit( angka2 );
printf( "menggunakan operator OR eksklusif bitwise ^ adalah\n"
);
tampilBit(angka1 ^ angka2);
/*
mendemonstrasikan komplemen bitwise (~)*/
angka1 = 21845;
printf( "\nKomplemen satu dari\n" );
tampilBit( angka1 );
printf( "adalah\n" );
tampilBit(~angka1);
return
0; /* indikasi terminasi sukses */
} /* akhir main */
/* display bits of an unsigned integer value
*/
void tampilBit( unsigned nilai )
{
unsigned c; /* kounter */
/*
mendeklarasikan tampilMask dan geser kiri 31 bit */
unsigned
tampilMask = 1 << 31;
printf( "%10u = ", nilai );
/*
loop menjelajahi bit */
for
( c = 1; c <= 32; c++ ) {
putchar( nilai & tampilMask ? '1' : '0' );
nilai <<= 1; /* menggeser nilai ke kiri sejauh 1 */
if
( c % 8 == 0 ) { /* menampilkan spasi setiap 8 bit */
putchar( ' ' );
}
/* akhir if */
} /*
akhir for */
putchar( '\n' );
} /* akhir fungsi tampilBit */
|
Gambar 9.9 | Operator AND bitwise, OR
inklusif bitwise, OR ekslusif bitwise, dan komplemen bitwise
Hasil dari kombinasi berikut
65535 = 00000000 00000000 11111111 11111111
1 = 00000000 00000000 00000000
00000001
menggunakan operator AND bitwise &
adalah
1 = 00000000 00000000 00000000
00000001
Hasil dari kombinasi berikut
15 = 00000000 00000000 00000000 00001111
241 = 00000000 00000000 00000000 11110001
menggunakan operator OR inklusif |
adalah
255 = 00000000 00000000 00000000 11111111
Hasil dari kombinasi berikut
139 = 00000000 00000000 00000000 10001011
199 = 00000000 00000000 00000000 11000111
menggunakan operator OR eksklusif
bitwise ^ adalah
76 = 00000000 00000000 00000000 01001100
Komplemen satu dari
21845 = 00000000 00000000 01010101 01010101
adalah
4294945450 = 11111111 11111111
10101010 10101010
Gambar 9.10 | Keluaran dari
program pada Gambar 9.9
Pada Gambar 9.9,
variabel integer angka1 ditugasi nilai
65535 (00000000
00000000 11111111 11111111 pada baris 16 dan variabel mask ditugasi nilai 1 (00000000 00000000 00000000 00000001) pada baris 17. Ketika angka1 dan mask dikombinasikan menggunakan operator AND bitwise (&) dalam ekspresi angka1 & mask (baris 22), hasil yang didapatkan
adalah 00000000
00000000 00000000 00000001. Semua bit kecuali bit paling-kanan di dalam variabel angka1 disembunyikan dengan mengANDkan dengan
variabel mask.
Operator OR
inklusif bitwise digunakan untuk menetapkan bit-bit spesifik menjadi 1 di dalam
sebuah operand. Pada Gambar 9.9, variabel angka1 ditugasi nilai 15 pada baris 25, (00000000 00000000 00000000
00001111) dan variabel tetapkanBit ditugasi nilai
241 (00000000
00000000 00000000 11110001) pada baris 26.
Ketika angka1 dan tetapkanBit dikombinasikan menggunakan operator OR bitwise di dalam ekspresi angka1 | tetapkanBit (baris 31), hasil yang didapatkan
adalah 255 (00000000
00000000 00000000 11111111). Gambar 9.11
menyimpulkan hasil pengkombinasian dua bit dengan operator OR inklusif.
Gambar 9.11 | Hasil dari mengkombinasikan dua bit
dengan operator OR inklusif |
Operator OR eksklusif bitwise (^)
menetapkan setiap bit di dalam hasil menjadi 1 jika hanya dan hanya 1 bit dari
kedua operandnya yang bernilai 1. Pada Gambar 9.9, variabel angka1 dan angka2 ditugasi nilai 139 (00000000 00000000 00000000 10001011) dan 199 (00000000 00000000 00000000
11000111) pada baris 34-35. Ketika dua variabel
tersebut dikombinasikan dengan operator OR eksklusif di dalam ekspresi angka1 ^ angka2 (baris 40), hasil yang didapatkan adalah 00000000 00000000 00000000
01001100. Gambar 9.12 menyimpulkan
hasil dari pengkombinasian dua bit dengan operator OR eksklusif bitwise.
Gambar 9.12 | Hasil dari mengkombinasikan dua bit
dengan operator OR eksklusif ^
Operator
komplemen bitwise (~) menetapkan semua bit 1 di dalam operandnya menjadi bit 0
di dalam hasil dan menetapkan semua bit 0 menjadi bit 1 di dalam hasil. Pada
Gambar 9.9, variabel angka1 ditugasi nilai 21845 (00000000 00000000
01010101 01010101)pada baris 43. Ketika ekspresi ~angka1 (baris 47) dievaluasi, hasil yang
diperoleh adalah 00000000 00000000 10101010 10101010.
Menggunakan
Operator Geser-Kiri dan Geser-Kanan
Program pada Gambar 9.13
mendemonstrasikan operator geser-kiri (<<) dan operator geser-kanan
(>>). Fungsi tampilBit digunakan untuk
menampilkan nilai-nilai integer unsigned.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
/* Gambar 9.13: gambar09_13.c
Menggunakan operator penggeseran bitwise */
#include <stdio.h>
void tampilBit( unsigned nilai ); /* prototipe
*/
int main( void )
{
unsigned
angka1 = 960; /* menginisialisasi angka1 */
/*
mendemonstrasikan geser-kiri bitwise */
printf( "\nHasil dari penggeseran kiri\n" );
tampilBit( angka1 );
printf( "8 bit posisi menggunakan " );
printf( "operator geser-kiri << adalah\n"
);
tampilBit(angka1 << 8);
/*
mendemonstrasikan operator geser-kanan bitwise */
printf( "\nHasil dari penggeseran kanan\n" );
tampilBit( angka1 );
printf( "8 bit posisi menggunakan " );
printf( "operator geser-kanan >> adalah\n" );
tampilBit(angka1 >> 8);
return
0; /* indikasi terminasi sukses */
} /* akhir main */
/* menampilkan bit-bit dari nilai integer
unsigned */
void tampilBit( unsigned nilai )
{
unsigned
c; /* kounter */
/*
mendeklarasikan tampilMask dan menggeser ke kiri 31 bit */
unsigned
tampilMask = 1 << 31;
printf( "%7u = ", nilai );
/*
loop menjelajahi bit */
for
( c = 1; c <= 32; c++ ) {
putchar( nilai & tampilMask ? '1' : '0' );
nilai <<= 1; /* menggeser nilai ke kiri sebesar 1 */
if
( c % 8 == 0 ) { /* menampilkan spasi setelah 8 bit */
putchar( ' ' );
}
/* akhir if */
} /*
akhir for */
putchar( '\n' );
} /* akhir fungsi tampilBit */
|
Hasil dari penggeseran kiri
960 = 00000000 00000000 00000011 11000000
8 bit posisi menggunakan operator
geser-kiri << adalah
245760 = 00000000 00000011 11000000 00000000
Hasil dari penggeseran kanan
960 = 00000000 00000000 00000011 11000000
8 bit posisi menggunakan operator
geser-kanan >> adalah
3 = 00000000 00000000 00000000 00000011
Gambar 9.13 | Operator
penggeseran bitwise
Operator geser-kiri (<<) menggeser bit-bit dari operandnya ke kiri sejauh sejumlah bit yang
dispesifikasi di dalam operand kanannya. Bit-bit yang ditinggalkan di kanan
diganti dengan bit 0; Pada Gambar 9.13, variabel angka1 ditugasi nilai 960 (00000000
00000000 00000011 11000000) pada baris 9. Hasil dari penggeseran ke kiri atas variabel angka1 sejauh 8 bit di
dalam ekspresi angka1 << 8 (baris 16) adalah 49152
(00000000
00000000 11000000 00000000).
Operator geser-kanan (>>) menggeser bit-bit dari operandnya ke
kanan sejauh sejumlah bit yang dispesifikasi di dalam operand kanannya.
Penerapan operator geser-kanan pada sebuah integer unsigned menyebabkan Bit-bit
yang ditinggalkan di kiri diganti dengan bit 0. Pada Gambar 9.13, hasil dari
penggeseran ke kanan atas angka1 di dalam
ekspresi angka1 >> 8 (baris 23) adalah 3 (00000000
00000000 00000000 00000011).
Operator
Penugasan Bitwise
Setiap operator bitwise biner memiliki
operator penugasan. Semua operator penugasan ditampilkan pada Gambar 9.14 dan
digunakan dengan cara yang sama dengan operator penugasan aritmatika.
Operator Penugasan Bitwise
|
|
&=
|=
^=
<<=
>>=
|
Operator penugasan AND bitwise
Operator penugasan OR inklusif bitwise
Operator penugasan OR ekslusif bitwise
Operator penugasan geser-kiri bitwise
Operator penugasan geser-kanan bitwise
|
Gambar 9.14 | Operator-operator penugasan bitwise
Gambar 9.15 menunjukkan derajat
keutamaan dan asosiatifitas berbagai operator yang dikenalkan sejauh ini pada
buku ini. Semuanya ditampilkan dari atas ke bawah dengan urutan keutamaan
menurun.
Operator
|
Asosiatifitas
|
Tipe
|
[] ()
. ->
+ -
++ -- !
* & ~
sizeof (tipe)
* / %
+ -
<< >>
< <=
> >=
== !=
&
^
|
&&
||
?:
= +=
-= *= /=
%= &= |=
^= <<= >>==
,
|
kiri ke kanan
kanan ke kiri
kiri ke kanan
kiri ke kanan
kiri ke kanan
kiri ke kanan
kiri ke kanan
kiri ke kanan
kiri ke kanan
kiri ke kanan
kiri ke kanan
kiri ke kanan
kanan ke kiri
kanan ke kiri
kiri ke kanan
|
tertinggi
unary
multiplikatif
aditif
penggeseran
relasional
ekualitas
AND bitwise
OR bitwise
OR bitwise
AND logikal
OR logikal
kondisional
penugasan
koma
|
Gambar 9.15 | Keutamaan dan asosiatifitas operator
9.10 Bidang Bit
C memampukan Anda untuk menspesifikasi
jumlah bit dimana di dalamnya anggota unsigned atau int atas suatu
struktur atau union disimpan. C memampukan Anda untuk menspesifikasi jumlah bit
dimana di dalamnya anggota int atau unsigned suatu struktur atau union disimpan.
Ini dikenal dengan bidang bit. Bidang bit memampukan utilisasi memori dengan
lebih baik dengan menyimpan data pada jumlah bit minimum. Anggota bidang bit
harus dideklarasikan sebagai int atau unsigned.
Perhatikan definisi struktur berikut:
struct bitKaru {
unsigned
muka : 4;
unsigned
jenis : 2;
unsigned
warna : 1;
};
yang memuat tiga bidang bit unsigned, yaitu muka, jenis, dan warna, yang digunakan untuk merepresentasikan setumpukan 52 kartu. Bidang bit
dideklarasikan dengan mencantumkan nama anggota int atau unsigned diikuti dengan
titik-dua dan sebuah konstanta integer yang merepresentasikan labar bidang
(yaitu, jumlah bit dimana di dalamnya anggota disimpan). Konstanta yang
merepresentasikan lebar tersebut harus berupa sebuah integer antara 0 dan
jumlah bit yang digunakan untuk menyimpan sebuah int pada sistem Anda. Contoh pada buku ini diuji pada komputer dengan integer
4-byte (32 bit).
Definisi struktur tersebut
mengindikasikan bahwa anggota muka disimpan dalam
4 bit, anggota jenis disimpan dalam
2 bit dan anggota warna disimpan dalam
1 bit. Jumlah bit didasarkan pada rentang nilai yang diinginkan untuk setiap
anggota struktur. Anggota muka menyimpan nilai
dari 0 (Ace) sampai 12 (King), dimana 4 bit dapat menyimpan nilai dalam rentang
0-15. Anggota jenis menyimpan nilai
dari 0 sampai 3 (0 = Diamonds, 1 = Hearts, 2 = Clubs, 3 = Spades), dimana 2 bit
dapat menyimpan nilai dalam rentang 0-3. Anggota warna menyimpan 0 (merah atau Red) atau 1 (hitam atau Black), dimana 1 bit
dapat menyimpan 0 atau 1.
Gambar 9.16 (keluaran ditampilkan pada
Gambar 9.17) menciptakan array tumpukan yang memuat 52 struct bitKartu pada baris 20. Fungsi isiTumpukan (baris 28-38) menyisipkan 52 kartu di
dalam array tumpukan dan fungsi tangani (baris 42-54) menampilkan 52 kartu.
Perhatikan bahwa anggota bidang bit dari struktur diakses sama seperti anggota
struktur yang lain. Anggota warna dicantumkan
agar mengindikasikan bahwa warna kartu pada sebuah sistem mengijinkan
penampilan warna. Adalah hal yang mungkin untuk menspesifikasi bidang bit
tak-bernama sebagai pengganjal di dalam struktur. Sebagai contoh,
struct contoh {
unsigned
a : 13;
unsigned
: 19;
unsigned
b : 4;
};
menggunakan suatu bidang 19-bit
tak-bernama sebagai pengganjal, dimana tidak ada apapun yang dapat disimpan
dalam 19 bit tersebut. Anggota b (pada komputer
word 4-byte) disimpan di dalam unit penyimpanan yang lain.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
/* Gambar 9.16: gambar09_16.c
Merepresentasikan kartu dengan bidang bit dalam struktur */
#include <stdio.h>
/* Definisi struktur bitKartu dengan bidang
bit */
struct bitKartu {
unsigned
muka : 4; /* 4 bit; 0-15 */
unsigned
jenis : 2; /* 2 bit; 0-3 */
unsigned
warna : 1; /* 1 bit; 0-1 */
}; /* akhir struktur bitKartu */
typedef struct bitKartu Kartu; /* nama tipe baru untuk struct bitKartu */
void isiTumpukan( Kartu * const wTumpukan ); /*
prototipe */
void tangani( const Kartu * const
wTumpukan ); /* prototipe */
int main( void )
{
Kartu tumpukan[ 52 ]; /* menciptakan array Kartu */
isiTumpukan( tumpukan );
tangani( tumpukan );
return
0; /* indikasi terminasi sukses */
} /* akhir main */
/* initialize Cards */
void isiTumpukan(Kartu * const wTumpukan)
{
int
i; /* kounter */
/*
loop menjelajahi wTumpukan */
for
( i = 0; i <= 51; i++ ) {
wTumpukan[ i ].muka = i % 13;
wTumpukan[ i ].jenis = i / 13;
wTumpukan[ i ].warna = i / 26;
} /*
akhir for */
} /* akhir fungsi isiTumpukan */
/* menampilkan kartu dalam format dua kolom;
kartu 0-25 disubskript
dengan k1 (kolom 1); kartu 26-51 disubskript dengan k2 (kolom 2) */
void tangani( const Kartu * const
wTumpukan )
{
int
k1; /* subskript 0-25 */
int
k2; /* subskript 26-51 */
/*
loop menjelajahi wTumpukan */
for
( k1 = 0, k2 = k1 + 26; k1 <= 25; k1++, k2++ ) {
printf( "Kartu:%3d Jenis:%2d Warna:%2d ",
wTumpukan[ k1 ].muka, wTumpukan[ k1 ].jenis,
wTumpukan[ k1 ].warna );
printf( "Kartu:%3d Jenis:%2d Warna:%2d\n",
wTumpukan[ k2 ].muka, wTumpukan[ k2 ].jenis,
wTumpukan[ k2 ].warna );
} /*
akhir for */
} /* akhir fungsi tangani */
|
Gambar 9.16 | Bidang bit
untuk menyimpan setumpuk kartu
Kartu:
0 Jenis: 0 Warna: 0 Kartu: 0
Jenis: 2 Warna: 1
Kartu:
1 Jenis: 0 Warna: 0 Kartu: 1
Jenis: 2 Warna: 1
Kartu:
2 Jenis: 0 Warna: 0 Kartu: 2
Jenis: 2 Warna: 1
Kartu:
3 Jenis: 0 Warna: 0 Kartu: 3
Jenis: 2 Warna: 1
Kartu:
4 Jenis: 0 Warna: 0 Kartu: 4
Jenis: 2 Warna: 1
Kartu:
5 Jenis: 0 Warna: 0 Kartu: 5
Jenis: 2 Warna: 1
Kartu:
6 Jenis: 0 Warna: 0 Kartu: 6
Jenis: 2 Warna: 1
Kartu:
7 Jenis: 0 Warna: 0 Kartu: 7 Jenis:
2 Warna: 1
Kartu:
8 Jenis: 0 Warna: 0 Kartu: 8
Jenis: 2 Warna: 1
Kartu:
9 Jenis: 0 Warna: 0 Kartu: 9
Jenis: 2 Warna: 1
Kartu: 10 Jenis: 0 Warna: 0 Kartu: 10
Jenis: 2 Warna: 1
Kartu: 11 Jenis: 0 Warna: 0 Kartu: 11
Jenis: 2 Warna: 1
Kartu: 12 Jenis: 0 Warna: 0 Kartu: 12
Jenis: 2 Warna: 1
Kartu:
0 Jenis: 1 Warna: 0 Kartu: 0
Jenis: 3 Warna: 1
Kartu:
1 Jenis: 1 Warna: 0 Kartu: 1
Jenis: 3 Warna: 1
Kartu:
2 Jenis: 1 Warna: 0 Kartu: 2
Jenis: 3 Warna: 1
Kartu:
3 Jenis: 1 Warna: 0 Kartu: 3
Jenis: 3 Warna: 1
Kartu:
4 Jenis: 1 Warna: 0 Kartu: 4
Jenis: 3 Warna: 1
Kartu:
5 Jenis: 1 Warna: 0 Kartu: 5
Jenis: 3 Warna: 1
Kartu:
6 Jenis: 1 Warna: 0 Kartu: 6
Jenis: 3 Warna: 1
Kartu:
7 Jenis: 1 Warna: 0 Kartu: 7
Jenis: 3 Warna: 1
Kartu:
8 Jenis: 1 Warna: 0 Kartu: 8
Jenis: 3 Warna: 1
Kartu:
9 Jenis: 1 Warna: 0 Kartu: 9
Jenis: 3 Warna: 1
Kartu: 10 Jenis: 1 Warna: 0 Kartu: 10
Jenis: 3 Warna: 1
Kartu: 11 Jenis: 1 Warna: 0 Kartu: 11
Jenis: 3 Warna: 1
Kartu: 12 Jenis: 1 Warna: 0 Kartu: 12
Jenis: 3 Warna: 1
Gambar 9.17 | Keluaran
program pada Gambar 9.16
Sebuah bidang bit tak-bernama dengan
lebar nol dipakai untuk menyejajarkan bidang bit berikutnya pada batas
unit-penyimpanan. Sebagai contoh, definisi struktur
struct contoh {
unsigned
a : 13;
unsigned
: 0;
unsigned
b : 4;
};
menggunakan sebuah bidang 0-bit
tak-bernama untuk melompati sisa bit (seberapapun) pada unit penyimpanan dimana
a disimpan dan untuk menyejajarkan b pada batas unit-penyimpanan berikutnya.
9.11 Konstanta Enumerasi
C menyediakan satu lagi tipe
terdefinisi-pengguna yang dinamakan dengan enumerasi. Enumerasi, yang diawali
dengan katakunci enum, merupakan
himpunan konstanta enumerasi integer yang direpresentasikan dengan pengenal.
Nilai-nilai di dalam suatu enum diawali dengan
0, kecuali kalau dispesifikasi, dan diinkremen sebesar 1. Sebagai contoh,
enumerasi
enum bulan {
JAN, FEB, MAR, APR, MEI, JUN, JUL, AGUST, SEP, OKT, NOV, DES };
menciptakan suatu tipe baru, enum bulan, dimana di dalamnya beberapa pengenal ditetapkan
bernilai integer 0 sampai 11. Untuk menomori bulan mulai dari 1 sampai 12,
digunakan enumerasi berikut:
enum bulan {
JAN = 1, FEB, MAR, APR, MEI, JUN, JUL, AGUST, SEP, OKT, NOV, DES
};
Karena nilai pertama di dalam enumerasi
tersebut secara eksplisit ditetapkan 1, nilai-nilai lainnya diinkremen dari 1,
menghasilkan nilai dari 1 sampai 12. Pengenal di dalam sebuah enumerasi harus
unik. Nilai dari setiap konstanta enumerasi dapat ditetapkan secara eksplisit
di dalam definisi dengan menugaskan sebuah nilai kepada pengenal. Dalam program
pada Gambar 9.18, variabel enumerasi bulan dipakai di dalam statemen for untuk menampilkan nama bulan dalam setahun pada array namaBulan. Elemen namaBulan[0] ditetapkan menjadi string kosong “ “.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/* Gambar 9.18: gambar09_18.c
Menggunakan tipe enumerasi */
#include <stdio.h>
/* konstanta enumerasi merepresentasikan
bulan dalam tahun */
enum bulan {
JAN =
1, FEB, MAR, APR, MEI, JUN, JUL, AGUST, SEP, OKT, NOV, DES };
int main( void )
{
enum bulan bulan2;
/*
menginisialisasi array pointer */
const char *namaBulan[] = {
"", "Januari", "February", "Maret",
"April", "Mei", "Juni",
"Juli", "Agustus", "September",
"Oktober",
"November", "Desember" };
/*
loop menjelajah bulan */
for
(bulan2 = JAN; bulan2 <= DES; bulan2++ ) {
printf( "%2d%11s\n", bulan2, namaBulan[ bulan2 ] );
} /*
akhir for */
return
0; /* indikasi terminasi sukses */
} /* akhir main */
|
1
Januari
2
February
3
Maret
4
April
5
Mei
6
Juni
7
Juli
8
Agustus
9
September
10
Oktober
11
November
12
Desember
Gambar 9.18 | Menggunakan
enumerasi
Kesimpulan
§
Struktur merupakan tipe data terderivasi, yang dikonstruksi menggunakan
beberapa objek bertipe data berbeda.
§
Variabel-variabel yang dideklarasikan di dalam kurung kurawal definisi
struktur adalah anggota-anggota struktur. Anggota struktur yang sama harus
memiliki nama yang unik, tetapi tipe struktur berbeda dapat memuat nama anggota
yang sama tanda terjadi konflik penamaan. Setiap definisi struktur harus
diakhiri dengan tanda titik-koma.
§
Definisi struktur tidak mencadangkan memori; tetapi, setiap definisinya
menciptakan suatu tipe data baru yang dipakai untuk mendefinisikan variabel.
Variabel struktur didefinisikan seperti variabel bertipe data lain.
§
Beberapa operasi yang valid dilakukan pada struktur adalah sebagai
berikut: menugaskan variabel struktur kepada variabel struktur bertipe sama,
mengambil alamat (&) atas suatu variabel struktur, mengakses anggota
struktur, dan menggunakan operator sizeof untuk menentukan ukuran suatu variabel struktur.
§
Struktur tidak bisa dibandingkan menggunakan operator == dan !=, karena
anggota struktur tidak disimpan di dalam memori yang bertetangga. Kadangkala
terdapat “lubang” di dalam suatu struktur, karena komputer bisa jadi menyimpan
beberapa tipe data spesifik seperti half
word, word, atau double word. Word adalah unit memori standar yang dipakai untuk menyimpan data
di dalam komputer, biasanya 2 byte atau 4 byte.
§
Struktur dapat diinisialisasi menggunakan daftar penginisialisasi, sama
seperti array. Untuk menginisialisasi suatu array, setelah nama variabel
dicantumkan tanda sama dengan dan daftar penginisialisasi yang diapit oleh
sepasang kurung kurawal dan dipisahkan dengan koma.
§
Dua operator dipakai untuk mengakses anggota struktur: operator
keanggotaan struktur (.), yang juga disebut dengan operator dot, dan operator
pointer struktur (->), yang juga dikenal dengan operator anak-panah.
Operator keanggotaan struktur mengakses sebuah anggota struktur melalui nama
variabel struktur.
§
Struktur dapat dilewatkan kepada fungsi dengan melewatkan anggota struktur
individual, dengan melewatkan keseluruhan struktur, atau dengan melewatkan
sebuah pointer ke struktur. Ketika struktur atau anggota struktur individual
dilewatkan kepada sebuah fungsi, artinya terjadi pelewatan dengan nilai. Oleh
karena itu, anggota struktur dari suatu pemanggil tidak dapat dimodifikasi oleh
fungsi terpanggil. Untuk melewatkan struktur dengan referensi, alamat dari
variabel struktur yang dilewatkan. Array struktur, seperti array lainnya,
secara otomatis dilewatkan dengan referensi.
§
Katakunci typedef menyediakan suatu mekanisme dalam menciptakan sinonim (atau alias) bagi
tipe data yang sebelumnya terdefinisi. Nama untuk tipe struktur seringkali
didefinisikan dengan typedef untuk menciptakan nama yang lebih pendek.
§
Seringkali typedef dipakai untuk menciptakan sinonim bagi tipe-tipe data dasar. Sebagai
contoh, suatu program yang memerlukan integer 4-byte bisa menggunakan tipe int pada suatu sistem dan tipe long pada sistem lainnya. Program yang
didesain untuk memiliki fleksibilitas seringkali menggunakan typedef dalam menciptakan alias bagi integer
4-byte, seperti Integer. Alias Integer dapat diubah sekali saja agar program dapat bekerja pada kedua sistem.
§
Union merupakan sebuah tipe data terderivasi, seperti struktur, dengan
anggota-anggota yang saling berbagi memori penyimpanan. Pada berbagai situasi
di dalam sebuah program, beberapa variabel bisa saja tak relevan dan beberapa
variabel lainnya saling relevan. Oleh karena itu, union berbagi bersama memori
daripada memboroskan memori pada variabel yang tidak sedang dipakai. Anggota
suatu union dapat berupa sembarang tipe data. Jumlah byte yang dipakai untuk
menyimpan sebuah union sedikitnya cukup menampung anggota terbesar. Pada banyak
kasus, union memuat dua atau lebih tipe data. Hanya satu anggota, dan oleh
karena itu satu tipe data, yang dapat direferensi pada suatu waktu.
§
Operator AND bitwise menetapkan setiap bit dalam hasil menjadi 1 jika kedua
bit operandnya bernilai 1. Operator inklusif OR menetapkan setiap bit dalam
hasil menjadi 1 jika salah satu atau kedua bit operandnya bernilai 1. Operator
ekslusif bitwise OR menetapkan setiap bit dalam hasil menjadi 1 jika hanya
salah satu operandnya bernilai 1. Operator geser-kiri menggeser ke kiri bit-bit
operand kiri sebesar sejumlah bit yang dispesifkasi dalam operand kanannya.
Operator geser-kanan menggeser ke kanan bit-bit operand kiri sebesar sejumlah
bit yang dispesifkasi dalam operand kanannya. Operator komplemen menetapkan
semua bit 0 menjadi 1 di dalam hasil dan menetapkan semua bit 1 menjadi 0 di
dalam bit hasil.
§
C memampukan Anda untuk menspesifikasi jumlah bit dimana di dalamnya
anggota unsigned atau int atas suatu
struktur atau union disimpan. C memampukan Anda untuk menspesifikasi jumlah bit
dimana di dalamnya anggota int atau unsigned suatu struktur atau union disimpan.
Ini dikenal dengan bidang bit. Bidang bit memampukan utilisasi memori dengan
lebih baik dengan menyimpan data pada jumlah bit minimum. Anggota bidang bit
harus dideklarasikan sebagai int atau unsigned.
§
Sebuah bidang bit tak-bernama dengan lebar nol dipakai untuk menyejajarkan
bidang bit berikutnya pada batas unit-penyimpanan.
§
C menyediakan satu lagi tipe terdefinisi-pengguna yang dinamakan dengan
enumerasi. Enumerasi, yang diawali dengan katakunci enum, merupakan himpunan konstanta enumerasi integer yang
direpresentasikan dengan pengenal. Nilai-nilai di dalam suatu enum diawali dengan 0, kecuali kalau
dispesifikasi, dan diinkremen sebesar 1.
Soal
1. Diberikan definisi struktur dan
variabel berikut:
struct konsumen {
char namaAkhir[ 15 ];
char namaPertama[ 15 ];
int nomorPelanggan;
struct
{
char
nomorTelepon[ 11 ];
char
alamat[ 50 ];
char
kota[ 15 ];
char
propinsi[ 15 ];
char
kodePos[ 6 ];
}
pribadi;
} rekamanPelanggan, *pelangganPtr;
pelangganPtr = &
rekamanPelanggan;
Tulislah
ekspresi yang bisa dipakai untuk mengakses anggota-anggota struktur pada tiap kasus
berikut:
a) Anggota namaAkhir dari struktur rekamanPelanggan.
b) Anggota namaAkhir dari struktur
yang ditunjuk oleh pelangganPtr.
c) Anggota namaPertama dari struktur rekamanPelanggan.
d) Anggota namaPertama dari struktur
yang ditunjuk oleh pelangganPtr.
e) Anggota nomorPelanggan dari struktur rekamanPelanggan.
f)
Anggota nomorPelanggan dari struktur
yang ditunjuk oleh pelangganPtr.
g) Anggota nomorTelepon dari anggota pribadi dari struktur rekamanPelanggan.
h) Anggota nomorTelepon dari anggota pribadi dari struktur
yang ditunjuk oleh pelangganPtr.
i)
Anggota alamat dari anggota pribadi dari struktur rekamanPelanggan.
j)
Anggota alamat dari anggota pribadi dari struktur
yang ditunjuk oleh pelangganPtr.
k) Anggota kota dari anggota pribadi dari struktur rekamanPelanggan.
l)
Anggota kota dari anggota pribadi dari struktur
yang ditunjuk oleh pelangganPtr.
m) Anggota propinsi dari anggota pribadi dari struktur rekamanPelanggan.
n) Anggota propinsi dari anggota pribadi dari struktur
yang ditunjuk oleh pelangganPtr.
o) Anggota kodePos dari anggota pribadi dari struktur rekamanPelanggan.
p) Anggota kodePos dari anggota pribadi dari struktur
yang ditunjuk oleh pelangganPtr.
2.
Ciptakanlah sebuah union integer dengan
anggota-anggota char c, short s, int i, dan long b. Tulislah
sebuah program yang membaca nilai bertipe char, short, int, dan long dan
menyimpannya di dalam variabel-variabel bertipe union integer. Setiap
variabel union harus ditampilkan sebagai char, short, int, dan long.
3.
Ciptakanlah union titikMengambang dengan
anggota-anggota float f, double d, dan long double x. Tulislah
sebuah program yang membaca nilai bertipe float, double, dan long double dan menyimpan
nilai tersebut dalam variabel bertipe union titikMengambang. Setiap variabel union harus ditampilkan
sebagai float, double, dan long double.
4.
Tulislah sebuah program yang menggeser ke kanan
sebuah variabel integer 4-bit. Program harus menampilkan integer tersebut dalam
bit sebelum dan sesudah operasi penggeseran.
5.
Jika komputer Anda menggunakan integer 2-byte,
modifikasilah program pada Gambar 9.7 sehingga dapat bekerja pada integer
2-byte.
6.
Tulislah sebuah program untuk membalikkan urutan
bit dalam sebuah nilai integer unsigned. Program harus membaca nilai dari
pengguna dan memanggil fungsi balikBit untuk menampilkan bit dalam urutan
terbalik. Tampilkan nilai di dalam bit sebelum dan sesudah operasi pembalikan
bit.
7.
Modifikasilah fungsi tampilBit pada Gambar 9.7
sehingga dapat dipakai pada sistem yang menggunakan integer 2-byte dan integer
4-byte.
8. Program berikut
menggunakan fungsi kelipatan untuk menentukan apakah sebuah
integer yang dimasukkan dari papan-ketik merupakan kelipatan dari suatu
integer X. Ujilah fungsi tersebut dan kemudian tentukan nilai X.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
/* soal09_08.c */
/* Program ini menentukan apakah sebuah
nilai adalah kelipatan dari X. */
#include <stdio.h>
int kelipatan( int
num ); /* prototipe */
int main( void )
{
int y; /* y akan menampung integer yang
dimasukkan oleh pengguna */
printf( "Masukkan sebuah integer antara 1 dan
32000: " );
scanf( "%d",
&y );
/* jika y adalah kelipatan dari X */
if ( kelipatan( y ) ) {
printf( "%d adalah kelipatan dari X\n",
y );
} /* akhir if */
else {
printf( "%d bukan kelipatan dari X\n",
y );
} /* akhir else */
return 0; /* indikasi terminasi sukses */
} /* akhir main */
/* menentukan jika num adalah kelipatan
dari X */
int kelipatan( int
num )
{
int
i; /* kounter */
int mask = 1; /* inisialisasi mask */
int kelipat = 1; /* inisialisasi kelipat */
for ( i = 1; i <= 10; i++, mask <<= 1
) {
if ( ( num & mask ) != 0
) {
kelipat = 0;
break;
} /* akhir if */
} /* akhir for */
return kelipat;
} /* akhir fungsi kelipatan */
|
No comments:
Post a Comment