web-dev-qa-db-ja.com

ユニオンで現在使用されているタイプを確認するにはどうすればよいですか?

組合があるとしましょう:

typedef union someunion {
    int a;
    double b;
} myunion;

たとえば、設定した後、どのタイプが結合されているかを確認することはできますか? a = 123?私のアプローチは、この共用体をいくつかの構造体に追加し、intの場合はuniontypeを1に設定し、doubleの場合は2に設定することです。

typedef struct somestruct {
    int uniontype
    myunion numbers;
} mystruct;

より良い解決策はありますか?

30
tomdavies

より良い解決策はありますか?

いいえ、あなたが示した解決策は最良の(そして唯一の)解決策です。 unionsは非常に単純です。つまり、割り当てたものを「追跡」しません。彼らがしているのは、すべてのメンバーに同じメモリ範囲を再利用できるようにすることだけです。それらはそれ以上のものを提供しないので、それらをstructで囲み、追跡に「タイプ」フィールドを使用することは正確に正しいことです。

18
dasblinkenlight

Cは、ユニオンのどのフィールドが現在使用されているかを自動的に追跡しません。 (実際、「間違った」フィールドから読み取ると、実装で定義された動作が発生すると思います。)そのため、現在使用/入力されているフィールドを追跡するのはコード次第です。

個別の「uniontype」変数を保持するためのアプローチは、これに対する非常に一般的なアプローチであり、うまく機能するはずです。

6
Eric Pi

現在unionに格納されている型を直接クエリする方法はありません。

unionに格納されている型を知る唯一の方法は、(mystructの例のように)明示的なフラグを設定するか、次の場合に制御がコードの特定の部分にのみ流れるようにすることです。ユニオンには既知のアクティブな要素があります。

4
Mankarse

警告:以下は学習目的のためだけです:

これを行うには、いくつかの醜いトリックを使用できます(和集合のデータ型のサイズが異なる限り、これが現在のケースです)。

#include <stdio.h>

typedef union someunion {
  int a;
  double b;
} myunion;

typedef struct somestruct {
  int uniontype;
  myunion numbers;
} mystruct;


#define UPDATE_CONTENT(container, value) if ( \
                                             ((sizeof(value) == sizeof(double)) \
                                              ? (container.uniontype = ((container.numbers.b = value), 2)) \
                                              : (container.uniontype = ((container.numbers.a = value), 1))))

int main()
{
  mystruct my_container;

  UPDATE_CONTENT(my_container, 42);
  printf("%d\n", my_container.uniontype);
  UPDATE_CONTENT(my_container, 37.1);
  printf("%d\n", my_container.uniontype);
  return (0);
}

しかし、私はあなたがこれを決してしないことを勧めます。

2
yoones

アプリケーションによっては、それが短命のオブジェクトである場合、制御フローでタイプをエンコードできる場合があります。両方の場合に別々のブロック/機能があります

  struct value {
      const char *name;
      myunion u;
  };

  void throwBall(Ball* ball)
  {
     ...
     struct value v;
     v.name = "Ball"; v.u.b = 1.2;
     process_value_double(&v);      //double
     struct value v2;
     v2.name = "Age";
     v2.u.a = 19;
     check_if_can_drive(&v2);       //int
     ...
  }

  void countOranges()
  {
       struct value v;
       v.name = "counter";
       v.u.a = ORANGE;
       count_objects(&v);          //int
  }
2
Adrian Panasiuk

多分私の変種は助けています

struct Table
{
    char mas[10];
    int width;
    int high;
    union stat
    {
        int st;
        char v;
    } un;
};


Table tble[2];
strcpy(tble[0].mas, "box");
tble[0].high = 12;
tble[0].width = 14;
tble[0].un.v = 'S';

strcpy(tble[1].mas, "bag");
tble[1].high = 12;
tble[1].width = 14;
tble[1].un.st = 40;

//struct Table *ptbl = &tble[0];
//ptbl++;

for (int i = 0; i < 2; i++)
{
    void *pt = &tble[i].un;
    if(*((char*)pt) == 'S')     
        sort(put_on_bag_line);
    else
        sort(put_on_box_line);
}
0
rrafornet