Anda di halaman 1dari 9

Bab 2 Mewakili dan Memanipulasi Informasi

2.1.9Operasi Logis di C

C juga menyediakan satu set operator logis ||,&&, dan !, yang sesuai dengan OR, AND, dan NOT operasi
logika. Ini dapat dengan mudah dibingungkan dengan operasi tingkat bit, namun fungsinya sangat
berbeda. Operasi logis memperlakukan argumen takbalik yang mewakili TRUE dan argumen 0 sebagai
mewakili FALSE. Mereka mengembalikan 1 atau 0, yang menunjukkan hasil masing-masing TRUE atau
FALSE. Berikut adalah beberapa contoh evaluasi ekspresi:

Hasil Ekspresi

Expression Result
!0x41 0x00
!0x00 0x01
!!0x41 0x01
0x69 && 0x55 0x01
0x69 || 0x55 0x01

Amati bahwa operasi bit-wise akan memiliki perilaku yang sesuai dengan mitra logisnya hanya dalam
kasus khusus dimana argumen dibatasi hingga 0 atau 1.

Perbedaan penting kedua antara operator logika && dan || versus rekan tingkat bit mereka &
dan | adalah bahwa operator logika tidak mengevaluasi instrumen pendahuluan mereka terhadap
eksploitasi dapat ditentukan dengan mengevaluasi argumen pertama. Jadi, misalnya, sebuah ekspresi
&& 5 / a tidak akan pernah menyebabkan pembagian nol, dan ekspresi p && * p ++ tidak akan
menyebabkan dereferencing dari pointer nol.

Latihan Soal 2.14

Misalkan x dan y memiliki nilai byte 0x66 dan 0x39. Isi tabel berikut yang menunjukkan nilai byte dari
ekspresi C yang berbeda:

Latihan Soal 2.15

Menggunakan hanya sedikit tingkat dan operasi logis, tuliskan ekspresi C yang setara dengan x == y.
Dengan kata lain, ia akan mengembalikan 1 jika x dan y sama, dan 0 sebaliknya.
2.1.10 Pergeseran Operasi di C

C juga menyediakan satu set operasi pergeseran untuk menggeser pola bit ke kiri dan ke kanan. Untuk
sebuah operan x yang memiliki representasi bit [xn-1,xn-2,...,x0] , ekspresi C x << k menghasilkan nilai
dengan representasi bit [xn-k-1,xn-k-2,...,x0, 0,...,0]. Artinya, x digeser k bit ke kiri, menjatuhkan bit k yang
paling signifikan dan mengisi ujung kanan dengan nol k. Jumlah shift harus bernilai antara 0 dan n-1.
Pergeseran operasi mengasosiasikan dari kiri ke kanan, jadi x << j << k sama dengan (x << j) << k.

Ada operasi shift kanan yang sesuai x >> k, namun memiliki perilaku yang sedikit halus.
Umumnya, mesin mendukung dua bentuk pergeseran kanan: logis dan aritmatika. Pergeseran kanan
yang logis mengisi ujung kiri dengan nol k, memberi hasil [0,...,0, xn-1, xn-2,...,xk]. Pergeseran tepat
aritmatika mengisi ujung kiri dengan pengulangan k yang paling signifikan, memberikan hasilnya [xn-1,...,
xn-1, xn-1, xn-2,...xk]. Konvensi ini mungkin tampak aneh, tapi seperti yang akan kita lihat, hal itu berguna
untuk beroperasi pada data integer yang ditandatangani.

Sebagai contoh, tabel berikut menunjukkan pengaruh penerapan operasi pergeseran yang
berbeda pada beberapa data sampel 8-bit:

Angka yang dicetak miring menunjukkan nilai-nilai yang mengisi sisi kanan (shift kiri) atau kiri (shift
kanan) akhir.Oleh karena semua kecuali satu entri melibatkan pengisian dengan angka nol.
Pengecualiannya adalah kasus pergeseran [10010101] dengan benar secara aritmatika. Karena bit yang
paling signifikan adalah 1, ini akan digunakan sebagai nilai fill.

