サイズが 4 ビットのデータ型がないのはなぜですか?
誰が言った?Intel 4004 CPUには、4 ビットのレジスタと 4 ビットのメモリ オペランドがありました。4 ビットのデータ型は直接サポートされているため、この CPU では当然のことです。
Intel 8051 CPUは、メモリの単一ビットを直接操作できるため、1 ビット変数を持つことができます。
これらは、データ型が非常に小さく、現在どこにでもある 8 ビット バイトよりも小さい CPU の 2 つの例にすぎません。
そんなに気が向いたら、なぜ作れないのですか?
私たちはできる。4 ビット データ型を直接サポートする CPU を作成するか、4 ビット変数をより大きな変数の一部としてシミュレートすることができます。
2 つの 4 ビット変数を 8 ビット バイトにパックできます。このアプローチの問題点は、8 ビット レジスタまたはメモリ位置から 4 ビットを抽出するために、より多くの命令を使用する必要があることです (これには、シフトとマスク ( AND
) 命令が必要です)。同様に、適切に 4-ビット値を 8 ビット バイトの半分に変換します (8 ビットをロードし、4 ビット半分の古い値をクリアし ( mask/ を使用AND
)、新しい値をシフトし、残りの値と結合してセーブ バックします)。明らかに、これはプログラムのコード サイズとその速度に悪影響を及ぼします。さらに、4 ビット変数は保持できる情報が非常に少ないため、あまり役に立ちません。これらの理由から、より小さな型のシミュレーションはあまり一般的ではありません。
ビットフィールドを見たことがありますが、それらは移植性がなく、おそらく使用されていないと聞きましたか?
それらは使用されます。それらが存在するのは、一部の (ただしすべてではない) アプリケーションで非常に役立つからです。短い変数が多数ある場合は、それらのいくつかを 1 バイトまたはマシン ワードにパックして、メモリの無駄を減らすことが有利な場合があります。
完全に移植できないわけではありません。言語標準では、より大きなデータ型のビットフィールドの位置とレイアウトが正確に定義されていないため、C および C++ での移植性は制限されています。これは、コンパイラの作成者がビット フィールドを操作するときに CPU 機能を最も効果的に利用できるようにするために意図的に行われます。
6.7.2.1 Structure and union specifiers
clause 10
1999年からのC標準の次のように述べています:
実装では、ビットフィールドを保持するのに十分な大きさのアドレス指定可能なストレージ ユニットを割り当てることができます。十分なスペースが残っている場合、構造内の別のビットフィールドの直後に続くビットフィールドは、同じユニットの隣接するビットにパックされます。十分なスペースが残っていない場合、収まらないビットフィールドを次のユニットに配置するか、隣接するユニットとオーバーラップするかは実装定義です。ユニット内のビットフィールドの割り当て順序 (上位から下位、または下位から上位) は実装定義です。アドレス可能なストレージ ユニットのアラインメントは指定されていません。
これは、マシンがビットの位置のプレース値を解釈する方法の結果だと思います。(ビッグエンディアン、リトルエンディアン)
はい、それが理由の一部です。しかし、それは決してビットフィールドだけに固有のものではありません。通常の非ビットフィールド型にもこの問題があります。
また、プリミティブ型よりも大きいこのようなビット フィールドを作成することもできません。では、なぜ制限するのでしょうか。アセンブルで出来ますか?
C (または C++) コンパイラ (またはインタプリタ) が、CPU が直接サポートする型よりも大きな型をシミュレートできる場合は、256 ビットのビット フィールドを使用することもできます。
ただし、直接サポートされている CPU の最大の型が 32 ビットである場合、128 ビットのようなより大きな型 (ビットフィールドであるかどうかにかかわらず) を使用すると、より多くのコードと特定のパフォーマンスの低下が発生することになります。 CPU 命令 (またはそれらのほんの一部) は、そのような大きなデータ値を操作できません。これらの余分な命令を実行するには、より多くの命令とより多くの時間が必要になります。
はい、これはアセンブリで実行できます。コードを記述して機能させる意思がある限り、アセンブリでは何でも実行できます。:)