3

免責事項: 私は C を学習している Haskell プログラマーです。Haskell では、次のようなデータ宣言があります。

data No = NO

ここで、NO は数値として解釈されません。Cに同等のものがある場合、次のことができます

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

いいえとして初期化された配列を持つようなことを行うために使用できます。

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}; 、メモ化に使う配列をsで初期化するのに問題があるno。問題は、必要に応じて、または選択した数値定数であるnoと定義されていることです。配列に格納されている値がゼロ (または選択したその定数) であると想定されている場合、チェックを行うとそのようになる可能性が0あるため、これは不十分です! したがって、不要な再帰を実行することになります。A[i] == no

これにより、質問 1 が発生します。C で、フラグとして扱われる記号定数を取得するにはどうすればよいでしょうか。これは、別の型のものとは比較になりません。

さて、労働組合の問題。ユニオンは、すべてのフィールドを 1 つのアドレスに格納します。したがって、たとえば、maybeInt.just への更新は、maybeInt.no の値に影響します。例えば、

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

99 を出力します。C にある種の互いに素な共用体型があれば、その共用体の値の 1 つを使用すると、もう 1 つは取得できなくなるというのがよいでしょう。

これは、2 番目の最後の問題につながります。C で互いに素な共用体型を取得するにはどうすればよいでしょうか。これは、多くの可能なバリアントを持つ型ですが、常に 1 つしかありません。次のようなことができるようにしたいと思います。

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

T.name2 が設定されている場合、T.name1 への参照はエラーをスローします。または、T への参照は、何らかの大文字と小文字の区別を経る必要があります。

これがうまくできない場合は、その理由を説明してください。

4

1 に答える 1

11

判別共用体は、非常に標準的な C のイディオムです。タグをデータから分離しておく必要があります。

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

ここで、タグの規律を維持する必要があります。つまり、特定のタグに適切な値からのみ読み取り、共用体メンバーへの書き込み後にタグを更新するだけです。例えば:

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;
}
于 2013-09-24T22:04:00.843 に答える