3
enum Enums { k1, k2, k3, k4 };

union MYUnion { 
    struct U{ 
         char P;
    }u;

    struct U0 { 
        char state; 
    } u0; 

    struct U1 { 
        Enums e; 
        char c; 
        int v1; 
    } u1; 

    struct U2 { 
        Enums e; 
        char c; 
        int v1; 
        int v2; 
    } u2; 

    struct U3 { 
        Enums e; 
        unsigned int i; 
        char c; 
    } u3; 

    struct U4 { 
        Enums e;
        unsigned int i; 
        char c; 
        int v1; 
    } u4; 

    struct U5 { 
        Enums e; 
        unsigned int i; 
        char c; 
        int v1; 
        int v2; 
    } u5; 
} myUnion

私は、C++ での Union のこの全体的な考えにとても混乱しています。この「myUnion」はメモリ内でどのように見えますか?? データが同じメモリ ブロックを共有していることはわかっていますが、どうすればよいでしょうか? 「myUnion」のサイズは?「u5」のサイズである場合、このメモリブロックにデータはどのように割り当てられますか??

4

5 に答える 5

1
  1. ユニオンのサイズは、ユニオン内の最大のもののサイズです。
  2. ユニオンのレイアウトは、最後に保存したものです。

したがって、最後のユニオンで、に.i格納してから int の最初のバイトに格納.eすると、enum 値で上書きされます (環境では 1 であると仮定しsizeof (enum)ます)。

ユニオンは次のようなものです。

void * p = malloc(sizeof(biggest_item))
Enums *ep = (Enums *)e;
unsigned int * ip = (unsigned int *)p;
char *cp = (char *)p;

*ep*ip、およびへの代入は*cp、共用体と同じように機能します。

于 2009-11-22T02:27:07.390 に答える
1

Murali が言ったように、ユニオンのサイズは、ユニオンに参加する最大の構造体のサイズになります。

アプリは、最大のブロックに十分なバイトを割り当てます。メモリ マッピングは次のように機能します。

次の点を考慮してください。

union Foo
{
  struct A
  {
    int x;
    unsigned char y;
    unsigned char z;

  }
  struct B
  {
    unsigned char a;
    unsigned char b;
    unsigned char c;
    unsigned char d;
    unsigned char e;
  }
}

この場合、int が 32 ビット (ターゲット プラットフォームによって異なります) であると仮定すると、a、b、c、および d は、整数 X を構成するバイトへのアクセスを提供します。A に書き込むと、x、b の最初のバイトが上書きされます。 x の 2 番目のバイトが上書きされます。

逆に、X に値を書き込むと、a、b、c、および d に影響します。

unsigned chars y と e は同じスペースを占有するため (これも int が 32 ビットであることに依存します)、.y と .e は実質的に互いのエイリアスです。

unsigned char Az は構造体 B のどの要素とも重複しないため、事実上、構造体 B への変更の影響を受けません。

ここでのポイントは、結合された構造体の要素が同じメモリを占有することです。異なる構造体は、異なるデータ型を使用できるようにすることで、同じメモリを読み書きするさまざまな方法を提供します。

于 2009-11-22T02:27:36.373 に答える
1

あなたは混乱するのが正しいです!私は混乱しています...あなたが持っているより複雑な例に移る前に、最初に簡単なものを見てみましょう。

まずはユニオンの基本。ユニオンとは、ユニオン型の変数を作成するときに、基礎となるコンポーネント (以下の i と f の例) がメモリ内で実際に重複していることを意味します。そのメモリを int として扱うこともあれば、float として扱うこともあります。これは当然厄介なことであり、自分が何をしているのかを本当に知る必要があります。

union AUnion
{
   int i;
   float f;
}; // assumes an int is 32 bits

AUnion aUnion;
aUnion.i = 0;
printf("%f", aUnion.f);

上記のコードでは、何が出力されますか? その質問に対する答えを理解するには、int と float がメモリ内でどのように表現されるかを理解する必要があります。どちらも 32 ビットのメモリを占有します。ただし、そのメモリがどのように解釈されるかは、2 つのタイプの間で異なります。aUnion.i = 0 を設定すると、「0 の整数を aUnion に書き込む」と言っています。たまたま 0 の整数は、すべての 32 ビットを 0 に設定することに対応します。ここで、aUnion.f を出力するとき、「ビットが実際に 32 ビット浮動小数点数であるかのように aUnion を扱い、出力します。コンピューターは、これらの基礎となるすべてのビットを、実際には int ではなく浮動小数点数の一部であるかのように扱います。バイナリでフォーマットされています。

次に、より複雑なユニオン コードのいくつかを取り上げます。

enum Enums { k1, k2, k3, k4 };

union MYUnion { 
struct U{ 
     char P;
}u;

struct U0 { 
    char state; 
} u0; 

struct U1 { 
    Enums e; 
    char c; 
    int v1; 
} u1; 

これらの構造体はすべて、上にある int と float と同じ方法でオーバーラップされます。ここで、列挙型が int にマップされていると仮定します。次に、列挙型の規則に基づいて、列挙型を基になるメモリの int 値にマップできます。

 enum Enums { k1/*0*/, k2/*1*/, k3/*2*/, k4/*3*/ };

それで、私たちが持っているのは

union MYUnion { 
struct U{ 
     char P;
}u;

struct U0 { 
    char state; 
} u0; 

struct U1 { 
    int e; 
    char c; 
    int v1; 
} u1; 

そして、あなたは非常に奇妙な組合を持っています。

MyUnion m;
m.u.P = 'h'

後で列挙型 (フードの下の int である可能性が最も高い) にアクセスすると、無効な値として読み取られます。これは、P が 1 バイトであり、int が 4 バイトであるためです。列挙型として読み取ると、奇妙な結果が得られます。

このコードの責任者を解任することを強くお勧めします。

于 2009-11-22T02:35:46.153 に答える
0

おそらく、ユニオンが優れた機能ではないためです。これらは、非常に制約のあるメモリ共有に役立つ場合があります。または、移植できないメモリのトリック (あるサイズの変数に書き込み、別のサイズから読み取る)。または、素敵なタグ付きユニオンをエミュレートするため。

タグ付きユニオン パターンは次のように機能します。

enum mytags { FULL_TIME_WORKER, PART_TIMER, CONTRACTOR}

struct worker_t {
    enum mytags tag,
    union {
        struct full_time_worker_t full_time_wroker,
         struct part_time_worker_t part_time_worker,
         struct contractor_t contractor }
    }
}


bool person_can_do_x(worker_t w)
{
    switch(workers.tag)
    {
    case FULL_TIME_WORKER:
    ...
    case PART_TIMER:
    ...
    case CONTRACTOR:
       ...w.contractor.....
    default:
        return true
    }
}
于 2011-06-05T13:26:08.747 に答える
0

そして、メモリのブロックがどのように見えるかを知るには、ターゲットCPUのメモリモデル(ビッグリトル)エンディアンなどに依存しますが、一般に、各構造体は同じアドレスとレイアウトを同じ領域で開始します-それが何をしようとしているのかを知っている場合は便利ですが、そうでない場合は足を撃ちます。

于 2009-11-22T02:27:59.960 に答える