23

私は、いわゆる Hotspot オープン ソース プロジェクトに取り組んでおり、実装を調べたところ、構造体に次のような厄介なネストされた共用体が見つかりました。

typedef struct RC_model_t_st
{
    union
    {
        struct block_model_t_st *block;
        struct grid_model_t_st *grid;
    };
    /* block model or grid model    */
    int type;
    thermal_config_t *config;
}RC_model_t;

私が C/C++ で知っている限りでは、union にはアクセスできません。では、そのような方法で宣言された共用体をどのように使用し、どのような目的で使用できるのでしょうか?

ありがとう!

4

6 に答える 6

36

これは匿名組合です。C++ では、[class.union] の段落 5 に従って:

名前検索の目的で、匿名共用体の定義の後、匿名共用体のメンバーは、匿名共用体が宣言されているスコープで定義されていると見なされます。

これは、 のメンバーであるかのようにそのメンバーにアクセスできることを意味しますRC_model_t_st

于 2012-11-29T11:36:32.257 に答える
10

確信が持てず、試していない場合:

ユニオン自体にはアクセスできませんが、そのメンバーにはアクセスできます。

obj.blockしたがって、参照と実行ができるはずですobj.grid

于 2012-11-29T11:30:58.307 に答える
9

無名共用体と構造体に関する標準を引用して Angew によって提供された回答を詳しく説明するために、C ソース コードのサンプルを提供し、そのサンプルによって生成された出力を提供して、およびコンポーネントstructunion構成される内で値がどのように割り当てられるかを示すことを考えました。structunion

Angew が引用している標準は次のとおりです。

名前検索の目的で、匿名共用体の定義の後、匿名共用体のメンバーは、匿名共用体が宣言されているスコープで定義されていると見なされます。

struct名前付きおよび無名の構造体と共用体で構成されるのソース コードは、次のようになります。これは Visual Studio 2005 を使用しており、メモリ ホールがないように#pragma (pack, 1)すべてを境界に揃えるために使用されます。char出力をより読みやすく、コーディングしやすくするために定義された単純な C プリプロセッサ マクロもあります。

typedef unsigned char UCHAR;

// use of Microsoft Visual Studio pragma to force char alignment for the struct.
#pragma pack(push, 1)
const struct {
    union {
        const UCHAR myArray[];  // this array shares memory with struct following
        struct {
            const UCHAR iOne;
            const UCHAR iTwo;
            const UCHAR iThree;
        };  // anonymous struct accessed by specifying Things.
    };      // anonymous union accessed by specifying Things.
//  const UCHAR myArray[];   // will cause error - "error C2020: 'myArray' : 'struct' member redefinition"
    union {
        const UCHAR myArray[];  // this array shares memory with struct following
        struct {
            const UCHAR iOne;
            const UCHAR iTwo;
            const UCHAR iThree;
        } s;    // named struct accessed by specifying Things.u.s
    } u;        // named union accessed by specifying Things.u
} Things = {1, 2, 4, 8, 9, 10, 22, 23, 24, 25};
#pragma pack(pop)

// a little helper macro to make the output easier to code.
#define PRINTF_VAL(x) printf ("%s %d \n", #x, x)

