web-dev-qa-db-ja.com

C:組合は実際にどこで使用されていますか?

型の整列が保証されているunion max_alignの例があります。私の友人を説明するために、共用体が実際に使用されているさらに簡単な例を探しています。

30
yesraaj

私は通常、テキストを解析するときに共用体を使用します。私はこのようなものを使用します:

typedef enum DataType { INTEGER, FLOAT_POINT, STRING } DataType ;

typedef union DataValue
{
    int v_int;
    float v_float;
    char* v_string;
}DataValue;

typedef struct DataNode
{
    DataType type;
    DataValue value;
}DataNode;

void myfunct()
{
    long long temp;
    DataNode inputData;

    inputData.type= read_some_input(&temp);

    switch(inputData.type)
    {
        case INTEGER: inputData.value.v_int = (int)temp; break;
        case FLOAT_POINT: inputData.value.v_float = (float)temp; break;
        case STRING: inputData.value.v_string = (char*)temp; break;
    }
}

void printDataNode(DataNode* ptr)
{
   printf("I am a ");
   switch(ptr->type){
       case INTEGER: printf("Integer with value %d", ptr->value.v_int); break;
       case FLOAT_POINT: printf("Float with value %f", ptr->value.v_float); break;
       case STRING: printf("String with value %s", ptr->value.v_string); break;
   }
}

共用体がどのように頻繁に使用されているかを確認したい場合は、 flex / bison を使用してコードを確認してください。たとえば splint を参照してください。これにはたくさんの共用体が含まれています。

33
Yousf

私は通常、ユニオンを使用して、データのさまざまなビューを表示したいと考えています。 32ビットvalと赤、緑、青、アルファコンポーネントの両方が必要な32ビットカラー値

struct rgba
{
  unsigned char r;
  unsigned char g;
  unsigned char b;
  unsigned char a;
};

union  
{
  unsigned int val;
  rgba components;
}colorval32;

注意:ビットマスキングとシフトで同じことを実現することもできます。

#define GETR(val) ((val&0xFF000000) >> 24)

しかし、私は組合のアプローチがよりエレガントだと思います

6
zebrabox

特定のポートをメモリにマッピングすることにより、レジスタまたはI/Oポートにバイト単位およびビット単位でアクセスするには、以下の例を参照してください。

    typedef Union
{
  unsigned int a;
struct {
  unsigned bit0 : 1,
           bit1 : 1,
           bit2 : 1,
           bit3 : 1,
           bit4 : 1,
           bit5 : 1,
           bit6 : 1,
           bit7 : 1,
           bit8 : 1,
           bit9 : 1,
           bit10 : 1,
           bit11 : 1,
           bit12 : 1,
           bit13 : 1,
           bit14 : 1,
           bit15 : 1
} bits;
} IOREG;

# define PORTA (*(IOREG *) 0x3B)
...
unsigned int i = PORTA.a;//read bytewise
int j = PORTA.bits.bit0;//read bitwise
...
PORTA.bits.bit0 = 1;//write operation
5
wrapperm

Windowsの世界では、unionsは、 タグ付きバリアント を実装するために一般的に使用されます。 COMオブジェクト間でデータを受け渡す方法

