C ++:boolが8ビット長なのはなぜですか?


132

C ++では、ブール型が8ビット長(システム上)であり、ブール値を保持するのに1ビットだけで十分なのはなぜでしょうか。

以前はパフォーマンス上の理由であると信じていましたが、32ビットまたは64ビットのマシンで、レジスターが32ビットまたは64ビット幅である場合、パフォーマンスの利点は何ですか?

それとも、これらの「歴史的な」理由の1つにすぎませんか?


9
私のシステムではboolは8ビットではありません。これは、intと同じ4バイトです。
Brian Neal

21
誰かが何をしている思考と思った最後の時間、私たちは)=これまでのstd ::ベクトル<ブール>、最も嫌わSTL「機能」になってしまった
ヴィクトルたSehr

1
jldupont、あなたは私を誤解していると思います。私はシステムを求めていましたsizeof(bool)が、4になります。msvcに32ビットのブール値があることを私は誓うことができましたが、試してみましたがそうではありませんでした。
avakar 2010年

7
公平にvector<bool>言えば、の問題は、巧妙になってブール値をビットにパックしようとすることではなく、これを実行してSTLコンテナとして偽装しようとすることです。プレーンなビットセットは、STLコンテナのふりをしない限り問題ありません。
2010年

2
@avakar-C ++ boolデータ型を、BOOLtypedefされたWindows 型と混同している可能性がありますlong。だからsizeof(bool) != sizeof(BOOL)、私は確かに多くの混乱を引き起こします(そしておそらくかなりの数のバグを引き起こします)。特に、WindowsにはbooleanBOOLEANtypedef があり、のエイリアスですunsigned char。また、bool1バイトであることが一般的ですが、C ++標準には、それsizeof(bool)が大きくなる可能性があることを具体的に示す注記があります。
Michael Burr

回答:


219

すべてのC ++データ型はアドレス可能でなければならないためです。

シングルビットへのポインタをどのように作成しますか?できません。ただし、バイトへのポインタを作成できます。したがって、C ++のブール値は通常バイトサイズです。(これも大きくなる可能性があります。それは実装次第です。主なことは、アドレス指定可能でなければならないため、C ++データ型はバイトより小さくならないことです)


7
「バイト」アドレッシングは、アーキテクチャー上の選択(ハードウェアレベル)です。異なる「アドレッシングの単位」を使用してシステムを設計することもできます。一般的なプロセッサの場合、「バイト」をアドレス指定すると、外部メモリから「バイト」よりも多くフェッチされてしまいます。これは、効率上の理由によるものです。
jldupont 2010年

8
はい、それはハードウェアの選択であり、ハードウェアがそれを許可する場合、ブール値のサイズが変わる可能性があります。しかし、OPはboolが8ビット幅である理由を尋ねました。その場合、CPUは8ビットバイトしかアドレス指定できないためです。
2010年

2
@jldupont:ポインタアドレスがバイトよりも細かいシステムがいくつかあります(以前にビット単位のポインタを使用する古いTI TMS34010 / 20でプログラムしたことがあります)が、非常にまれです。
マイケルコーン

1
よく分からない。すべてのオブジェクトはアドレス可能でなければなりません。つまり、オブジェクトのアドレスを取得できる必要があります。オブジェクトは独自のアドレスを格納する必要はありません。charは通常8ビット幅で、256文字を格納するのに十分ですが、各charには、メモリ内の場所によって定義されるアドレスもあります。そのため、charへのポインタを作成できます。
2010年

88
私が疑わしい類推に寄与するかもしれない場合:私の建物には8つのフロアがありますが、郵便局はそれらが異なる住所であることを認めません。したがって、自分で住所をすべて指定したい場合は、実際には1つのフロアに収まるにもかかわらず、建物全体を借りる必要があります。私は他の7つのフロアを「住所の保存」に使用していません。住所ではフロアではなく建物を参照するという郵便局の規則のため、それらを無駄にしています。C ++オブジェクトには自分自身へのアドレスが必要です-配信後にメールを並べ替えるポストルームはありません;-)
Steve Jessop

39

メモリはバイトアドレス指定可能です。メモリから読み取ったバイトをシフトまたはマスキングしないと、単一ビットをアドレス指定することはできません。これは非常に大きな理由だと思います。


1
常にではない。8051 MCUは、例えば、ビットアドレス可能位置の16バイト有する
海岸に

20

booleanタイプは、通常、アドレス指定可能なメモリの最小単位以下のターゲットマシン(すなわち、通常8ビットバイト)のを。

メモリへのアクセスは常に「チャンク」で行われます(複数の単語、これはハードウェアレベル、バストランザクションでの効率のためです):ほとんどのCPUシステムではブールビットを「単独」でアドレス指定することはできません。もちろん、データがレジスタに格納されると、ビットを個別に操作するための専用の命令がしばしば存在します。

このため、「ブール」ベースのデータ型を使用する効率を上げるために、「ビットパッキング」の手法を使用することは非常に一般的です。enum(Cで)2の累乗のコーディングなどの手法が良い例です。同じようなトリックがほとんどの言語で見られます。

更新:優れた議論のおかげで、C ++での定義sizeof(char)==1により、私の注意が喚起されました。したがって、「ブール」データ型のアドレス指定は、アドレス指定可能なメモリの最小単位にかなり結びついています(私の要点を補強します)。


