Neden 1 bit boyutunda değil de boole 1 bayttır?


127

C ++ 'da,

  • Neden 1 bit boyutunda değil de boole 1 bayttır?
  • Neden 4 bitlik veya 2 bitlik tamsayılar gibi türler yok?

Bir CPU için bir emülatör yazarken yukarıdaki şeyleri kaçırıyorum


10
C ++ 'da, verileri bit alanlarını kullanarak "paketleyebilirsiniz". struct Packed { unsigned int flag1 : 1; unsigned int flag2: 1; };. Çoğu derleyici bir tam unsigned intayırır, ancak okurken / yazarken kendileri bit çevirme ile ilgilenirler. Ayrıca modulo işlemlerini kendi başlarına hallederler. Bu a, unsigned small : 4:) özelliği, 0 ile 15 arasında bir değere sahiptir, ve 16 almak gerekir, bunun önceki bit üzerine değil
Matthieu M.

Yanıtlar:


208

Çünkü CPU, bayttan daha küçük bir şeyi adresleyemez.


10
Lanet olsun, şimdi bu garip efendim
Asm

31
Aslında dört x86 talimatları bt, bts, btrve btc olabilir tek bit adres!
fredoverflow

11
Bence btbir bayt ofsetini ele alıyor ve sonra biti belirli bir ofsette test ediyor, bayt cinsinden girdiğiniz bir adresi belirtirken ... bit ofset değişmezleri biraz kelime gibi olur (özür dilerim).
user7116

2
@six: Bir dizinin başlangıcını bir kayıtta ve sonra göreceli "bit ofsetini" bir saniyeye yükleyebilirsiniz. Bit ofseti "bir bayt içinde" ile sınırlı değildir, herhangi bir 32 bitlik sayı olabilir.
fredoverflow

4
Hem evet hem hayır. Bit alanlarımız var ve adres + bit numarası olan bir bit alanı işaretçimiz olabilir. Açıktır ki, böyle bir gösterici, bit numarası için ekstra depolama gereksinimi nedeniyle boşluğa * dönüştürülemez.
Maxim Egorushkin

32

Gönderen Vikipedi :

Tarihsel olarak, bir bayt, bir bilgisayardaki tek bir metin karakterini kodlamak için kullanılan bit sayısıdır ve bu nedenle , birçok bilgisayar mimarisinde temel adreslenebilir öğedir .

Bayt olduğunu Yani temel adreslenebilir birim , aşağıda bilgisayar mimarisi adresi olamaz. Ve (muhtemelen) 4 bitlik baytı destekleyen bilgisayarlar olmadığından, 4 bit vb. bool

Ancak, temel adreslenebilir birim olarak 4 biti adresleyebilen böyle bir mimari tasarlayabilirseniz, o zaman boolyalnızca o bilgisayarda 4 bit boyutuna sahip olursunuz !


4
"o zaman, sadece o bilgisayarda 4 bitlik int boyutuna sahip olacaksınız" - hayır yapmayacaksınız, çünkü standart CHAR_BIT'in 8'den küçük olmasını yasaklıyor. Mimari üzerindeki adreslenebilir birim 8 bitten küçükse, o zaman a C ++ uygulamasının, temeldeki donanımın bellek modelinden farklı bir bellek modeli sunması gerekecektir.
Steve Jessop

@Steve: oops ... Bunu gözden kaçırdım. Kaldırıldı intve chargönderimden.
Nawaz

1
4-bit'e de sahip olamazsınız bool, çünkü C ++ 'dakichar en küçük adreslenebilir birim , mimarinin kendi işlem kodlarıyla neyi ele alabildiğine bakılmaksızın. en az 1 değerine sahip olmalı ve bitişik nesnelerin C ++ ' da kendi adresleri olmalıdır , bu nedenle uygulama onları büyütmeli ve hafızayı boşa harcamalıdır. Bu nedenle bit alanları özel bir durum olarak mevcuttur: Bir yapının bit alanı üyelerinin ayrı ayrı adreslenebilir olması gerekmez, bu nedenle a'dan daha küçük olabilirler (tüm yapı hala olamaz). sizeof(bool)boolchar
Steve Jessop

@ Steve Jessop: Bu ilginç görünüyor. Lütfen bana charC ++ 'da adreslenebilir en küçük birim olduğunu söylediği dil spesifikasyonundan referans verebilir misiniz ?
Nawaz

