2

ノード内のデータを更新できるリンク リストを作成しようとしていますが、何を試しても、C では void ポインターの値 (またはそれが指す場所) を更新できないようです。 . 私が持っているテストコードは次のとおりです。

void newData(void * d)
{
    char data[] = "world";

    d = &data;
}

int main()
{
        char testData[] = "hello";
        void * testPointer = &testData;

        printf("TestData is %s\n", (char *)testPointer);

        // Modify the data
        newData(&testPointer);

        printf("TestData is %s\n", (char *)testPointer);
}

出力するだけ::

TestData is hello
TestData is hello

ここで明らかな何かが欠けていますか?また、ポインターへのポインターを使用してみましたが、役に立ちませんでした。

4

3 に答える 3

7

私はあなたが必要だと思います

void newData(void ** d) 
{
    char data[] = "world";
    *d = &data;  
}     

ただし、「ワールド」はスタック ローカルであり、newData から戻った後は有効ではないため、これには独自の問題があります。

于 2011-02-08T20:29:33.960 に答える
4

これには次の 2 つの問題があります。

char data[] = "world";

おそらく関数のスタック フレームの一部として作成されます配列はポインターに劣化します。そのため、関数が を呼び出すとret、スタックがクリーンアップされ、そのアドレスのメモリがなくなっているはずです。ここで何らかの操作が機能する場合、それはまだメモリを上書きしていないためです。

あなたは何ができますか?static(少なくとも c99 によると) プログラムの存続期間中の存在を保証する 1 つのソリューションであると宣言します(つまり、スタックではなくデータ セグメントに割り当てられ、c ライブラリがメインの前に割り当てます)。ただし、これは単なるデモであると思われるため、次のことを指摘する価値があります。

char data[] = "world";
memcpy(d, data, 5);

コンテンツをコピーしていて、値を指していないため、完全に有効です。

newData(&testPointer);

ここであなたは単純な間違いを犯しています。アセンブリのポインターは、別のメモリアドレスを保持するメモリアドレスです。関数にポインタを渡すときは、そのメモリ アドレスを渡す必要があります。これにより、その関数を呼び出すときに、ポインタの内容であるメモリ アドレスが新しいポインタの形式でスタックにコピーされます。もちろん、これらのポインターはどちらも同じものを指しているため、最終的に参照渡し型を実現できます。信じられない場合は、デバッガーで見てください。

ただし、ポインタのアドレスを渡しているため、値へのポインタへのポインタを作成しています。次のようなメモリを想像してください。

|Address|Value
|0x120  |0x121    <-- this is what you're passing with &testPointer
|0x121  |0x122    <-- this is a pointer; it contains the address of a value
|0x122  |h        <-- this is a value.
|0x123  |e
|0x124  |l
...

それがより明確になることを願っています。私の単純な記憶では、あなたは.0x120ではなく合格です0x121。もちろん、2 回逆参照することはできますが、なぜでしょうか? 簡単な解決策は、次のようにポインターを渡すことです。

newData(testPointer);
于 2011-02-08T20:49:30.510 に答える
1

少し変更すると、コードで問題を解決できると思います。

void newData(void ** d)
{
    char* data = "world";

    *d = data;
}
于 2015-05-19T09:05:57.473 に答える