让我们说我们有一个联盟:
typedef union someunion {
int a;
double b;
} myunion;
我可以在设置之后检查哪种类型的联合一个= 123? 我的方法是将这个联合添加到某个结构中,并在它为int时将uniontype设置为1,当它为double时将其设置为2.
typedef struct somestruct {
int uniontype
myunion numbers;
} mystruct;
有没有更好的解决方案?
答案 0 :(得分:18)
有没有更好的解决方案?
不,您展示的解决方案是最好的(也是唯一的)解决方案。 union
非常简单 - 它们不会“跟踪”你分配给你的内容。他们所做的就是让你为所有成员重用相同的内存范围。除此之外,它们不提供任何其他内容,因此将它们封装在struct
中并使用“类型”字段进行跟踪正是要做的事情。
答案 1 :(得分:6)
C不会自动跟踪当前正在使用的联合中的哪个字段。 (事实上,我认为从"错误"字段中读取会导致实现定义的行为。)因此,您的代码需要跟踪当前使用/填写的代码。
您保持单独的联盟类型的方法'变量是一种非常常见的方法,应该可以正常工作。
答案 2 :(得分:3)
无法直接查询当前存储在union
中的类型。
了解union
中存储的类型的唯一方法是使用显式标志(如mystruct
示例中所示),或确保控件仅在代码的某些部分流动时联盟有一个已知的活跃元素。
答案 3 :(得分:2)
根据应用程序的不同,如果它是一个短期对象,您可以对控制流中的类型进行编码,即。两个案件都有单独的块/功能
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
}
答案 4 :(得分:2)
警告:以下内容仅供学习之用:
您可以使用一些丑陋的技巧(只要您的联合中的数据类型具有不同的大小,这是当前情况):
#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);
}
但我建议你永远不要这样做。
答案 5 :(得分:0)
也许我的变体正在帮助
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);
}