ゴリラ向け動画サイト「ウホウホ動画」にありがちなこと

【C言語】別関数でポインタの値を変えたのに変わらない。

メイン関数のポインタの値を、別関数で書き換えるプログラムを作りました。
以下がそのプログラムになります。
そのままだと、ダブルポインタを操作する必要があるので分かり辛いです。なので、ダブルポインタをシングルポインタにしてからポインタの書き換えを行うようにしました。その結果、きちんとポインタの書き換えが出来なくなってしまいました。

なぜ出来なくなってしまったのでしょうか。

2つのプログラムの違いは、
>  *pp = &dummy;

>  p = *pp;      // ダブルポインタをシングルポインタにした
>  p = &dummy;
に変わっただけです。

【参考】http://www.kouno.jp/home/c_faq/c4.html#8


-----------------正しいプログラム----------------
// 以下プログラムは、正しく動作する
// 実行結果は、
//   p = 5
// と表示される

void func( int **pp );

int main (void){
  int *p;
  int a = 0;

  p = &a;
  func( &p );
  printf("p = %d\n", *p);

  return 0;
}

void func( int **pp ){
  static int dummy = 5;

  *pp = &dummy;
}
----------------------------------------------


-----------------間違いプログラム----------------
// 以下プログラムは、正しく動作しない
// 実行結果は、
//   p = 0
// と表示される

void func( int **pp );

int main (void){
  int *p;
  int a = 0;

  p = &a;
  func( &p );
  printf("p = %d\n", *p);

  return 0;
}

void func( int **pp ){
  static int dummy = 5;
  int *p;

  p = *pp;      // ダブルポインタをシングルポインタにした
  p = &dummy;
}
----------------------------------------

A 回答 (5件)

参照URLの回答に答えがありますよね。

 call by value であることをこのFAQで
示しているだけのことです。
call by value C言語の値渡し について調べてみましょう。

まぁ
>p = &dummy;
ではなく
*p = dummy ;
で、5が表示されると思うけどC FAQの本題ではないですね。
「【C言語】別関数でポインタの値を変えたの」の回答画像5
    • good
    • 0

>  p = *pp;      // ダブルポインタをシングルポインタにした


>  p = &dummy;

これを「何か変だ」と気付かないのが、わからない理由でしょうね。
これではpの中身をいじっているだけで、ppには何の影響も及ぼしません。
元コード以上に簡潔に記述する手段はありませんし、そもそも「ポインタの中身」を見る/操作する場合は*(変数名)で記述するのが当然なので元コードがわかりづらいとも思えません。
    • good
    • 0

*pp を書き換えていないから。

    • good
    • 0

int *p は


(int *)型の変数 p だと考えてみてください。

p = *pp ;

p = &dummy ;

変数pに(int *)型の値を代入しているだけです。
ローカル変数に代入しただけでは関数外に何も影響しないのはわかりますね?


「シングルポインタ」にしたというのは
void func0( int *pp ){
  static int dummy = 5;
  *pp = dummy;
}
ならわかっているではないかと思います。
これは、呼び出し側で int型のアドレスを渡して、関数側でアドレスから実体を求めて(*pp)それにint型の値を代入することで、呼び出し側のint型の内容を変更するものです。

これが、double型が対象なら
void func0( double *pp ){
  static double dummy = 5.0;
  *pp = dummy;
}
となるのもわかると思います。

「正しいプログラム」の方では、対象が(int *)型になったものなのです。
呼び出し側で (int *)型のアドレスを渡して、関数側でアドレスから実体を求めて(*pp)それに(int *)型の値を代入することで、呼び出し側の(int *)型の内容を変更するものです。
変数dummyのアドレスを渡すのが目的なので、 *PP = &dummy ;とはなりますが、それ以外のところは int → doubleの変更と同様に int → int * の変更でよいのです。
    • good
    • 0

なぜ変更したのですか?理由は?


>p = &dummy;
ではなく
*p = &dummy ;
ではいかが。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!