Standar C tidak secara tepat menentukan jenis pergeseran hak yang tepat yang harus digunakan.
Untuk data unsigned (yaitu, objek integral dinyatakan dengan unsigned unsigned), pergeseran benar
harus logis. Untuk data yang ditandatangani (default), baik aritmatika atau pergeseran logis dapat
digunakan. Sayangnya ini berarti kode apapun dengan asumsi satu bentuk atau lainnya berpotensi
mengalami masalah portabilitas. Namun, dalam praktiknya, hampir semua kombinasi kompiler / mesin
menggunakan pergeseran tepat aritmetika untuk data yang ditandatangani, dan banyak pemrogram
menganggap ini sebagai masalahnya.

Java, di sisi lain, memiliki definisi yang tepat tentang bagaimana pergeseran benar harus
dilakukan. Ekspresi x >> k bergeser x secara aritmatika oleh posisi k, sementara x >>> k menggesernya
secara logis.
Selain pergeseran oleh k, untuk nilai k yang besar

Untuk tipe data yang terdiri dari w bit, apa yang harus menjadi efek pergeseran dengan beberapa
nilai k w? Sebagai contoh, apa yang seharusnya menjadi efek dari komputasi berikut ekspresi pada
mesin 32-bit:

int lval = 0xFEDCBA98 << 32;


int aval = 0xFEDCBA98 >> 36;
unsigned uval = 0xFEDCBA98u >> 40;

Standar C dengan hati-hati menghindari menyatakan apa yang harus dilakukan dalam kasus seperti
itu. Pada banyak mesin, instruksi pergeseran jumlah pergeseran mempertimbangkan secara efektif
hanya log rendah 2 w bit dari jumlah pergeseran saat menggeser nilai w-bit sehingga jumlah
pergeseran dihitung secara efektif sebagai k mod w. Sebagai contoh, pada mesin 32-bit yang
mengikuti konvensi ini, ketiga shift di atas dihitung seolah-olah jumlahnya masing-masing 0, 4, dan
8, memberikan hasil

lval 0xFEDCBA98
aval 0xFFEDCBA9
uval 0x00FEDCBA

Perilaku ini tidak dijamin untuk program C, bagaimanapun, dan jumlah pergeseran harus
dijaga kurang dari ukuran kata.

Java, di sisi lain, secara khusus mensyaratkan bahwa jumlah pergeseran harus dihitung
dengan mode modular yang telah kita tunjukkan.

Selain masalah pendahuluan operator dengan operasi shift


Mungkin tergoda untuk menuliskan ungkapan 1 << 2 + 3 << 4, bermaksud itu berarti (1 << 2) + (3 <<
4). Tapi, di C, ungkapan sebelumnya setara dengan 1 << (2 + 3) << 4, karena penambahan (dan
pengurangan) memiliki preseden yang lebih tinggi daripada pergeseran. Aturan asosiatif kiri-kanan
kemudian menyebabkan hal ini menjadi tanda kurung sebagai (1 << (2 + 3)) << 4, memberikan nilai
512, bukan 52 yang dimaksud.
Mendapatkan preseden yang salah dalam ekspresi C adalah sumber kesalahan program yang umum,
dan seringkali hal ini sulit ditemukan dengan inspeksi. Bila ragu, dimasukkan ke dalam tanda kurung!

Latihan Soal 2.16

Isi tabel di bawah ini menunjukkan efek dari pergeseran operasi yang berbeda pada jumlah byte
tunggal. Cara terbaik untuk memikirkan operasi pengalihan adalah bekerja dengan representasi
biner. Mengkonversi nilai awal menjadi biner, melakukan pergeseran, dan kemudian
mengkonversikan kembali ke heksadesimal. Masing-masing jawaban harus 8 digit biner atau 2
digit heksadesimal.

2.2 Integer Representasi

Pada bagian ini, kami menjelaskan dua cara yang berbeda bit dapat digunakan untuk
mengkodekan bilangan bulat satu yang hanya dapat mewakili bilangan nonnegatif, dan satu yang
dapat mewakili