これについてあなたが残したすべてのコメントについて、あなたが答えの最も重要な部分を省いたことは印象的です:C ++はそれへのポインターを作成することが可能でなければならないためbool、型は割り当て可能なメモリの最小単位に従います。その要件がない場合、現在のバイトアドレス指定可能なマシンでも、aは単一ビットとして表されたと考えられます。bool
2010年

1
うーん...少しアドレス可能なCPUアーキテクチャを作ることができた...そのためのコンパイラーなどを書くことさえできた。「ビットアドレス指定可能」になる特別なメモリ領域(またはその他)を用意できます。想像力を伸ばすことは不可能ではありません。
jldupont 2010年

2
はい、そのシステムでは、ブール値を1ビットにすることができます。しかし、OPは「jlduponts仮想CPUで8ビット幅のboolである理由」を尋ねませんでした。彼は現在の一般的な日常のCPUについて尋ねましたが、それらはバイトアドレス指定が可能なためです。
2010年

4
C ++では定義ごとにsizeof(char)== 1であるため、ハードウェアで実行できることと実行できないことは関係ありません。sizeof(bool)<sizeof(char)にすることはできません。BTW C ++は、ハードウェアがアドレス可能な最小単位をcharするのが不都合な場合に、ハードウェアがアドレス指定できるサブユニットをアドレス指定するための「ファット」ポインターを使用できるように定義されています。これは、少なくとも一部のCコンパイラでは古いワードアドレス指定可能なアーキテクチャで使用されています。
AProgrammer

@AProgrammer::sizeof(char)==1 definitionそれは私の議論に対する最高の反論です。ありがとう!
jldupont

6

8ビットがアドレス可能な最小メモリ量であるという答えは正しいです。ただし、一部の言語で、ブール値に1ビットを使用できます。パスカル実装セットをビット文字列として覚えているようです。つまり、次のセットの場合:

{1, 2, 5, 7}

あなたはこれをメモリに持っているかもしれません:

01100101

もちろん、必要に応じてC / C ++でも同様のことを行うことができます。(大量のブール値を追跡している場合、それ理にかなっているかもしれませんが、それは実際には状況によって異なります。)


8
実際、C ++は特殊なコンテナーvector <bool>を使用してこれを実行します。これは一般的に災害と見なされます。

C ++は、Cから継承された「ビットフィールド」でもこれを行います。構造体/クラスのメンバー変数を宣言するときに、値を格納するために使用されるビット数を宣言できます(たとえば、「unsigned short field:3」)。

@ニール:なぜそれは一般的に災害と見られているのですか?パフォーマンスの問題ですか?
ジェローム

2
@ジェローム:それは、ビットがアドレス指定できないため、通常の方法で動作できないためvectorです。動作に制約があるため、実際にはSTLタイプのコンテナではありません。さらに悪いのは、誰かがを持ち、それらboolを作りたいという問題を引き起こすvectorことです。それは意外な振る舞いであり、それはあなたが言語で望んでいることではありません。
David Thornley、2010年

1
@jldupont-このようなポイントを1回作成するだけで十分です。また、C ++は、ハードウェアの機能に関係なく、ビットがアドレス可能であることを保証するわけではありません(むしろその逆です)。

1

これは古いのはわかっていますが、2セント投入すると思いました。

ブール型またはデータ型を1ビットに制限すると、アプリケーションでメモリが破損する可能性があります。1ビットのみのメモリ内のエラー統計をどのように処理しますか?

私が就職の面接に行ったところ、プログラムがリードした発言の1つに、「ミサイルを発射する信号を送信するときは、ワイヤレスで単純な1ビットをオフビットで送信するだけです。その信号をできるだけ速くする必要があります。」

まあ、それは私が概念とビット、バイト、およびエラー処理を理解しているかどうかを確認するためのテストでした。悪意のある人が1ビットのメッセージを送信するのはどれほど簡単でしょう。または、送信中にビットが逆方向に反転するとどうなりますか。


掲載し新しい質問を、他の質問への答えとして、あなたの質問を投稿しないでください。
イゴールJerosimić13年

6
この「回答」に含まれている質問は、実際には修辞的なものだと思います。つまり、ブール値を1ビットとして実装しないのは、1ビットでエラー統計を処理できないためです。
Stephen Holt

1
@StephenHoltですが、それが理由ではなく、TBHこの答えは意味がありません。
文書

1
...何?CRCのようなものか、トラップ表現か、「エラー統計」の意味がわかりません。しかし、いずれの場合でも、極端な環境のコードを除くすべてのプログラマは、コードがメモリを読み取る前にハードウェアがエラーの検出/修正を処理できることを正しく想定しているため、大きなタイプでさえ「エラー統計」に余分な「スペア」ビットを使用しません。なんらかの方法ですべての変数に検証情報などを埋め込む時間を費やす必要はありません。boolOPのマシンでは8ビットを使用し、私のマシンでは32ビットを使用するのはそのためではありません。他の7ビットまたは31ビットは「エラー統計」には使用されないためです。これは意味がありません
underscore_d

1

一部の組み込みコンパイラには、ブールフラグをビットパックするために使用されるint1タイプがあります(たとえば、Microchip MPU用のCコンパイラのCCSシリーズ)。これらの変数の設定、クリア、およびテストでは、単一命令のビットレベルの命令を使用しますが、他の回答に記載されている理由により、コンパイラーは他の操作(変数のアドレスの取得など)を許可しません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.