Mengapa ukuran boolean 1 byte dan bukan 1 bit?

127

Di C ++,

  • Mengapa ukuran boolean 1 byte dan bukan 1 bit?
  • Mengapa tidak ada tipe seperti bilangan bulat 4-bit atau 2-bit?

Saya melewatkan hal-hal di atas saat menulis emulator untuk CPU

Asm
sumber
10
Dalam C ++ Anda dapat "mengemas" data dengan menggunakan bit-fields. struct Packed { unsigned int flag1 : 1; unsigned int flag2: 1; };. Kebanyakan kompiler akan mengalokasikan penuh unsigned int, namun mereka menangani bit-twiddling itu sendiri saat Anda membaca / menulis. Juga mereka menangani sendiri operasi modulo. Itu adalah unsigned small : 4atribut yang memiliki nilai antara 0 dan 15, dan ketika harus mencapai 16, itu tidak akan menimpa bit sebelumnya :)
Matthieu M.

Jawaban:

208

Karena CPU tidak dapat menangani sesuatu yang lebih kecil dari satu byte.

Paul Tomblin
sumber
10
Sial, sekarang canggung Pak
Asm
31
Sebenarnya, empat x86 petunjuk bt, bts, btrdan btc dapat mengatasi bit tunggal!
fredoverflow
11
Saya pikir btalamat offset byte dan kemudian menguji bit pada offset tertentu, terlepas dari itu, ketika menentukan alamat yang Anda masukkan dalam byte ... literal offset bit akan menjadi sedikit bertele-tele (maafkan permainan kata).
pengguna7116
2
@six: Anda dapat memuat awal array dalam satu register dan kemudian relatif "bit offset" ke dalam satu detik. Bit offset tidak terbatas pada "dalam satu byte", dapat berupa nomor 32 bit apa pun.
fredoverflow
4
Ya dan tidak. Kami memiliki bitfield, dan kami dapat memiliki penunjuk bitfield, yaitu alamat + nomor bit. Jelas, pointer seperti itu tidak akan dapat diubah menjadi void * karena persyaratan penyimpanan ekstra untuk nomor bit.
Maxim Egorushkin
32

Dari Wikipedia :

Secara historis, byte adalah jumlah bit yang digunakan untuk menyandikan satu karakter teks di komputer dan karena alasan inilah elemen beralamat dasar di banyak arsitektur komputer.

Jadi byte adalah yang satuan dialamatkan dasar , di bawah ini yang arsitektur komputer tidak bisa alamat. Dan karena tidak (mungkin) ada komputer yang mendukung 4-bit byte, Anda tidak memiliki 4-bit bool dll.

Namun, jika Anda dapat merancang arsitektur yang dapat menangani 4-bit sebagai unit beralamat dasar, maka Anda akan memiliki boolukuran 4-bit, hanya di komputer itu!

Nawaz
sumber
4
"Anda akan memiliki int berukuran 4-bit, maka hanya di komputer itu" - tidak, Anda tidak akan, karena standar melarang CHAR_BIT kurang dari 8. Jika unit yang dapat dialamatkan pada arsitektur kurang dari 8 bit, maka a Implementasi C ++ hanya perlu menampilkan model memori yang berbeda dari model memori perangkat keras yang mendasarinya.
Steve Jessop
@ Steve: oops ... Saya mengabaikan itu. Dihapusint dan chardari postingan saya.
Nawaz
1
Anda juga tidak dapat memiliki 4-bit bool, karena charini adalah unit terkecil yang dapat dialamatkan dalam C ++ , terlepas dari apa yang dapat ditangani oleh arsitektur dengan opcode-nya sendiri. sizeof(bool)harus memiliki nilai minimal 1, dan boolobjek yang berdekatan harus memiliki alamatnya sendiri di C ++ , jadi penerapannya hanya perlu membuatnya lebih besar dan membuang memori. Itulah mengapa bit field ada sebagai kasus khusus: anggota bitfield dari struct tidak diharuskan untuk dapat dialamatkan secara terpisah, jadi mereka bisa lebih kecil dari a char(walaupun struct keseluruhan masih tidak bisa).
Steve Jessop
@ Steve Jessop: sepertinya menarik. bisakah Anda memberi saya referensi dari spesifikasi bahasa yang menyatakan charadalah unit beralamat terkecil dalam C ++?
Nawaz
3
Pernyataan spesifik terdekat mungkin 3.9 / 4: "Representasi objek dari sebuah objek tipe T adalah urutan dari objek char unsigned N yang diambil oleh objek tipe T, di mana N sama dengan sizeof (T)". Jelas sizeof(bool)tidak bisa 0,5 :-) Saya kira sebuah implementasi secara legal dapat menyediakan pointer sub-byte sebagai perpanjangan, tetapi objek "biasa" seperti bool, dialokasikan dengan cara biasa, harus melakukan apa yang dikatakan standar.
Steve Jessop
12