3
En yakın spesifik ifade muhtemelen 3.9 / 4'tür: "T tipi bir nesnenin nesne temsili, N'nin sizeof (T) 'ye eşit olduğu, T tipi nesne tarafından alınan N işaretsiz karakter dizisidir." Açıkçası sizeof(bool)0.5 :-) olamaz. Sanırım bir uygulama yasal olarak bir uzantı olarak alt bayt işaretçileri sağlayabilir, ancak sıradan yollarla tahsis edilen bool gibi "sıradan" nesneler, standardın söylediğini yapmak zorundadır.
Steve Jessop

12

En kolay cevap; Bunun nedeni CPU'nun belleği bit olarak değil bayt cinsinden adreslemesi ve bitsel işlemlerin çok yavaş olmasıdır.

Bununla birlikte, C ++ 'da bit boyutu ayırmayı kullanmak mümkündür. Bit vektörleri için std :: vektör uzmanlaşması ve ayrıca bit boyutlu girdiler alan yapılar vardır.


1
Bitsel işlemlerin yavaş olduğunu kabul ettiğimden emin değilim. ves, nots, xors vb. çok hızlıdır. Genellikle yavaş olan bitsel işlemlerin uygulanmasıdır. Makine seviyesinde oldukça hızlılar. Dallanma ... şimdi bu yavaş.
Hogan

3
Daha açık hale getirmek için, bir boole vektörü yaratırsanız ve içine 24 boole koyarsanız, yalnızca 3 bayt (3 * 8) alacaktır. Başka bir boole koyarsanız, başka bir bayt alacaktır. Yine de, başka bir boole'yi iterseniz, son bayttaki "ücretsiz" bitleri kullandığı için fazladan bayt almayacaktır
Pedro Loureiro

evet, biraz da olsa işlemlerin yavaş olduğundan da şüpheliyim :)
Pedro Loureiro

Bit vektörleri, bit boyutlu tahsisler oluşturmaz. bayt boyutlu tahsisler oluştururlar. Tek bir bit tahsis etmek mümkün değildir.
John Dibling

1
Bir bit vektöründeki tek bir biti okumak üç işlem gerektirir: shift ve ve ve tekrar başka bir shift. Yazmak iki. Oysa tek tek baytlara tek bir tane ile erişilebilir.
sukru

7

Eski günlerde, şiddetli bir kar fırtınasında, her iki yönde de yokuş yukarı okula yürümek zorunda kaldığım ve öğle yemeğinin, okulun arkasındaki ormanda izleyip çıplak ellerimizle öldürebileceğimiz hayvan olduğu zamanlarda, bilgisayarların hafızası çok daha azdı. bugün. Şimdiye kadar kullandığım ilk bilgisayarda 6K RAM vardı. 6 megabayt değil, 6 gigabayt değil, 6 kilobayt. Bu ortamda, olabildiğince çok boolean bir int içine yerleştirmek çok mantıklıydı ve bu yüzden onları çıkarmak ve yerleştirmek için düzenli olarak işlemleri kullanırdık.

Bugün, insanlar yalnızca 1 GB RAM'e sahip olduğunuz için sizinle dalga geçecek ve 200 GB'den daha az bir sabit diski bulabileceğiniz tek yer bir antika dükkanı olduğunda, bit paketlemeye değmez.


Bayraklarla uğraşma durumu hariç. Bir şeye birden çok seçenek ayarlamak gibi şeyler ... örneğin. 00000001 + 00000100 = 00000101.
Armstrongest

@Atomix: Bunu artık neredeyse hiç yapmıyorum. İki bayrağa ihtiyacım olursa, iki boole alanı yaratırım. Bayrakları bu şekilde paketleyeceğim yerde kod yazardım ve sonra "if flags & 0x110! = 0 then" veya benzeri yazardım, ancak bu şifreli ve bu günlerde genellikle ayrı alanlar yapıp "if fooFlag || barFlag" yazıyorum " yerine. Bazı nedenlerden ötürü bu tür bayrakları paketlemenin daha iyi olduğu durumları göz ardı etmem, ancak artık eskisi gibi hafızadan tasarruf etmeye gerek yok.
Jay

2
Aslında, öyle oldukça sen bellekte saklamak verilerin ilgili geniş miktarına - Eğer hesaplama hızlı olmasını istiyorsanız, bit paketi için sorun değer. Boole'ları paketlemek yalnızca daha küçük depolama için değildir - boolean girdi dizilerinizi, paketten çıkarıldıklarında 8 kat daha hızlı (bant genişliği açısından) okuyabileceğiniz anlamına gelir ve bu genellikle oldukça önemlidir. Ayrıca, CPU üzerindeki çalışmanızı hızlandıran popc (nüfus sayımı) gibi bit işlemlerini de kullanabilirsiniz.
einpoklum

