2

私はビットフィールドを含む構造を持っています。私によると2バイトであることがわかりますが、4であることがわかります。スタックオーバーフローでこれに関連するいくつかの質問を読みましたが、私の問題に関連することはできません。これは私が持っている構造です

struct s{
char b;
int c:8;
};
int main()
{
printf("sizeof struct s = %d bytes \n",sizeof(struct s));
return 0;
}

int型がメモリ境界にある必要がある場合、出力は8バイトである必要がありますが、4バイトを示していますか?

4

5 に答える 5

1

int c:8;bit-fieldは、サイズが 8 ビットのa を宣言していることを意味します。32 ビット システムのアラインメントは通常 4 バイト (=32 ビット) であるため、オブジェクトは 2 バイト (文字 + 8 ビット) ではなく 4 バイトのように見えます。

于 2011-08-19T12:18:51.130 に答える
1

ここに画像の説明を入力

ソース: http://geeksforgeeks.org/?p=9705

要約すると、アライメントを犠牲にすることなく、ビットのパッキング(ビットフィールドの目的)を可能な限り最適化しています。

変数のデータ配置は、これらのバンクにデータが格納される方法を扱います。たとえば、32 ビット マシンでの int の自然なアラインメントは 4 バイトです。データ型が自然にアラインされている場合、CPU は最小の読み取りサイクルでそれをフェッチします。

同様に、 の自然なアラインメントshort intは 2 バイトです。つまり、short int はバンク 0 – バンク 1 のペアまたはバンク 2 – バンク 3 のペアに格納できます。Adoubleは 8 バイトを必要とし、メモリ バンクで 2 行を占有します。double のアライメントがずれていると、double データをフェッチするために 2 つ以上の読み取りサイクルが強制されます。

double 変数は 32 ビット マシンの 8 バイト境界に割り当てられ、2 つのメモリ読み取りサイクルが必要であることに注意してください。64 ビット マシンでは、バンク数に基づいて、double 変数が 8 バイト境界に割り当てられ、1 回のメモリ読み取りサイクルしか必要としません。

そのため、コンパイラはすべての構造体にアラインメント要件を導入します。構造体の最大のメンバーのようになります。から削除charしてstructも、まだ4 バイトになります。

ではstructchar1 バイト アラインされます。その後にビット フィールドが続きintます。これは整数用に 4 バイト アラインされていますが、ビット フィールドを定義しました。

8 ビット = 1 バイト。Char任意のバイト境界にすることができます。したがって、Char+ Int:8= 2 バイトです。これは奇妙なバイト境界であるため、コンパイラは 4 バイト境界を維持するためにさらに 2 バイトを追加します。

int8 バイトにするには、実際の(4 バイト) と(1 バイト)を宣言する必要がありますchar。それは5バイトです。これも奇妙なバイト境界なので、は8 バイトstructにパディングされます。

パディングを制御するために過去によく行ったことは、struct常に 4 バイトの境界を維持するために、間にフィラーを配置することでした。だから私はstructこのようなものを持っている場合:

struct s {
    int id;
    char b;
};

次のように割り当てを挿入します。

struct d {
    int id;
    char b;
    char temp[3];
}

これstructにより、4 バイト + 1 バイト + 3 バイト = 8 バイトのサイズが得られます。このようにstructして、特にネットワーク経由でどこかに送信する場合に、希望どおりにパディングすることができます。また、実装を変更した場合 (これstructバイナリファイルに保存する場合など、フィラーは最初から存在していたので、初期構造を維持している限り、すべて問題ありません!)

最後に、ビットフィールドを使用した C 構造体のサイズに関するこの記事を読んで、詳細を確認してください。

于 2011-08-19T16:49:07.623 に答える
0

でも、c8ビットを占有するように指定すると、実際にはintではありませんよね?c+のサイズbは 2 バイトですが、コンパイラは構造体を 4 バイトにパディングします。

于 2011-08-19T12:17:49.617 に答える
0

プラットフォームに依存しない一般的な C では、構造体/共用体のサイズもビットフィールドのサイズも知ることができません。コンパイラは、最初のメモリ位置を除いて、構造体/共用体/ビットフィールド内のどこにでも好きなだけパディング バイトを自由に追加できます。

さらに、どのビットが msb で lsb が C によって定義されていないため、コンパイラは任意の数のパディングビットをビット フィールドに自由に追加でき、好きな場所に置くことができます。

ビットフィールドに関して言えば、C 言語によって冷たく取り残されています。それらには標準がありません。特定のプラットフォームでどのように動作するかを知るには、コンパイラのドキュメントを詳細に読む必要があり、完全に移植性がありません。

賢明な解決策は、ビット フィールドを決して使用しないことです。ビット フィールドは C の冗長な機能です。代わりに、ビット単位の演算子を使用します。ビット単位の演算子と詳細に文書化されたビット フィールドは、同じマシン コードを生成します (文書化されていないビット フィールドは、非常に任意のコードになる可能性があります)。しかし、ビット単位の演算子は、世界中のどのコンパイラ/システムでも同じように機能することが保証されています。

于 2011-08-19T14:17:21.453 に答える
0

構造体のフィールドの配置は、コンパイラ/プラットフォームに依存します。コンパイラは、長さが 16 ビット以下のビットフィールドに 16 ビット整数を使用している可能性があります。おそらく、4 バイト境界よりも小さいものに構造体を配置することはありません。

結論: 構造体フィールドがどのように配置されているかを知りたい場合は、使用しているコンパイラとプラットフォームのドキュメントを読む必要があります。

于 2011-08-19T12:22:47.153 に答える