union型は、2つのオブジェクト間で任意のデータを渡すための単一の自然なインターフェースを提供できるという考え方です。一部のCOMオブジェクトは、バリアント(例:type VARIANT または _variant_tdoublefloatintなどを含むことができます。

Windows C++コードでCOMオブジェクトを処理する必要がある場合、いたるところにバリアント型が表示されます。

3
Nate Kohl

ユニオンは、さまざまな種類のメッセージがある場合に役立ちます。その場合、中間レベルで正確なタイプを知る必要はありません。送信者と受信者だけがメッセージの実際のメッセージを解析する必要があります。他のレベルでは、サイズと、場合によっては送信者および/または受信者の情報を知るだけで十分です。

2
Makis
struct cat_info
{
int legs;
int tailLen;
};

struct fish_info
{
bool hasSpikes;
};


union 
{
fish_info fish;
cat_info cat;
} animal_data;

struct animal
{
char* name;
int animal_type;
animal_data data;
};
2
ironic

SDLはイベントを表すために共用体を使用します: http://www.libsdl.org/cgi/docwiki.cgi/SDL_Event

2

組合が役立つ別の例を次に示します。

(私自身の考えではなく、これは c ++の最適化 について説明しているドキュメントで見つかりました)

begin-quote

....ユニオンは、スペースを節約するためにも使用できます。

最初に非組合アプローチ:

void F3(bool useInt) {
    if (y) {
        int a[1000];
        F1(a);  // call a function which expects an array of int as parameter
    }
    else {
        float b[1000];
        F2(b);  // call a function which expects an array of float as parameter
    }
}

ここでは、aとbに同じメモリ領域を使用できます。これは、それらのライブ範囲が重複しないためです。 aとbを結合して結合することで、cpu-cache spaceを大幅に節約できます。

void F3(bool useInt) {

    union {
        int a[1000];
        float b[1000];
    };

    if (y) {
        F1(a);  // call a function which expects an array of int as parameter
    }
    else {
        F2(b);  // call a function which expects an array of float as parameter
    }
}

もちろん、ユニオンの使用は安全なプログラミング手法ではありません。これは、aとbの使用が重複してもコンパイラーから警告が出されないためです。このメソッドは、キャッシュスペースを大量に消費する大きなオブジェクトにのみ使用してください。 ...

end-qoute

1
anon

このような意味ですか?

union {
   long long a;
   unsigned char b[sizeof(long long)];
} long_long_to_single_bytes;

[〜#〜]追加[〜#〜]

私は最近、これをAIXマシンで使用して、64ビットのマシン識別子をバイト配列に変換しました。

std::string getHardwareUUID(void) {
#ifdef AIX
   struct xutsname m; // aix specific struct to hold the 64bit machine id
   unamex(&b);        // aix specific call to get the 64bit machine id
   long_long_to_single_bytes.a = m.longnid;
   return convertToHexString(long_long_to_single_bytes.b, sizeof(long long));
#else // Windows or Linux or Solaris or ...
   ... get a 6byte ethernet MAC address somehow and put it into mac_buf
   return convertToHexString(mac_buf, 6);
#endif
1
anon

パーティーに少し遅れていることはわかっていますが、実用的な例として、VBScriptのVariantデータ型はUnionとして実装されていると思います。次のコードは、他の方法で見つかった記事から抜粋した簡単な例です here

struct tagVARIANT
{
    union 
    {
        VARTYPE vt;
        Word wReserved1;
        Word wReserved2;
        Word wReserved3;
        union 
        {
            LONG lVal;
            BYTE bVal;
            SHORT iVal;
            FLOAT fltVal;
            DOUBLE dblVal;
            VARIANT_BOOL boolVal;
            DATE date;
            BSTR bstrVal;
            SAFEARRAY *parray;
            VARIANT *pvarVal;
        };
    };
};

(記事に記載されている)実際の実装は、oaidl.hCヘッダーファイルにあります。

1
user69820

私は時々このように共用体を使用しました

//Define type of structure
typedef enum { ANALOG, BOOLEAN, UNKNOWN } typeValue_t;
//Define the union
typedef struct  {
  typeValue_t typeValue;
  /*On this structure you will access the correct type of
    data according to its type*/
  union {
    float ParamAnalog;
    char  ParamBool;
  };
} Value_t;

次に、さまざまな種類の値の配列を宣言し、データを多かれ少なかれ効率的に格納し、次のような「ポリモーフ」操作を行うことができます。

 void printValue ( Value_t value ) {
    switch (value.typeValue) {
       case BOOL:
          printf("Bolean: %c\n", value.ParamBool?'T':'F');
          break;
       case ANALOG:
          printf("Analog: %f\n", value.ParamAnalog);
          break;
       case UNKNOWN:
          printf("Error, value UNKNOWN\n");
          break;
    }
 }
1
Khelben

最近、私は ベクトルプログラミング で使用されるいくつかの共用体を見たと思います。ベクトルプログラミングは インテルMMXテクノロジー 、GPUハードウェア、 IBMのセルブロードバンドエンジン などで使用されます。

ベクトルは128ビットのレジスタに対応します。 [〜#〜] simd [〜#〜] アーキテクチャで非常によく使用されます。ハードウェアには128ビットのレジスターがあるため、4つの単精度浮動小数点をレジスター/変数に格納できます。ベクトルの個々の要素を作成、変換、抽出する簡単な方法は、共用体を使用することです。

typedef union {
    vector4f vec; // processor-specific built-in type
    struct { // human-friendly access for transformations, etc
        float x;
        float y;
        float z;
        float w;
    };
    struct { // human-friendly access for color processing, lighting, etc
        float r;
        float g;
        float b;
        float a;
    };
    float arr[4]; // yet another convenience access
} Vector4f;

int main()
{
    Vector4f position, normal, color;
    // human-friendly access
    position.x = 12.3f;
    position.y = 2.f;
    position.z = 3.f;
    position.w = 1.f;

    // computer friendly access
    //some_processor_specific_operation(position.vec,normal.vec,color.vec);
    return 0;
}

playStation 3マルチコアプログラミング、またはグラフィックスプログラミングの道を進んだ場合、これらの問題に直面する可能性が高くなります。

1
Afriza N. Arief
  • 特定の型に強制変換する必要があるシリアル化されたデータを読み取るとき。
  • Lexからyaccにセマンティック値を返す場合。 (yylval
  • ポリモーフィック型、特にDSLまたは一般的な言語を読み取るものを実装する場合
  • 異なる型を取ることを目的とした関数を具体的に呼び出すディスパッチャーを実装する場合。
1
DigitalRoss

例:

異なるソケットタイプを使用しているが、共通のタイプを参照したい場合。

0
Xolve

ユニオンの多くの例が<X11/Xlib.h>にあります。一部のIPスタック(BSD <netinet/ip.h>など)にあるものはほとんどありません。

一般的なルールとして、プロトコルの実装はユニオン構造を使用します。

0
mouviciel

ユニオンは type punning の場合にも役立ちます。これは、いくつかの特定の場所( 浮動小数点比較 アルゴリズムのいくつかの手法など)で望ましいです。

0
fbrereto

もう1つの例:キャストの実行を節約する。

typedef union {
  long int_v;
  float float_v;
} int_float;

void foo(float v) {
  int_float i;
  i.float_v = v;
  printf("sign=%d exp=%d fraction=%d", (i.int_v>>31)&1, ((i.int_v>>22)&0xff)-128, i.int_v&((1<<22)-1));
}

の代わりに:

void foo(float v) {
  long i = *((long*)&v);
  printf("sign=%d exp=%d fraction=%d", (i>>31)&1, ((i>>22)&0xff)-128, i&((1<<22)-1));
}
0
fortran

便宜上、共用体を使用して、同じクラスを使用してxyzw値とrgba値を格納できるようにしています

#ifndef VERTEX4DH
    #define VERTEX4DH

    struct Vertex4d{

        union {
            double x;
            double r;
        };
        union {
            double y;
            double g;
        };
        union {
            double z;
            double b;
        };
        union {
            double w;
            double a;
        };

        Vertex4d(double x=0, double y=0,double z=0,double w=0) : x(x), y(y),z(z),w(w){}
    };

#endif
0
Tom J Nowell