Gambar 2.8 Rentang tipikal untuk tipe data integral C pada mesin 32-bit. Teks dalam tanda kurung siku
bersifat opsional.
Gambar 2.9 Rentang tipikal untuk tipe data integral C pada mesin 64-bit. Teks dalam tanda kurung siku
bersifat opsional.

negatif, nol, dan positif. Kita akan melihat kemudian bahwa keduanya sangat terkait baik dalam sifat
matematis dan penerapan tingkat mesinnya. Kami juga menyelidiki pengaruh perluasan atau penyusutan
bilangan bulat yang dikodekan agar sesuai dengan representasi dengan panjang yang berbeda.

2.2.1 Tipe Data Integral

C mendukung berbagai jenis data integral yang mewakili rentang bilangan bulat yang terbatas. Ini
ditunjukkan pada Gambar 2.8 dan 2.9, bersama dengan rentang nilai yang dapat mereka miliki untuk
mesin "khas" 32 dan 64-bit. Setiap jenis dapat menentukan ukuran dengan kata kunci char, pendek,
panjang, atau panjang, serta indikasi apakah jumlah yang terwakili semuanya tidak negatif (dinyatakan
sebagai unsigned), atau mungkin

Gambar 2.10 Kisaran yang dijamin untuk tipe data integral C. Teks dalam tanda kurung siku bersifat
opsional. Standar C mengharuskan tipe data memiliki setidaknya kisaran nilai ini.
negatif (default). Seperti yang kita lihat pada Gambar 2.3, jumlah byte yang dialokasikan untuk berbagai
ukuran berbeda-beda sesuai dengan ukuran kata mesin dan kompilatornya. Berdasarkan alokasi byte,
ukuran yang berbeda memungkinkan rentang nilai yang berbeda untuk diwakili. Kisaran tergantung
mesin hanya ditunjukkan untuk ukuran designator panjang. Sebagian besar mesin 64-bit menggunakan
representasi 8-byte, memberikan rentang nilai yang jauh lebih luas daripada representasi 4 byte yang
digunakan pada mesin 32-bit.

Salah satu fitur penting yang perlu diperhatikan pada Gambar 2.8 dan 2.9 adalah bahwa
rentangnya tidak simetris kisaran angka negatif memanjang satu lebih jauh dari kisaran angka positif. Kita
akan melihat mengapa ini terjadi ketika kita mempertimbangkan bagaimana angka negatif terwakili.

Standar C menentukan rentang nilai minimum yang harus dimiliki oleh masing-masing tipe
data. Seperti yang ditunjukkan pada Gambar 2.10, rentangnya sama atau lebih kecil dari pada
implementasi khas yang ditunjukkan pada Gambar 2.8 dan 2.9. Secara khusus, jika mereka hanya
memerlukan kisaran simetris bilangan positif dan negatif. Kita juga melihat bahwa tipe data int dapat
menjadi Diimplementasikan dengan nomor 2 byte, meskipun ini sebagian besar adalah kemunduran
pada hari 16 mesin 16-bit. Kita juga melihat ukuran yang panjang bisa diimplementasikan dengan nomor
4 byte, seperti yang sering terjadi. Tipe data lama diperkenalkan dengan ISO C99, dan memerlukan
setidaknya representasi 8 byte.

C Yang Baru? Nomor yang ditandatangani dan tidak ditandatangani di C, C ++, dan Java
Baik dukungan C dan C ++ ditandatangani (default) dan nomor unsigned. Java hanya mendukung
nomor yang ditandatangani.

2.2.2 Enkode yang tidak ditandatangani

Asumsikan kita memiliki tipe data integer dari w bits. Kami menulis vektor bit sebagai x, untuk
menunjukkan keseluruhan vektor, atau sebagai [xw-1,xw-2,...,x0], untuk menunjukkan bit individu dalam
vektor. Mengobati x sebagai angka yang ditulis dalam notasi biner, kita mendapatkan

