如何知道为union设置了哪个变量值?

时间:2014-10-10 10:21:18

标签: c logic unions

我正在努力优化项目。它包含一个选项结构,用户可以在其中一次选择一个选项。除了该选项之外,我们还使用标志变量来检查为此记录设置的选项值。      为了使内存有效,我想将struct转换为union。但是,我如何知道联合中设置了哪个变量值。因为联合中没有限制来获取变量的值,即使没有设置它也是如此。

 struct options{
     int basicPay;
     int lumsumPay;
     int mothlyPay;
     int weeklyPay;
     int dailyPay;
     int anualPay;

     int payType;   // Flag variable to check which option is selected
 };

union OptimizeOptions{
    int basicPay;
    int lumsumPay;
    int mothlyPay;
    int weeklyPay;
    int dailyPay;
    int anualPay;

    int payType;   // Confuse at here
 };

3 个答案:

答案 0 :(得分:17)

工会遇到的问题是,没有简单的方法可以知道工会的哪个成员最后一次更改。为了跟踪此信息,您可以将union嵌入到具有另一个成员的结构中(称为“标记字段”或“判别”) 。标记字段的目的是提醒更改/更新哪个成员。你可以试试这个:

typedef struct{
       int payType;      // Tag field 

       union{
           int basicPay;
           int lumsumPay;
           int mothlyPay;
           int weeklyPay;
           int dailyPay;
           int anualPay;
      }OptimizeOptions;

}Options;

但是,在你的情况下,没有必要为联盟写六个单独的成员,因为它们都是int类型。因此可以减少到

typedef struct{
    enum{BASIC_PAY, LUMSUM_PAY, MONTHLU_PAY, WEEKLY_PAY, DAILY_PAY, ANNUAL_PAY} payType; 
    int pay;
}Options;

让我们通过一个简单的例子来理解使用标记字段。假设我们想要一个可以存储intdouble类型数据的数组。使用union可以实现这一点。因此,首先定义一个将存储intdouble的联合类型。

typedef union {
      int i;
      double d;
} Num;

接下来,我们必须创建一个元素为Num type

的数组
Num num_arr[100];

现在,假设我们要将0的元素num_arr分配给商店25,而元素1则存储3.147。这可以作为

完成
num_arr[0].i = 25;
num_arr[1].d = 3.147;  

现在假设我们必须编写一个打印num_arr元素的函数。功能如下:

void print_num(Num n)
{
     if(n contains integer)
         printf("%d", n.i);
     else
         printf("%f", n.d);
}

等待! print_num如何决定n是否包含整数或double

这将通过使用标记字段来完成:

typedef struct{
    enum{INT, DOUBLE} kind;        //Tag field
    union{
       int i;
       double d;
    }u;
}Num;   

因此,每次将值分配给u的成员时,kind 必须 1 为设置为INTDOUBLE以提醒我们实际存储的类型。例如:

n.u.i = 100;
n.kind = INT;

print_num函数将是这样的:

void print_num(Num n)
{
     if(n.kind == INT)
         printf("%d", n.i);
     else
         printf("%f", n.d);
}  

1 :程序员有责任使用union成员的每个作业更新标记字段。忘记这样做会导致错误,正如@ comment j_random_hacker中指出的那样。

答案 1 :(得分:15)

您是否在union内尝试了struct?让我们看看以下示例等效:

union options{
  int basicPay;
  int lumsumPay;
  int mothlyPay;
  int weeklyPay;
  int dailyPay;
  int anualPay;
};

struct record{
  union options op;   // Options union
  int payType;   // Flag variable to check which option is selected
}

union(options)将为其最大变量保留内存,您可以设置其值,您的结构(记录)将跟踪该联合内存块,并且payType标志值可能是设置将告诉你的程序获取联合的特定变量。

答案 2 :(得分:0)

现在 std::variant 包含了这个通用功能。

std::variant<int, float> x;
x = 42;
bool is_x_an_int = std::holds_alternative<int>(x); // YES
bool is_x_a_float = std::holds_alternative<float>(x); // NO
int value_of_x = std::get<int>(x); // 42
int an_error = std::get<float>(x); // exception

https://en.cppreference.com/w/cpp/utility/variant