免责声明:我是一名学习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]初始化为一些荒谬的值,如-100,这适用于这个问题;但是,鉴于一个任意的记忆例程,我不知道值的范围,这种解决方案是行不通的。
使用枚举类型的问题:我看到的第一件事,就是让我跳出座位说“是”是枚举类型。我想为什么不做enum No {no};
之类的事情嗯,用no
初始化用于记忆的数组有问题。问题是如果我愿意,no
被定义为0
或我选择的某个数字常量。这是不能令人满意的,因为如果存储在数组中的值假设为零(或我选择的常量),那么当我执行检查A[i] == no
时,它可能应该是办法!因此,我最终会执行一个不需要的递归。
这给我们带来了问题1:如何在C中获得一个被视为标志的符号常量,这对于任何不同类型的东西都是无法比拟的?
现在,工会的问题。联盟将其所有字段存储在一个地址中。因此,例如,对maybeInt.just的更新会影响maybeInt.no的值。例如,
union MaybeInt maybeInt;
maybeInt.just=9;
printf("%d",maybeInt.just);
printf("%d",maybeInt.no);
打印99.如果在C中存在某种不相交的联合类型,那将会很好,所以如果我使用了联合的一个值,则另一个变得无法获得。
这给我们带来了第二个也是最后一个问题:如何在C中获得不相交的联合类型 - 这是一种具有许多可能变体的类型,但在任何给定时间只有一个。我希望能够做一些事情:
disjoint T {type1 name1 , .... };
并设置if T.name2,然后对T.name1的引用会引发错误。或者更好的是,对T的任何引用都必须经过某种区分。
如果不能很好地完成,请解释原因。
答案 0 :(得分:10)
受歧视的工会是一种非常标准的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;
}