Gambar 2.11 Contoh nomor yang tidak ditandai untuk w = 4. Bila bit i dalam representasi biner memiliki
nilai 1, maka akan memberikan kontribusi 2i terhadap nilainya.
interpretasi unsigned x. Kami mengekspresikan penafsiran ini sebagai fungsi B2U w (untuk "biner ke
unsigned," length w):

Dalam persamaan ini, notasi "=" berarti sisi kiri ditentukan sama dengan sisi kanan. Fungsi B2U w
memetakan string angka nol dan angka dengan bilangan bulat nonnegatif. Sebagai contoh, Gambar 2.11
menunjukkan pemetaan, yang diberikan oleh B2U, dari vektor bit ke bilangan bulat untuk kasus berikut:

B2U4([0001]) = 0 . 23 + 0 . 22 + 0 . 21 + 1 . 20 = 0+0+0+1 = 1
B2U4([0101]) = 0 . 23 + 1 . 22 + 0 . 21 + 1 . 20 = 0+4+0+1 = 5
B2U4([1011]) = 1 . 23 + 0 . 22 + 1 . 21 + 1 . 20 = 8+0+2+1 = 11
B2U4([1111]) = 1 . 23 + 1 . 22 + 1 . 21 + 1 . 20 = 8+4+2+1 = 15

Pada gambar, kita mewakili setiap posisi bit i dengan sebuah garis biru yang mengarah ke kanan dengan
panjang 2i. Nilai numerik yang terkait dengan vektor bit sama dengan panjang gabungan dari balok
dimana nilai bit yang sesuai adalah 1.

Mari kita pertimbangkan kisaran nilai yang bisa diwakili menggunakan w bits. Nilai paling sedikit
diberikan oleh vektor bit [00...0] memiliki nilai integer 0, dan nilai terbesar diberikan oleh vektor bit

[11...1] memiliki nilai integer UMax w = = 2w-1 . Dengan menggunakan case 4-bit sebagai
contoh, kita memiliki UMax4 = B2U4([1111]) = 24 1 = 15. Jadi, fungsinya B2Uw dapat didefinisikan
sebagai pemetaan B2Uw : {0,1}w {0,...,2w - 1}.

Representasi biner unsigned memiliki properti penting yang setiap bilangan antara 0 dan 2 w - 1
memiliki pengkodean unik sebagai nilai w-bit. Misalnya, hanya ada satu representasi nilai desimal 11
sebagai unsigned, bilangan 4 bit, yaitu [ 1011]. Properti ini ditangkap secara matematis dengan
menyatakan bahwa fungsi B2U adalah bijeksi - ini mengasosiasikan nilai unik untuk setiap vektor bit
dengan panjang w; Sebaliknya, setiap bilangan bulat antara 0 dan 2 w - 1 memiliki representasi biner yang
unik sebagai vektor bit dengan panjang w.

2.2.3 Pengkodean Komplemen Dua

Formulir aplikasi apapun, kami ingin mewakili nilai negatif juga. Representasi komputer yang paling
umum dari nomor yang ditandatangani dikenal sebagai bentuk pelengkap dua. Ini didefinisikan dengan
menafsirkan kata paling signifikan dari kata tersebut agar memiliki bobot negatif. Kami mengekspresikan
penafsiran ini sebagai fungsi B2T (untuk "biner ke dua komplemen" panjang w):

Bit xw-1 yang paling signifikan, disebut juga tanda bit. "Bobotnya" adalah 2 w-1, negasi bobotnya dalam
representasi unsigned. Bila bit tanda diset ke 1, nilai yang diwakili negatif, dan bila diset ke 0 nilainya
tidak negatif. Sebagai contoh, Gambar 2.12 menunjukkan pemetaan, yang diberikan oleh B2T, dari vektor
bit ke bilangan bulat untuk kasus berikut:
B2T4([0001]) = -0 . 23 + 0 . 22 + 0 . 21 + 1 . 20 = 0+0+0+1 = 1
B2T4([0101]) = -0 . 23 + 1 . 22 + 0 . 21 + 1 . 20 = 0+4+0+1 = 5
B2T4([1011]) = -1 . 23 + 0 . 22 + 1 . 21 + 1 . 20 = -8+0+2+1 = -5
B2T4([1111]) = -1 . 23 + 1 . 22 + 1 . 21 + 1 . 20 = -8+4+2+1 = -1

Pada gambar tersebut, kami menunjukkan bahwa bit tanda memiliki bobot negatif dengan
menunjukkannya sebagai bar abu-abu menunjuk ke kiri. Nilai numerik yang terkait dengan vektor bit
kemudian diberikan oleh kombinasi dari bar abu-abu menunjuk ke kiri dan palang biru penunjuk arah
kanan.

Gambar 2.12 Dua contoh nomor pelengkap untuk w = 4. Bit 3 berfungsi sebagai tanda sedikit, dan jadi,
bila diset ke 1, akan memberikan kontribusi -23 = -8 terhadap nilainya. Bobot ini ditunjukkan sebagai bar
abu-abu menunjuk ke kiri.

Kita melihat bahwa pola bit identik untuk Gambar 2.11 dan 2.12 (dan juga untuk Persamaan 2.2 dan 2.4),
namun nilainya berbeda bila bit paling signifikan adalah 1, karena dalam satu kasus memiliki bobot +8,
dan di sisi lain Kasus itu memiliki bobot -8. Mari kita perhatikan kisaran nilai pelengkap bilangan. Paling
representable yang dapat direpresentasikan sebagai nilai diberikan oleh vektor bit [10...0] (atur sedikit
dengan bobot negatif, tapi bersihkan semua yang lain), memiliki nilai integer Tmin w = -2w-1. Nilai terbesar
diberikan oleh vektor bit [01...0] (bersihkan sedikit dengan bobot negatif, tapi tetapkan yang lainnya),

memiliki nilai integer TMaxw = = 2w-1 -1. Dengan menggunakan case 4-bit sebagai contoh, kita
memiliki Tmin4 = B2T4([1000]) =-2 = -8 dan TMax4 = B2T4([0111]) = 22 + 21 + 20 =4 + 2 + 1= 7.
3

Kita bisa melihat bahwa B2Tw adalah pemetaan pola bit panjang w ke angka antara TMin w dan TMaxw ,
yang ditulis sebagai B2T w : {0,1}w {-2w-1,...,2w-1 - 1}. Seperti yang kita lihat dengan representatiteon
yang tidak bertanda tangan, setiap bilangan yang memiliki rentang representatif memiliki pengkodean
unik sebagai nomor pelengkap w-bit dua. Dalam istilah matematika, kita mengatakan bahwa fungsi B2T w
adalah bijeksi - ia menghubungkan nilai unik pada setiap vektor bit dengan panjang w; sebaliknya,
masing-masing bilangan bulat antara -2 w-1 dan 2w-1 -1 memiliki representasi biner yang unik sebagai
vektor bit dengan panjang w.
Latihan Soal 2.17

Dengan mengasumsikan w = 4, kita dapat menetapkan nilai numerik ke setiap digit heksadesimal yang
mungkin, dengan asumsi interpretasi pelengkap yang tidak ditandatangani atau dua. Isi tabel berikut
sesuai dengan interpretasi ini dengan menuliskan kekuatan nol dari dua di penjumlahan yang
ditunjukkan pada Persamaan 2.1 dan 2.3:

Gambar 2.13 menunjukkan pola bit dan nilai numerik untuk beberapa bilangan penting
untuk ukuran kata yang berbeda. Tiga yang pertama memberikan rentang bilangan bulat yang dapat
direpresentasikan dalam hal nilai ketiga nilai khusus ini sering dalam diskusi berikutnya. Kami akan
menurunkan subskrip w dan mengacu pada nilai UMax, TMin, dan TMax saat w dapat disimpulkan dari
konteks atau tidak penting dalam diskusi.

Beberapa poin patut disoroti tentang angka-angka ini. Pertama, seperti yang diamati
pada Gambar 2.8 dan 2.9, rangkaian pelengkap dua adalah asimetris: |Tmin| = |Tmax| + 1 yaitu, tidak
ada pasangan positif untuk TMin. Seperti yang akan kita lihat, ini mengarah pada beberapa sifat khas dari
dua aritmatika kompilasi dan dapat terjadi

Anda mungkin juga menyukai