int itSelf (UCHAR iMask)
{
    int iMatch = -1;

    int jj = 0;
    jj = Things.myArray[0]; PRINTF_VAL(Things.myArray[0]);
    jj = Things.myArray[1]; PRINTF_VAL(Things.myArray[1]);
    jj = Things.myArray[2]; PRINTF_VAL(Things.myArray[2]);
    jj = Things.myArray[3]; PRINTF_VAL(Things.myArray[3]);
    jj = Things.myArray[4]; PRINTF_VAL(Things.myArray[4]);
    jj = Things.iOne; PRINTF_VAL(Things.iOne);
    jj = Things.iTwo; PRINTF_VAL(Things.iTwo);
    jj = Things.iThree; PRINTF_VAL(Things.iThree);

    jj = Things.u.myArray[0]; PRINTF_VAL(Things.u.myArray[0]);
    jj = Things.u.myArray[1]; PRINTF_VAL(Things.u.myArray[1]);
    jj = Things.u.myArray[2]; PRINTF_VAL(Things.u.myArray[2]);
    jj = Things.u.myArray[3]; PRINTF_VAL(Things.u.myArray[3]);
    jj = Things.u.myArray[4]; PRINTF_VAL(Things.u.myArray[4]);
    jj = Things.u.s.iOne; PRINTF_VAL(Things.u.s.iOne);
    jj = Things.u.s.iTwo; PRINTF_VAL(Things.u.s.iTwo);
    jj = Things.u.s.iThree; PRINTF_VAL(Things.u.s.iThree);

    return iMatch + 1;
}

この関数によって生成される出力は次のようになります。

Things.myArray[0] 1
Things.myArray[1] 2
Things.myArray[2] 4
Things.myArray[3] 8
Things.myArray[4] 9
Things.iOne 1
Things.iTwo 2
Things.iThree 4
Things.u.myArray[0] 8
Things.u.myArray[1] 9
Things.u.myArray[2] 10
Things.u.myArray[3] 22
Things.u.myArray[4] 23
Things.u.s.iOne 8
Things.u.s.iTwo 9
Things.u.s.iThree 10

出力は、共用体の使用によって引き起こされたmain のさまざまなコンポーネント間のオーバーラップを示していますstruct。また、匿名とThingsのコンポーネントがどのように参照され、名前付きとのコンポーネントがどのように参照されるかを確認することもできます。structunionstructunion

const UCHAR myArray[];また、楽しみのために、匿名のunion包含の後に配列定義を追加して、const UCHAR myArray[];何が起こるかを確認してみました。コンパイラはerror C2020: 'myArray' : 'struct' member redefinition. struct上記の定義では、追加はコメントアウトされていますThings。ただし、 の 2 番目の使用はconst UCHAR myArray[];名前付きでunionあるため、2 番目の使用は共用体の名前を指定することによってアクセスされるため、コンパイルは機能します。

于 2016-02-14T05:09:05.177 に答える
3

匿名共用体で宣言された名前は、非メンバー変数のように直接使用されます。これを行う正当な理由は、メモリを節約するためです。

#include <iostream>

int main(int argc, char **argv) {
   union {
      double first;
      double second;
   };

   first = 10.001;
   second = 3.141592;
   std::cout << first << " " << second << std::endl;

   first = 10.002;
   std::cout << first << " " << second << std::endl;
}
于 2012-11-29T11:47:39.873 に答える
-2

まず最初に言いたいのは、ユニオンは、構造体と同じように、さまざまなタイプの変数のコレクションです。ただし、ユニオンを使用すると、一度に 1 つのフィールドにしか情報を格納できません。

ユニオンは基本的にメモリ節約のために使用され、そのサイズはユニオンの最大メンバーと同じです。

また、共用体のデータ フィールドにアクセスするには、構造体の場合と同じようにドット演算子 (.) を使用し、@Atmocreations で説明します。値が 1 つのメンバーに割り当てられると、他のメンバーは同じメモリを共有するため、削除されます。

ユニオンが役立つ例としては

union time    
        {
        long time_in_sec;
        double time_in_mili_sec;
        }mytime;

.... 上記の共用体を使用して、現在の時刻 (秒単位) を格納し、秒単位の正確な時刻を保持できます。または、ミリ秒単位の正確な時間を保持するために使用できます。おそらく、両方ではなく、どちらか一方が必要な場合があります。この宣言は見覚えがあるはずです。これは構造体定義と同じですが、構造体の代わりにキーワード union を使用します。

詳細についてはhttp://msdn.microsoft.com/en-us/library/5dxy4b7b(v=vs.80).aspx

于 2012-11-29T11:50:03.797 に答える