1

リンクリストに少し問題があります。このコードがリンクリストを問題なくトラバースして出力する理由がわかりません。

struct foo {
    int data;
    struct foo * next;
};

int main(void) {
    struct foo * bar = NULL;
    ...
    print(bar);
}

void print(struct foo * bar) {
    while (bar != NULL) {
        printf("%d, bar->data);
        bar = bar->next;
    }
}

しかし、配列などの別の構造内にリストを配置すると、ポインターが次の場所で再割り当てされるため、トラバーサル中にリストが破棄されますbar[i] = bar[i]->next

struct foo {
    int data;
    struct foo * next;
};

int main(void) {
    struct foo ** bar = (struct foo**)malloc(SIZE * sizeof(struct foo*));
    for (i = 0; i < SIZE; i++)
        bar[i] = NULL;
    ...
    print(bar);
}

void print(struct foo ** bar) {
    for (i = 0; i < SIZE; i++)
        while (bar[i] != NULL) {
            printf("%d, bar->data);
            bar[i] = bar[i]->next;
        }
}

なぜこれが起こるのですか?printこのシナリオで関数を作成する適切な方法は次のとおりです。

void print(struct foo ** bar) {
    struct foo * helper;
    for (i = 0; i < SIZE; i++)
        for (helper = foo[i]; helper != NULL; helper = helper->next)
            printf("%d", helper[i]->data);
}

理由を理解したいだけです。最初のシナリオではポインタが再割り当てされないのに、2番目のシナリオでは再割り当てされるのはなぜですか?値の受け渡しと参照の受け渡しに関係していると思いますが、それは最初の関数もリストを破棄することを意味します。誰かがいくつかの洞察を提供できますか?

4

1 に答える 1

2
void print(struct foo* bar)
{
    while (bar != NULL)
    {
        printf("%d, bar->data);
        bar = bar->next;
    }
}

この関数はcopy of a pointer to struct foo、最初の引数としてを取ります。関数がそれをどのように処理するかに関係なく、ここではコピーを操作しているだけなので、元のポインターは変更されないことを確信しています。一方、ポインタが指す値は変更できます。

void print(struct foo** bar)
{
    for (i = 0; i < SIZE; i++)
        while (bar[i] != NULL)
        {
            printf("%d, bar->data);
                bar[i] = bar[i]->next;
        }
}

この関数はcopy of a pointer to pointer to struct foo、最初の引数としてを取ります。この場合も、元のポインタからポインタへのポインタはここから変更できません。一方、ポインタが指す値、つまりここからはpointer to foo変更できます。もちろん、バーが指すポインタが指す値も変更できます。

これを正しく理解していれば、関数に渡すstruct something代わりに渡すことがstruct something*パフォーマンスの観点から悪い考えである理由を理解する必要があります。

于 2012-12-23T03:51:12.833 に答える