C ++: mengapa bool panjangnya 8 bit?

132

Dalam C ++, saya bertanya-tanya mengapa tipe bool panjangnya 8 bit (di sistem saya), di mana hanya satu bit yang cukup untuk menyimpan nilai boolean?

Saya dulu percaya itu untuk alasan kinerja, tetapi kemudian pada mesin 32 bit atau 64 bit, di mana register lebar 32 atau 64 bit, apa keuntungan kinerja?

Atau hanya salah satu dari alasan 'historis' ini?

Jérôme
sumber
9
Bool bukan 8-bit pada sistem saya. Ini 4 byte, sama dengan int.
Brian Neal
21
Terakhir kali seseorang memikirkan apa yang Anda pikirkan, kami berakhir dengan std :: vector <bool>, "fitur" stl paling dibenci yang pernah =)
Viktor Sehr
1
jldupont, saya pikir Anda salah membaca saya. Saya meminta sistem, di mana sizeof(bool)4. Saya bisa bersumpah bahwa msvc memiliki 32-bit bools, tetapi saya hanya mencoba dan tidak.
avakar
7
Agar adil, masalah dengan vector<bool>bukan karena mencoba menjadi pintar dan mengemas bool menjadi bit, tetapi mencoba untuk melakukan ini dan menyamar sebagai wadah STL . Bitet biasa akan baik-baik saja asalkan tidak juga berpura-pura menjadi wadah STL.
jalf
2
@avakar - Anda mungkin membingungkan booltipe data C ++ dengan BOOLtipe Windows yang diketikkan long. Jadi sizeof(bool) != sizeof(BOOL), yang saya yakin menyebabkan banyak kebingungan (dan mungkin banyak bug). Terutama karena ada juga booleandan BOOLEANtypedef di Windows, yang merupakan alias untuk unsigned char. Juga, perhatikan bahwa meskipun umum untuk bool1 byte, standar C ++ memiliki catatan yang secara khusus menunjukkan bahwa sizeof(bool)bisa lebih besar.
Michael Burr

Jawaban:

219

Karena setiap tipe data C ++ harus dialamatkan.

Bagaimana Anda membuat pointer ke bit tunggal? Kamu tidak bisa Tapi Anda bisa membuat pointer ke byte. Jadi boolean di C ++ biasanya berukuran byte. (Ini mungkin lebih besar juga. Itu hingga implementasi. Hal utama adalah bahwa itu harus dialamatkan, sehingga tidak ada tipe data C ++ bisa lebih kecil dari satu byte)

jalf
sumber
7
pengalamatan "byte" adalah pilihan arsitektur (level hw): seseorang dapat merancang sistem dengan "unit pengalamatan" yang berbeda. Untuk prosesor umum, menangani "byte" bagaimanapun juga mengambil lebih dari "byte" dari memori eksternal: ini karena alasan efisiensi.
jldupont
8
Ya, ini pilihan perangkat keras, dan jika perangkat keras memungkinkan, ukuran bool bisa berubah. Tetapi OP bertanya mengapa bool memiliki lebar 8 bit, dan pada sistem yang merupakan kasusnya, umumnya karena CPU hanya mampu mengatasi byte 8-bit.
jalf
2
@ jldupont: Ada beberapa sistem di mana alamat pointer lebih berbutir daripada byte (saya sudah memprogram pada TI TMS34010 / 20 sebelumnya, yang menggunakan bit-wise pointer), tetapi mereka sangat jarang.
Michael Kohne
1
Tidak yakin apa yang kamu maksud. Setiap objek harus dapat dialamatkan, yaitu, harus mungkin untuk mengambil alamat suatu objek. Objek tidak harus menyimpan alamatnya sendiri. Lebar karakter biasanya 8 bit, cukup untuk menyimpan 256 karakter, tetapi setiap karakter juga memiliki alamat yang ditentukan oleh memori. Itu sebabnya Anda bisa membuat pointer ke char.
jalf
88
Jika saya dapat menyumbang analogi yang cerdik: ada delapan lantai di gedung saya, tetapi Kantor Pos tidak mengakui bahwa itu adalah alamat yang berbeda. Jadi jika saya ingin alamat untuk diri saya sendiri, maka saya harus menyewa seluruh bangunan, meskipun saya benar-benar muat di satu lantai. Saya tidak menggunakan tujuh lantai lainnya untuk "menyimpan alamat", saya hanya terpaksa membuangnya karena aturan Kantor Pos yang merujuk pada bangunan, bukan lantai. Objek C ++ harus memiliki alamat untuk diri mereka sendiri - tidak ada ruang pos untuk menyortir surat setelah pengiriman ;-)
Steve Jessop
39

