31

Cでは、構造体の中に含まれている配列の中に、配列の要素の間にパディングが追加されている可能性があるという噂を聞きました。明らかに、パディングの量は要素のペア間で変化することはできません。または、配列内の次の要素を計算することは、単純なポインター演算では不可能です。

この噂では、構造体に含まれていない配列にはパディングが含まれていないことが保証されているとも述べられています。私は少なくともその部分が真実であることを知っています。

したがって、コードでは、噂は次のとおりです。

{
    // Given this:
    struct { int values[20]; } foo;
    int values[20];

    // This may be true:
    sizeof(values) != sizeof(foo.values);
}

私はそれsizeof(values)が常に等しくなるとかなり確信していsizeof(foo.values)ます。ただし、これを明示的に確認または拒否するC標準(具体的にはC99)には何も見つかりませんでした。

この噂がC規格で扱われているかどうか誰かが知っていますか?

編集:配列foo.valuesの終わりと構造体の終わりの間にパディングがある可能性がfooあり、標準では、の開始fooと開始の間にパディングがないと規定されていることを理解していますfoo.values。しかし、誰かが標準からの引用または参照を持っていますか?それはの要素の間にパディングがないと言っていますfoo.valuesか?

4

5 に答える 5

38

いいえ、配列の要素の間にパディングはありません。それは特に許可されていません。C99標準では、配列型を「配列型は、連続して割り当てられた空でないオブジェクトのセットを記述します...」と呼びます。対照的に、構造は「連続して」割り当てられるのではなく、「順次」割り当てられます。

構造内の配列の前後にパディングがある場合があります。それは完全に別の動物です。コンパイラは構造の整列を支援するためにそれを行うかもしれませんが、C標準はそれについて何も述べていません。

于 2009-07-01T00:03:55.457 に答える
11

ここで注意してください。構造体の最後にパディングを追加できますが、質問で述べているように、配列の要素間には追加されません。配列は常に連続したメモリを参照しますが、構造体の配列には、構造体自体の一部として各要素にパディングが追加されている場合があります。

あなたの例では、valuesfoo.values配列は同じサイズになります。代わりに、パディングは構造体の一部になりますfoo

于 2009-07-01T00:05:07.107 に答える
3

構造体がそのメンバー間または最後のメンバーの後にパディングを必要とする理由と、配列がパディングを必要としない理由についての説明は次のとおりです

タイプが異なれば、アライメント要件も異なる場合があります。一部のタイプは単語の境界に揃える必要があり、他のタイプは2つまたは4つの単語の境界に揃える必要があります。これを実現するために、構造体のメンバー間にパディングバイトが含まれる場合があります。構造体の直接のメモリ位置も構造体の配置要件に準拠する必要があるため、末尾のパディングバイトが必要になる場合barがありstruct foo *ます。

(struct foo *)((char *)bar + sizeof(struct foo))

への有効なポインタを生成しますstruct foo(つまり、位置ずれが原因で失敗することはありません)。

配列の各「メンバー」には同じ配置要件があるため、パディングを導入する理由はありません。これは、構造体に含まれる配列にも当てはまります。配列の最初の要素が正しく整列されている場合、後続のすべての要素も正しく整列されます。

于 2009-07-01T00:42:13.693 に答える
0

はい、そうですね。変数によっては、変数は多くの場合、いくつかの境界に揃えられます。たとえば、次のようにします。

typedef struct
{
    double d;
    char c;
} a_type_t;

私のシステムでは、doubleとcharはそれぞれ8バイトと1バイトです。合計9。ただし、その構造は16バイトになるため、doubleは常に8バイトに整列されます。ints、charsなどを使用したばかりの場合、配置は1、2、4、または8になる可能性があります。

一部のタイプTのsizeof(T) 場合、等しい場合と等しくない場合があり sizeof(T.a) + sizeof(T.b) + sizeof(T.c) ...ます。

一般的に、これは完全にコンパイラとアーキテクチャに依存します。実際には、それは決して重要ではありません。

于 2009-07-01T00:03:40.510 に答える
-1

検討:

struct {
  short s;
  int i;
} s;

ショートが16ビットで、32ビットを使用しているとすると、各構造体メンバーはワード(この場合は32ビット)の境界に配置される傾向があるため、サイズはおそらく8バイトになります。コンパイラフラグなどによって変更できるのは実装固有の動作であるため、「おそらく」と言います。

これは、必ずしもC標準で定義されているわけではない実装動作であることを強調する価値があります。ショートパンツ、int、ロングのサイズと同じように(C標準では、ショートはintより大きくならず、longはintより小さくならない、つまり16/32 / 32、16 /32/64になる可能性があると単純に述べています。 、32/32/64または他の多くの構成)。

于 2009-06-30T23:57:04.893 に答える