6

次のようなポインタ引数を使用してリンクリストを初期化したい:

/* 
 * Initialize a linked list using variadic arguments
 * Returns the number of structures initialized
 */
int init_structures(struct structure *first, ...) 
{
    struct structure *s;
    unsigned int count = 0;
    va_list va;
    va_start(va, first);

    for (s = first; s != NULL; s = va_arg(va, (struct structure *))) {
        if ((s = malloc(sizeof(struct structure))) == NULL) {
            perror("malloc");
            exit(EXIT_FAILURE);
        }
        count++;
    }

    va_end(va);

    return count;
}

問題は、でclangエラーが発生type name requires a specifier or qualifierva_arg(va, (struct structure *))、型指定子がデフォルトでintになっていることです。(struct structure *)また、およびでインスタンス化されたフォームにも注意してstruct structure *ください。これ、割り当てられているように見えるのsはですint (struct structure *)

から括弧を削除すると正常にコンパイルされます(struct structure *)が、初期化されるはずの構造にアクセスできません。

intかっこがva_argに渡された型引数の周りにあるのになぜ仮定されるのですか?どうすればこれを修正できますか?

4

3 に答える 3

7

va_argは多くのシステムのマクロであり、かっこで囲まれてstruct structure *いるとマクロが展開されるため、解析できないものになります。だからそうしないでください。

これは、初期化された構造に「アクセスできない」理由とは関係ありません。構造体を割り当ててに割り当てていますがs、これsはローカル変数です。ローカル変数に割り当てることによって、呼び出し元の値に影響を与えることはできません。あなたがやりたいことを達成するために、発信者はポインタからポインタを渡す必要があり、それを初期化することができます

int init_structures(struct structure **first, ...) 
{
    struct structure **s;
    unsigned int count = 0;
    va_list va;
    va_start(va, first);

    for (s = first; s != NULL; s = va_arg(va, struct structure **)) {
        if ((*s = malloc(sizeof(struct structure))) == NULL) {
            perror("malloc");
            exit(EXIT_FAILURE);
        }
        count++;
    }

    va_end(va);

    return count;
}

そして、発信者は次のことを行う必要があります。

struct structure *a, *b;
init_structures(&a, &b, NULL);
于 2010-05-16T22:03:54.453 に答える
5

C99の§7.15.1.1(va_argマクロ)には以下が必要です。

パラメータタイプは、タイプに*を後置するだけで、指定されたタイプを持つオブジェクトへのポインタのタイプを取得できるように指定されたタイプ名でなければなりません。

そのため、ここでは括弧を使用できません。

struct structure **他の回答では、mallocの結果をに渡して割り当てる必要がある理由が説明されてい*sます。

于 2010-05-16T22:08:34.733 に答える
1

のタイプの周りにparensを配置することはできません va_arg。あなたはする必要はありません。va_arg奇妙な獣です。実際には、これはCPPマクロであり、ある種のコンパイラごとの魔法に拡張されます。コンパイラで拡張を見ると、コンパイラがどのように拡張するかがわかります。それが何であれ、それはparensが好きではありません。

于 2010-05-16T22:03:50.550 に答える