web-dev-qa-db-ja.com

関数を使用したポインターに含まれるアドレスの変更

ポインターを宣言した場合pとしてint *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("\n The address is %u ",p);
    change_adrs(p);
    printf("\n the address is %u ",p); // but this doesn't change the address
    return 0;
}

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

31
pranphy

Cでは、関数の引数は値で渡されます。したがって、コピーは引数から作成され、変更はそのコピーに対して行われますが、変更されると予想される実際のポインタではありません。ダブルポインター引数を受け入れるように関数を変更し、これを行う場合は、参照解除された引数を変更する必要があります。例えば

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

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

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

37

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
12
user529758

Cの関数内の変数の内容を変更する場合、ポインターも同様に変数であるため、pointerまたはindirect referenceを使用して渡す必要があります常に&アドレスと*参照演算子。というのは *演算子は常に使用され、変数の値を変更するときに先行します。

#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;

}
2
snr

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

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;
}

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

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

_  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;
}
_
0
Omkant