Memori byte addressable. Anda tidak dapat menangani sedikit pun, tanpa menggeser atau menutupi byte yang dibaca dari memori. Saya akan membayangkan ini adalah alasan yang sangat besar.

Stephen Roantree
sumber
1
Tidak selalu. The 8051 MCU, misalnya, memiliki 16 byte lokasi yang dapat dialamatkan bit
Beached
20

Suatu booleantipe biasanya mengikuti unit terkecil dari memori yang dapat dialamatkan dari mesin target (yaitu biasanya byte 8bits).

Akses ke memori selalu dalam "potongan" (banyak kata, ini untuk efisiensi di tingkat perangkat keras , transaksi bus): bit boolean tidak dapat diatasi "sendirian" di sebagian besar sistem CPU. Tentu saja, begitu data terkandung dalam register , seringkali ada instruksi khusus untuk memanipulasi bit secara independen.

Untuk alasan ini, sangat umum untuk menggunakan teknik "bit packing" untuk meningkatkan efisiensi dalam menggunakan tipe data base "boolean". Teknik seperti enum(dalam C) dengan kekuatan 2 pengkodean adalah contoh yang baik. Trik yang sama ditemukan di sebagian besar bahasa.

Diperbarui : Berkat diskusi yang luar biasa, saya tertarik sizeof(char)==1pada definisi C ++. Oleh karena itu, menangani tipe data "boolean" sangat terkait dengan unit terkecil dari memori yang dapat dialamatkan (memperkuat poin saya).

jldupont
sumber
Untuk semua komentar yang Anda tinggalkan tentang hal ini, sangat mengesankan bahwa Anda meninggalkan bagian terpenting dari jawaban: Suatu booltipe mengikuti unit terkecil dari memori yang dapat dialokasikan karena C ++ mengharuskan Anda harus membuat pointer ke sana . Tanpa persyaratan itu, a boolbisa saja direpresentasikan sebagai bit tunggal bahkan pada mesin byte-addressable saat ini.
jalf
1
hmmm ... Saya bisa membuat arsitektur CPU di mana sedikit bisa dialamatkan ... Saya bahkan bisa menulis kompiler dll untuk itu. Saya dapat memiliki wilayah memori khusus (atau apa pun) yang akan "bit addressable". Ini bukan imajinasi mustahil.
jldupont
2
Ya, dan pada sistem itu, bool bisa dibuat menjadi satu bit. Tetapi OP tidak bertanya "mengapa lebar bool 8 bit pada CPU hipotetis jlduponts". Dia bertanya tentang CPU saat ini, umum, sehari-hari, dan pada itu, itu karena mereka byte-addressable.
jalf
4
sizeof (char) == 1 per definisi dalam C ++, jadi apa yang bisa atau tidak bisa dilakukan oleh perangkat keras Anda tidak relevan. Anda tidak dapat memiliki sizeof (bool) <sizeof (char). BTW C ++ didefinisikan sedemikian rupa sehingga Anda dapat memiliki "gemuk" pointer untuk mengatasi beberapa subunit dari apa perangkat keras dapat mengatasi jika tidak nyaman untuk memiliki unit perangkat keras yang bisa dialamatkan char. Ini telah digunakan setidaknya dalam beberapa kompiler C untuk arsitektur addressable kata lama.
Pemrogram
@AProgrammer:: sizeof(char)==1 definitionitulah argumen balasan terbaik untuk argumentasi saya. Terima kasih!
jldupont
6

Jawaban tentang 8-bit menjadi jumlah terkecil dari memori yang dapat dialamatkan adalah benar. Namun, beberapa bahasa dapat menggunakan 1-bit untuk boolean, dengan cara tertentu. Saya ingat Pascal mengimplementasikan set sebagai string bit. Yaitu, untuk set berikut:

{1, 2, 5, 7}

Anda mungkin memiliki ini dalam memori:

01100101

Anda dapat, tentu saja, melakukan sesuatu yang serupa di C / C ++ jika Anda mau. (Jika Anda melacak sekelompok boolean, itu bisa masuk akal, tetapi itu benar-benar tergantung pada situasinya.)

