59

ポインタpint *p;として宣言した場合。メインモジュールでは、すでに宣言されている別の整数変数がどこにあるかpを割り当てることで、に含まれるアドレスを変更できます。次のような関数を使用してアドレスを変更したいと思います。p = &a;a

void change_adrs(int*q)
{
    int *newad;
    q = newad;
}

この関数をメインモジュールから呼び出すと

int main()
{
    int *p;
    int a = 0;
    p = &a; // this changes the address contained by pointer p
    printf("The address is %u\n", p);
    change_adrs(p);
    printf("The address is %u\n", p); // but this doesn't change the address
    return 0;
}

アドレスの内容は変更されていません。同じタスクに関数を使用することの何が問題になっていますか?

4

5 に答える 5

67

Cでは、関数の引数は値で渡されます。したがって、引数のコピーが作成され、変更が行われると予想される実際のポインタオブジェクトではなく、そのコピーに変更が加えられます。これを行う場合は、ポインターからポインターへの引数を受け入れるように関数を変更し、逆参照された引数に変更を加える必要があります。例えば

 void foo(int** p) {
      *p = NULL;  /* set pointer to null */
 }
 void foo2(int* p) {
      p = NULL;  /* makes copy of p and copy is set to null*/
 }

 int main() {
     int* k;
     foo2(k);   /* k unchanged */
     foo(&k);   /* NOW k == NULL */
 }

C ++を使用する余裕がある場合、別の方法は、ポインターへの参照を受け入れるように関数を変更することです。

于 2012-11-17T13:44:50.520 に答える
17

Cでは、変数は値によって渡されます。つまり、ポインターのコピーが関数に渡されます。代わりに、ポインタへの別のポインタを使用してください。

void change(int **p, int *someOtherAddress)
{
    *p = someOtherAddress;
}

int a = 1, b = 2;
int *p = &a;

printf("*p = %d\n", *p);
change(&p, &b);
printf("*p = %d\n", *p);

このプリント

*p = 1
*p = 2
于 2012-11-17T13:45:15.323 に答える
4

Cの関数の変数の内容を変更する場合、ポインターも一種の変数です。常にアドレス演算子と間接参照演算子を使用して、ポインターまたは間接参照で渡す必要があります。つまり、変数の値を変更するときは、常に演算子が使用され、その前に置かれます。&**

#include <stdio.h>
#include <stdlib.h>


void changeIntVal(int *x) {
    *x = 5;
}

void changePointerAddr(int **q) {
    int *newad;
    *q = newad;
}

void changePPAddr(int ***q) {
    int **dummy;
    *q = dummy;
}

int main() {
    int *p;
    int **pp;
    int *tempForPP;
    int a = 0;
    printf("\n The address pointing by p -> %p, pp -> %p, value of a -> %d ", p, pp, a);


    p = &a;
    pp = &tempForPP;
    printf("\n The address pointing by p -> %p, pp -> %p, value of a -> %d ", p, pp, a);

    changeIntVal(&a);        // ----
                             //    |---
    changePointerAddr(&p);   // ----  |---->  parts of what I mean
                             //    |---
    changePPAddr(&pp);       // ----

    printf("\n The address pointing by p -> %p, pp -> %p, value of a -> %d ", p, pp, a);

    return 0;

}
于 2017-06-04T10:32:54.733 に答える
1

in関数はそれにローカルであり、その関数の変更は反映されないpため、これは実際の値を変更しません。値を渡す代わりに、のアドレスを渡します。qmainpp

以下の構文を使用してください

void change_adrs(int **q)
{
    int * otheraddess;
    *q = otheraddress; 
}

このように電話しますchange_adrs(&p);

または、別の方法があります。関数の戻りタイプを変更し、返されたアドレスをキャッチします。

int* change_adrs(int *q)
{
    int * otheraddess;
    q = otheraddress;
    return q; 
}


int main()
{
    p = change_adrs(p);
    return 0;
}
于 2012-11-17T13:45:00.150 に答える
1

のようなプリミティブデータ型のint場合、ダブルポインタは必要ありません。が格納されているアドレスに直接書き込むことができint、そのアドレスを呼び出されている関数のポインタとして扱います。これは、charポイントされるもののサイズが可変である配列(「文字列」)とは異なります。したがって、呼び出された関数内から変更する場合は、別のレベルの間接参照を使用する必要があります。これを試して:

void foo(int *oldVal)
{
    int newVal = 99;    // or whatever you want
    *oldVal = newVal;
}

int main(int argc, char *argv[])
{
    int someVal = 0;
    foo(&someVal);      // we send its address to foo()

    printf("someVal is now %d.\n", someVal);

    return EXIT_SUCCESS;
}
于 2014-04-11T08:19:58.427 に答える