Jawaban termudah adalah; itu karena CPU mengalamatkan memori dalam byte dan bukan dalam bit, dan operasi bitwise sangat lambat.

Namun, dimungkinkan untuk menggunakan alokasi ukuran bit di C ++. Ada spesialisasi std :: vector untuk vektor bit, dan juga struct mengambil entri berukuran bit.

sukru
sumber
1
Tidak yakin saya setuju bahwa operasi bitwise lambat. ands, nots, xors dll sangat cepat. Biasanya implementasi operasi bitwise yang lambat. Pada level mesin, mereka cukup cepat. Bercabang ... sekarang lambat.
Hogan
3
Untuk lebih jelasnya, jika Anda membuat vektor boolean dan memasukkan 24 boolean ke dalamnya, maka hanya akan mengambil 3 byte (3 * 8). Jika Anda memasukkan boolean lain, itu akan membutuhkan satu byte lagi. Namun, jika Anda mendorong boolean lain, itu tidak akan membutuhkan byte tambahan karena menggunakan bit "gratis" di byte terakhir
Pedro Loureiro
ya, saya juga meragukan operasinya lambat :)
Pedro Loureiro
Vektor bit tidak membuat alokasi berukuran bit. mereka membuat alokasi berukuran byte. Tidak mungkin mengalokasikan sedikit pun.
John Dibling
1
Membaca satu bit dalam vektor bit memerlukan tiga operasi: shift, dan, dan shift lain lagi. Menulis itu dua. Sedangkan byte individu dapat diakses dengan satu byte.
sukru
7

Kembali ke masa lalu ketika saya harus berjalan ke sekolah dalam badai salju yang mengamuk, menanjak dua arah, dan makan siang adalah hewan apa pun yang dapat kami lacak di hutan di belakang sekolah dan bunuh dengan tangan kosong, komputer memiliki memori yang jauh lebih sedikit daripada yang tersedia. hari ini. Komputer pertama yang saya gunakan memiliki RAM 6K. Bukan 6 megabyte, bukan 6 gigabyte, 6 kilobyte. Dalam lingkungan itu, sangat masuk akal untuk mengemas sebanyak mungkin boolean ke dalam int, jadi kami akan secara teratur menggunakan operasi untuk mengeluarkan dan memasukkannya.

Saat ini, ketika orang-orang mengejek Anda karena hanya memiliki 1 GB RAM, dan satu-satunya tempat Anda dapat menemukan hard drive dengan kurang dari 200 GB adalah di toko barang antik, tidak ada gunanya mengemas sedikit.

Jay
sumber
Kecuali saat berhadapan dengan Flags. Hal-hal seperti Menyetel beberapa opsi pada sesuatu ... mis. 00000001 + 00000100 = 00000101.
Armstrongest
@Atomix: Saya hampir tidak pernah melakukan ini lagi. Jika saya membutuhkan dua bendera, saya membuat dua bidang boolean. Saya biasa menulis kode di mana saya akan mengemas bendera seperti itu dan kemudian menulis "if flags & 0x110! = 0 then" atau sejenisnya, tetapi ini samar dan akhir-akhir ini saya biasanya membuat bidang terpisah dan menulis "if fooFlag || barFlag " sebagai gantinya. Saya tidak akan mengesampingkan kemungkinan kasus di mana mengemas bendera seperti itu lebih baik untuk beberapa alasan, tetapi tidak lagi perlu menyimpan memori seperti dulu.
Jay
2
Sebenarnya, cukup sepadan dengan masalah Anda untuk mengemas bit, jika Anda ingin komputasi Anda cepat - pada sejumlah besar data yang Anda simpan di memori. Mengemas boolean tidak hanya untuk penyimpanan yang lebih kecil - ini berarti Anda dapat membaca array input boolean 8 kali lebih cepat (dalam hal bandwidth) seperti saat mereka dibuka, dan itu seringkali cukup signifikan. Selain itu, Anda dapat menggunakan operasi bit, seperti popc (jumlah populasi) yang mempercepat pekerjaan Anda pada CPU itu sendiri.
einpoklum
2
Jumlah boolean yang benar-benar besar adalah apa yang Anda kerjakan setiap hari jika Anda melakukannya: DBMS, pembelajaran mesin, simulasi ilmiah, dan banyak hal lainnya. Dan - hanya mengerjakannya berarti menyalinnya - dari memori ke cache. Sejuta uang bukanlah apa-apa, pikirkan miliaran.
einpoklum
1
@PeterCordes Ya, tentu saja, jika saya memiliki satu set boolean yang secara logis merupakan "ide yang sama" sehingga saya secara alami menganggapnya sebagai "array" dalam arti tertentu, dan jika saya kemudian akan menutupi atau memfilternya atau jika tidak, lakukan operasi bitwise pada mereka, maka mengemasnya menjadi byte mungkin masuk akal. Seperti yang saya katakan sebelumnya, saya sulit sekali memikirkan terakhir kali saya mengerjakan aplikasi di mana kondisi tersebut diterapkan, tetapi Anda memberikan beberapa contoh yang baik, dan saya yakin dengan sedikit imajinasi seseorang dapat memikirkan orang lain.
Jay
6

