1

次のコードは移植可能ですか?

ポインターを値で渡すだけで、呼び出し元で変更できます。

void foo(void *p)
{
    void **pp = (void**)p;
    *pp = "hahaha";
}

int main(int argc,char **argv)
{
    void *p = NULL;
    p = &p;
    printf("%p\n",p);
    foo(p);
    printf("%s\n",(char *)p);     // hahaha
    printf("%p\n",p);

    return 0;
}
4

3 に答える 3

4

はい、ポインターが指すものを変更できますが、ポインターがそれ自体を指すようにしたため、それを行うことしかできません。

p = &p;

あなたの質問に答えるには、はい、これは移植可能です。いいえ、一般的には良い考えではありません。

于 2010-12-29T00:54:32.123 に答える
3

ポインターを値でポインターに渡すと、それ自体に割り当てるときと関数に渡すときに、ポインターが単一のポインターのように見えます。そのポインターがそれ自体を指すようにしたという理由だけで機能します。

あなたがやっていることは基本的にこれです:

void foo(void **p)
{
    *p = "hahaha";
}

int main(int argc,char **argv)
{
    void *p = NULL;
    printf("%p\n", &p);
    foo(&p);
    printf("%s\n",(char *)p);     // hahaha
    printf("%p\n", p);
    return 0;
}

いくつかのキャストとトリックが追加されています。「暗黒のカードトリック」と私は言いますが、実際のプログラムに入れるのは間違いなく良い考えではありません.

実際に質問に答えるには:はい、移植可能である必要があります。標準では、すべてのデータポインターを問題なく a との間でキャストできることが保証されているためvoid *です (これは、コードで常に行っていることです)。

へのポインターvoidは、任意の不完全型またはオブジェクト型へのポインターとの間で変換できます。不完全な型またはオブジェクト型へのポインタは、ポインタに変換されたりvoid 、元に戻されたりする可能性があります。結果は元のポインタと等しくなります。

(C99、§6.3.2.3.1)

于 2010-12-29T00:56:29.920 に答える
2

あなたは実際にポインターへのポインターで遊んでいます。あなたはまだポインタを値渡ししており、コンパイラを騙して呼び出し元の値を変更していません。変更しているのは、ポインターへのポインターが指す値だけです。

自分自身や他のプログラマーを混乱させることを除けば、実生活で使用するのはあまり良い考えではありません。

于 2010-12-29T00:58:38.610 に答える