0

重複の可能性:
構造体の sizeof が各メンバーの sizeof の合計と等しくないのはなぜですか?

なぜこのようになっているのか理解できません:

#include <stdio.h>
#include <stdlib.h>

typedef struct
{
    char b;
    int a;
} A;

typedef struct
{
    char b;
} B;

int main() {
    A object;
    printf("sizeof char is: %d\n",sizeof(char));
    printf("sizeof int is: %d\n",sizeof(int));
    printf("==> the sizeof both are: %d\n",sizeof(int)+sizeof(char));
    printf("and yet the sizeof struct A is: %d\n",sizeof(object));
    printf("why?\n");

    B secondObject;
    printf("pay attention that the sizeof struct B is: %d which is equal to the "
            "sizeof char\n",sizeof(secondObject));

    return 0;
}

コードで質問を説明したと思いますが、これ以上説明する必要はありません。さらに、別の質問があります: ヒープ/静的ヒープ/スタックに割り当てがあることは知っていますが、割り当て場所が不明であることはどういう意味ですか?

私はこの例について話している:

    typedef struct
{
    char *_name;
    int   _id;
} Entry;

int main()
{
    Entry ** vec = (Entry**) malloc(sizeof(Entry*)*2);
    vec[0] = (Entry *) malloc(sizeof (Entry));
    vec[0]->_name = (char*)malloc(6);
    strcpy (vec[0]->_name, "name");
    vec[0]->_id = 0;
    return 0;
}

私はそれを知っています:vecはスタックにあります。*vec はヒープ上にあります。*vec[0] はヒープ上にあります。vec[0]->id はヒープ上にあります。

しかし : vec[0]->_name が不明なのはなぜですか?

4

4 に答える 4

1

構造体のメンバー間および構造体の末尾には、指定されていない量のパディングがあります。C では、構造体オブジェクトのサイズは、そのメンバーのサイズの合計以上です。

于 2013-02-02T13:26:10.100 に答える
0

CPU とメモリの配置を検索する場合は、この質問とこの質問、および他の多くの質問を参照してください。つまり、読み取るデータのサイズに合わせてメモリにアクセスすると、CPU はより快適になります。たとえば、uint16_tを読み取る場合、2 の倍数であるアドレスで読み取ると (ほとんどの CPU で) より効率的になります。CPU がそのように設計されている理由の詳細は、まったく別の話です。

これが、コンパイラが救助に来て、余分なストレージスペースを犠牲にして、CPU がそれらにアクセスするのに最も快適な方法で構造体のフィールドをパディングする理由です。あなたの場合、おそらく4バイトであると仮定して、charとの間に3バイトのパディングが与えられます。intint

C 標準 (現在手元にはありません) またはmalloc の man ページを見ると、次のようなフレーズが表示されます。

malloc() および calloc() 関数は、任意の種類の変数に対して適切にアラインされた、割り当てられたメモリへのポインタを返します。

この動作は、上で述べたのとまったく同じ理由によるものです。要するに、メモリの配置は気にするべきことであり、それは構造体のレイアウトやローカル変数のレイアウトなどの他の場所でコンパイラが行うことです.

于 2013-02-02T13:32:09.630 に答える
0

コンパイラは、構造体にパディングを自由に追加して、データ型が適切に整列されるようにします。たとえば、 anはバイトintにアラインされます。sizeof(int)したがって、構造体のサイズの出力A8. コンパイラがこれを行うのintは、アラインされていないアドレスから をフェッチするのはせいぜい非効率的であり、最悪の場合はまったく機能しないためです。これは、コンピューターが使用するプロセッサによって異なります。x86 は、ほとんどのデータ型についてアラインされていないアドレスから問題なくフェッチしますが、フェッチ操作に約 2 倍の時間がかかります。

2 番目のコード スニペットでは、宣言していませんi

したがってvec[0]->_name、未知ではありません-「malloc」(およびmallocの兄弟)から得られる他のものと同じように、ヒープ上にあります。

于 2013-02-02T13:29:20.447 に答える
0

ここで構造パディングに遭遇しています。コンパイラは、フィールドが 4 バイトでアラインされるように、bフィールドの後に 3 バイト分のパディングを挿入する可能性があります。コンパイラ固有のビットを使用して、このパディングをある程度制御できます。たとえば、MSVC ではpack プラグマ、またはGCC では属性ですが、これはお勧めしません。構造体のパディングは、メンバーのアラインメント制限を指定するためにあります。一部のアーキテクチャでは、アラインされていないアクセスでエラーが発生します。(他の人はアライメントを手動で修正するかもしれませんが、通常はかなりゆっくりと行います。)struct Aaaligned

参照: http://en.wikipedia.org/wiki/Data_structure_alignment#Data_structure_padding


2 番目の質問については、「不明」という名前が何を意味するのかわかりません。詳しく説明しますか?

于 2013-02-02T13:33:05.883 に答える