2
Gerçekten çok sayıda boole, her gün çalıştığınız şeydir: DBMS'ler, makine öğrenimi, bilimsel simülasyonlar ve daha pek çok şey. Ve - sadece üzerinde çalışmak demek onları - bellekten önbelleğe kopyalamak demektir. Bir milyon bool hiçbir şeydir, milyarlarca düşünün.
einpoklum

1
@PeterCordes Evet, kesinlikle, mantıksal olarak "aynı fikir" olan bir boole kümem olsaydı, böylece doğal olarak onları bir anlamda bir "dizi" olarak düşünürsem ve sonra onları maskeleyeceksem veya filtreleyeceksem veya aksi takdirde bunlarda bit düzeyinde işlemler gerçekleştirirseniz, bunları baytlar halinde paketlemek mantıklı olabilir. Daha önce de söylediğim gibi, bu koşulların uygulandığı bir uygulama üzerinde en son çalıştığım zamanı düşünmekte zorlanıyorum, ancak birkaç iyi örnek veriyorsunuz ve eminim biraz hayal gücüyle başkalarını da düşünebilirsiniz.
Jay

6

Alt boyuttaki tam sayıları elde etmek için bit alanlarını kullanabilirsiniz.

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

Genellikle yapıları donanımdan beklenen tam bit desenleriyle eşlemek için kullanılsa da:

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
};

6

1 bitlik bool'lara ve 4 ve 2 bitlik girişlere sahip olabilirsiniz. Ancak bu, mimariye bakmanın doğal olmayan bir yolu olduğu için, hiçbir performans kazancı sağlamayan garip bir talimat seti oluşturur. Kullanılmayan verileri geri almaya çalışmaktansa, baytın daha iyi bir bölümünü "harcamak" aslında mantıklı.

Tecrübelerime göre, birkaç bool'u tek bir bayta yerleştirmeyi zahmet eden tek uygulama Sql Server'dır.


6

Çünkü bayt, dildeki en küçük adreslenebilir birimdir.

Ancak bool'un 1 bit almasını sağlayabilirsiniz, örneğin bunlardan bir grup varsa, örn. bir yapıda, şöyle:

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

2

boolbir bayt olabilir - adreslenebilir en küçük CPU boyutu veya daha büyük olabilir. Performans amacıyla boolboyutunun olması alışılmadık bir durum değil int. Belirli amaçlar için (örneğin donanım simülasyonu) N bitli bir türe ihtiyacınız varsa, bunun için bir kitaplık bulabilirsiniz (örneğin, GBL kitaplığının BitSet<N>sınıfı vardır). Eğer boyutuyla ilgileniyorsanız bool(muhtemelen büyük bir kabınız var) o zaman parçaları kendiniz paketleyebilir veya std::vector<bool>sizin için yapacak olanı kullanabilirsiniz (konteyner gereksinimlerini karşılamadığından ikincisine dikkat edin).


2

Bunu emülatör seviyenizde nasıl uygulayacağınızı düşünün ...

bool a[10] = {false};

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

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

2

Çünkü MIPS gibi bazı CPU'lar 4 baytlık bir kelime kullansa da, CPU genel olarak belleği 1 baytlık temel birim olarak ayırır.

Bununla birlikte , her bool için bir bit olan özel bir şekilde vectoranlaşmalar tahsis edilir.boolvector<bool>


1
Performans cezası olsa da MIPS cpu'nun bile size bireysel bir bayta erişim sağlayacağına inanıyorum.
Paul Tomblin

@Paul: Evet haklısınız, ancak genellikle kelimeye özgü lw/ swçok daha yaygın olarak kullanılıyor.
Ryan Li

MIPS hakkında bilmiyorum, ancak IA-64 mimarisi yalnızca 64 bit sınırında erişime izin veriyor.
Gene Bushuyev

0

Bayt, bir bilgisayarın dijital veri depolama birimidir. Bir bilgisayarda RAM milyonlarca bayta sahiptir ve bunlardan herhangi birinin bir adresi vardır. Her bit için bir adrese sahip olsaydı, bilgisayar yapabildiğinden 8 kat daha az RAM yönetebilirdi.

Daha fazla bilgi: Wikipedia


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.