Benjamin Oakes
sumber
8
Faktanya, C ++ melakukan ini dengan vektor wadah khusus <bool> - ini biasanya dilihat sebagai bencana.
C ++ juga melakukan ini dengan "bidang bit," yang diwarisi dari C. Saat mendeklarasikan variabel anggota dari struct / kelas, Anda dapat mendeklarasikan jumlah bit yang digunakan untuk menyimpan nilai (misalnya, "bidang pendek yang tidak ditandai: 3").
@Neil: mengapa sering dianggap sebagai bencana? Apakah ini masalah kinerja?
Jérôme
2
@ Jerome: Itu karena, karena sedikit tidak dapat dialamatkan, itu tidak bisa berperilaku seperti biasa vector. Ini sebenarnya bukan tipe wadah STL, karena ada kendala pada perilaku. Yang lebih buruk adalah bahwa hal itu menyebabkan masalah dengan seseorang yang memiliki booldan ingin membuatnya vector. Itu adalah perilaku yang mengejutkan, dan bukan itu yang Anda inginkan dalam suatu bahasa.
David Thornley
1
@ jldupont - cukup membuat poin seperti ini sekali saja. Dan C + + tidak membuat jaminan bahwa bit dapat dialamatkan (bukan sebaliknya), tidak peduli apa perangkat keras mampu.
1

Saya tahu ini sudah tua tapi saya pikir saya akan memasukkan 2 sen saya.

Jika Anda membatasi tipe boolean atau data Anda menjadi satu bit saja maka aplikasi Anda berisiko mengalami peningkatan memori. Bagaimana Anda menangani statistik kesalahan dalam memori yang hanya satu bit?

Saya pergi ke sebuah wawancara kerja dan salah satu pernyataan yang ketua program katakan kepada saya adalah, "Ketika kami mengirim sinyal untuk meluncurkan rudal, kami hanya mengirim bit on-bit sederhana melalui nirkabel. Mengirim satu bit sangat cepat dan kami membutuhkan sinyal itu secepat mungkin. "

Yah, itu adalah tes untuk melihat apakah saya memahami konsep dan bit, byte, dan penanganan kesalahan. Betapa mudahnya bagi orang jahat untuk mengirim pesan satu bit. Atau apa yang terjadi jika selama transmisi bit akan terbalik.

Cire
sumber
Ajukan pertanyaan baru , jangan posting pertanyaan Anda sebagai jawaban untuk pertanyaan lain.
Igor Jerosimić
6
Saya pikir pertanyaan yang terkandung dalam "jawaban" ini sebenarnya adalah pertanyaan retoris, yaitu alasan kami tidak menerapkan boolean sebagai satu bit adalah karena bit tunggal tidak dapat menangani statistik kesalahan.
Stephen Holt
1
@StephenHolt tapi itu bukan alasan dan TBH jawaban ini tidak masuk akal.
doc
1
...apa? Saya tidak tahu apa yang Anda maksud dengan "statistik kesalahan", apakah CRC atau sejenisnya, atau representasi perangkap. Tetapi bagaimanapun juga, tipe yang lebih besar tidak menggunakan bit 'ekstra' ekstra mereka untuk "statistik kesalahan" karena semua kecuali pembuat kode lingkungan ekstrem menganggap perangkat keras mereka dapat menangani deteksi / koreksi kesalahan sebelum kode mereka membaca memori, sehingga mereka tidak perlu menghabiskan waktu mereka entah bagaimana melapisi setiap variabel dengan info verifikasi atau apa pun. Itu tidak mengapa boolmenggunakan 8 bit pada mesin OP dan 32 pada tambang, karena 7 atau 31 bit lainnya tentu tidak digunakan untuk "statistik kesalahan". Ini tidak masuk akal
underscore_d
1

Beberapa kompiler tertanam memiliki tipe int1 yang digunakan untuk mengemas flag boolean (misalnya seri CCS dari kompiler C untuk Microchip MPU's). Pengaturan, kliring, dan pengujian variabel-variabel ini menggunakan instruksi level bit instruksi tunggal, tetapi kompiler tidak akan mengizinkan operasi lain (misalnya mengambil alamat variabel), karena alasan yang disebutkan dalam jawaban lain.

EBlake
sumber