gpt4 book ai didi

C 符号类型和不相交的 union 类型?

转载 作者:太空狗 更新时间:2023-10-29 15:52:33 26 4
gpt4 key购买 nike

免责声明:我是一名学习 C 的 Haskell 程序员。在 Haskell 中,我们有像这样的数据声明

data No = NO

其中 NO 没有作为数字的任何解释。如果我们在 C 中有等价的东西,我们就可以做

union MaybeInt { enum No no; int just;};

它可以用来做一些事情,比如有一个初始化为 No 的数组。

int A[k];
for (int i = 0; i < k; i++)
A[i] = NO;

这在做内存时很有用,因为通常有一些递归算法在数组中查找内容,并根据查找的值,进行递归调用或不进行递归调用。例如:(对于斐波那契数)

fibMem (int k){
if (FIB[k] == NO)
compute fibMem(k-1) + fib(k-2) and store the result in FIB[k]
return FIB[k]
}

现在,当然,我可以将 FIB[i] 初始化为一些 absurd 的值,例如 -100,这对解决这个问题很有效;然而,给定一个任意的内存例程,我不知道值的范围,这种解决方案是行不通的。

使用枚举类型的问题:让我从座位上跳起来说"is"的第一件事是枚举类型。我想为什么不做类似 enum No {no}; 的事情呢,用 no 初始化用于内存的数组有一个问题。问题是 no 被定义为 0 或我选择的某个数字常量(如果我愿意)。这是不令人满意的,因为如果存储在数组中的值应该为零(或我选择的常数),那么当我进行检查时 A[i] == no 它可能应该是这样的!因此,我最终将执行一个不需要的递归。

这给我们带来了问题 1:如何在 C 中获得一个符号常量,它被视为标志,与任何不同类型的东西都无法比较?

现在, union 的问题。 union 将其所有字段存储在一个地址中。因此,例如,对 maybeInt.just 的更新会影响 maybeInt.no 的值。例如,

union MaybeInt maybeInt;
maybeInt.just=9;
printf("%d",maybeInt.just);
printf("%d",maybeInt.no);

打印 99。如果 C 中有某种不相交 union 类型,那就太好了,这样如果我使用 union 的一个值,另一个就无法获得。

这将我们带到了第二个也是最后一个问题:如何在 C 中获得一个不相交的 union 类型——这是一种有许多可能变体但在任何给定时间只有一个变体的类型。我想要一些能够做类似的事情:

disjoint T {type1 name1 , .... };

如果设置了 T.name2,则对 T.name1 的引用会引发错误。或者更好的是,任何对 T 的引用都必须经过某种大小写区分。

如果这不能很好地完成,请解释原因。

最佳答案

可区分 union 是一个非常标准的 C 习惯用法。您只需要将标签与数据分开即可:

struct Data
{
enum DataType
{
NotSet,
Integer,
Infinity,
Message
} tag;
union ValueType
{
int n;
char const * msg;
} data;
};

现在您只需要维护标签纪律,即只读取适合给定标签的值,并在写入 union 成员后更新标签。例如:

void foo(struct Data const * x)
{
switch (x->tag)
{
case NotSet: // ...
case Integer: // use x->data.n
case Infinity: // ...
case Message: // use x->data.msg
};

x->data.msg = "Thank you!";
x->tag = Message;
}

关于C 符号类型和不相交的 union 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18992814/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com