Anda dapat menggunakan bidang bit untuk mendapatkan bilangan bulat dengan ukuran sub.

struct X
{
    int   val:4;   // 4 bit int.
};

Meskipun biasanya digunakan untuk memetakan struktur ke pola bit yang diharapkan perangkat keras secara tepat:

struct SomThing   // 1 byte value (on a system where 8 bits is a byte
{
    int   p1:4;   // 4 bit field
    int   p2:3;   // 3 bit field
    int   p3:1;   // 1 bit
};
Martin York
sumber
6

Anda bisa memiliki bit 1-bit dan int 4 dan 2-bit. Tapi itu akan membuat set instruksi aneh tanpa perolehan kinerja karena itu cara yang tidak wajar untuk melihat arsitektur. Sebenarnya masuk akal untuk "membuang" bagian yang lebih baik dari satu byte daripada mencoba untuk mendapatkan kembali data yang tidak digunakan itu.

Satu-satunya aplikasi yang mengganggu untuk mengemas beberapa bools menjadi satu byte, menurut pengalaman saya, adalah Sql Server.

Paul Sasik
sumber
6

Karena byte adalah unit beralamat terkecil dalam bahasa tersebut.

Tetapi Anda dapat membuat bool take 1 bit misalnya jika Anda memiliki banyak mis. dalam struct, seperti ini:

struct A
{
  bool a:1, b:1, c:1, d:1, e:1;
};
bratao
sumber
2

boolbisa satu byte - ukuran CPU terkecil yang dapat dialamatkan, atau bisa lebih besar. Bukan hal yang aneh harus boolberukuran sebesar itu intuntuk tujuan kinerja. Jika untuk tujuan tertentu (katakanlah simulasi perangkat keras) Anda memerlukan tipe dengan N bit, Anda dapat menemukan perpustakaan untuk itu (misalnya perpustakaan GBL memiliki BitSet<N>kelas). Jika Anda khawatir dengan ukuran bool(Anda mungkin memiliki wadah besar,) maka Anda dapat mengemas bit sendiri, atau gunakan std::vector<bool>yang akan melakukannya untuk Anda (hati-hati dengan yang terakhir, karena tidak memenuhi persyaratan wadah).

Gene Bushuyev
sumber
2

Pikirkan tentang bagaimana Anda akan mengimplementasikan ini pada level emulator Anda ...

bool a[10] = {false};

bool &rbool = a[3];
bool *pbool = a + 3;

assert(pbool == &rbool);
rbool = true;
assert(*pbool);
*pbool = false;
assert(!rbool);
franji1
sumber
2

Karena pada umumnya CPU mengalokasikan memory dengan 1 byte sebagai basic unitnya, meskipun beberapa CPU seperti MIPS menggunakan word 4 byte.

Namun vectortransaksi booldengan cara khusus, dengan vector<bool>satu bit untuk setiap bool dialokasikan.

Ryan Li
sumber
1
Saya percaya bahkan cpu MIPS akan memberi Anda akses ke byte individu, meskipun ada hukuman kinerja.
Paul Tomblin
@Paul: Ya, Anda benar, tetapi umumnya kata-spesifik lw/ swjauh lebih banyak digunakan.
Ryan Li
Tidak tahu tentang MIPS, tetapi arsitektur IA-64 hanya mengizinkan akses pada batas 64-bit.
Gene Bushuyev
0

Byte adalah unit penyimpanan data digital yang lebih kecil dari sebuah komputer. Di komputer, RAM memiliki jutaan byte dan siapa pun di antaranya memiliki alamat. Jika ia memiliki alamat untuk setiap bit, komputer dapat mengelola RAM 8 kali lebih sedikit dari yang ia bisa.

Info lebih lanjut: Wikipedia

Francesco Pasa
sumber
0

Meskipun ukuran minimum yang memungkinkan adalah 1 Byte, Anda dapat memiliki 8 bit informasi boolean pada 1 Byte:

http://en.wikipedia.org/wiki/Bit_array

Bahasa Julia memiliki BitArray misalnya, dan saya membaca tentang implementasi C ++.

Diego Javier Zea
sumber