• 締切済み

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

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

みんなの回答

  • R32C
  • ベストアンサー率39% (115/290)
回答No.5

参照URLの回答に答えがありますよね。 call by value であることをこのFAQで 示しているだけのことです。 call by value C言語の値渡し について調べてみましょう。 まぁ >p = &dummy; ではなく *p = dummy ; で、5が表示されると思うけどC FAQの本題ではないですね。

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.4

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

  • asuncion
  • ベストアンサー率33% (2126/6286)
回答No.3

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

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.2

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 * の変更でよいのです。

  • SaKaKashi
  • ベストアンサー率24% (755/3136)
回答No.1

なぜ変更したのですか?理由は? >p = &dummy; ではなく *p = &dummy ; ではいかが。

関連するQ&A

  • C言語の基本的な質問ですが、関数へのポインタの宣言

    関数へのポインタの質問です。 下のように、関数へのポインタを使ったプログラムを書きました。 (関数へのポインタを理解するためのものなので、実用的な意味はありません。(*^_^*) また、このプログラムはコンパイルもリンクも実行も問題なく出来ます。) #include <stdio.h> int add_func(int,int); (*func_p0) (int,int); int main(void) { int (*func_p1) (int,int); int (*func_p2) ( ); int hoge0,hoge1,hoge2; func_p0=add_func; hoge0=func_p0(3,5); printf("0 : 3+5は%d\n",hoge0); func_p1=add_func; hoge1=func_p1(3,5); printf("1 : 3+5は%d\n",hoge1); func_p2=add_func; hoge2=func_p2(3,5); printf("2 : 3+5は%d\n",hoge2); return(0); } int add_func(int x, int y) { return(x+y); } func_p0のように戻り値の型を書かない場合と、func_p1やfunc_p2のように戻り値の型を書くのとでは何が違うのでしょうか。 func_p0は外部変数ですが、自動変数にする(main関数の中で同様に宣言。)とコンパイルエラーになります。 それはなぜですか。 func_p1のように引数の型が書いてあるのと、func_p2のように引数の型が書いていないのでは何が違うのでしょうか。 int (*func_p2) ( );というのは、int (*func_p2) (void);とは違うんですよね?

  • C言語での関数の引数の受け渡しについて

    C言語での関数の引数の受け渡しについて教えてもらいたいのです。 char *p=Goo;  というポインタpがmain関数で定義され、このポインタpをある関数 void func(・・・) に渡すことは出来ますか? つまりポインタを実引数として扱うことはできるのかという事ですが・・・ int p=10; とかだったら、 void func(int test) の関数には、main関数で func(p) で仮引数testにわたせると思うんですが・・・ もし出来るようでしたら、関数の渡し方と定義の記述を教えてください。 どうか宜しくお願いします。

  • C言語で、他の関数で配列を書き換えられないようにしたい

    下のCのプログラムでは、func関数は配列aの先頭要素へのポインタを返します。 main関数の側では配列aの中身を表示します。 しかし、main関数のfor文の中の★の部分をコメントアウトせずに入れると、この配列の中身が書き換わってしまいます。  私はfunc関数以外では、この配列の中身をいじられたくないのです。  なんとかfunc関数を工夫して作成して、func関数以外では、配列の中身が変わらないようにしたいのですが、どうすればよいでしょうか。    とは言ったものの、多分できないだろうなあ、という気がします。  できないならばできないでも仕方ないのですが、確信が持てないのです。 条件があります。 funcでは表示は行なわない。 配列aの中身を表示できるように、funcから呼び出し元へ、aのアドレスまたはaの先頭要素のアドレスがわかるような情報を返す。 #include <stdio.h> char *func(int i) { static char a[]="AAAA"; a[i]='z'; return a; } int main(void) { int i; for(i=0; i<4; i++) { char *p=func(i); /* p[i]='X'; ★配列の中身を書き換えてしまう。 */ puts(p); } return 0; }

  • 関数のポインタのポインタ・・・

    main内部を変更してはならない。 関数setとsetsetで、3.140000と表示させよ gcc -Wallでいろいろと探したのですが /bin/などと表示されていて、何を直せばいいのか、わからない状態です。 簡易c言語だと 3.139999 = 3.140000 となります どこかで0.000001を足すのでしょうか? でもxで3.14で出てますしね。むしろなぜ3.13999が出てきたのか。 ただ学校のコンパイラだとセグメントエラが出ます #include <stdio.h> void out(double **); void set(double *,double **); void setset(double **,double ***); int main() { double x; double *p; double **pp; x = 3.14; set(&x, &p); setset(&p, &pp); out(pp); return 0; } void set(double *x,double **p) { *p = x; } void setset(double **p,double ***pp) { **pp = *p; } void out(double **pp) { printf("%f = 3.140000\n", **pp); }

  • 関数ポインタについて

    C言語の関数ポインタの問題で以下のような問題で、実際に解いて、プログラムを動かしてみてみました。 正常に動作したのですが、この回答では満点はもらえませんでした。 このほかに良い解答例などありましたら、教えていただけないでしょうか。 どうかよろしくお願い致します。 [問題]次の※1・※2を埋めなさい(「func1」,「func2」は解答に含まれないように書くこと)。 #include <stdio.h> void func1() { printf("func1\n"); } void func2() { printf("func2\n"); } void func(int no) { void (*func[2])(void) = {func1, func2}; /* ※1 (*func[no])() */; } int main() { /* ※2 func(1) */; return 0; } 実行結果:func2

  • 【C++】関数ポインタの代入

    C++の関数ポインタについて質問です。 下記のように関数ポインタを宣言し、3通りの代入を行ってみました。 (3)のように関数名の頭に&を付けた場合と(2)のように&を付けなかった場合で 全く動きが同じになってしまうのですが、何故なのでしょうか? ------------------------------------------ #include "stdafx.h" #include <iostream> using namespace std; void Func1(){ cout<<"Func1が呼ばれました。"<<endl; return; } int main() { //(1) void (*fp1_1)(); fp1_1 = Func1; fp1_1(); //(2) void (*fp1_2)()=Func1; fp1_2(); //(3) void (*fp1_3)()=&Func1; fp1_3(); getchar(); return 0; }

  • 【C++】関数ポインタの使い方

    関数ポインタの使い方で悩んでいます。 下記の (1)のようにグローバルメソッドとして定義したメソッドを関数ポインタに代入することは出来るのですが、 (2)のようにクラスのメンバメソッドとして定義したメソッドは関数ポインタに代入することは出来ませんでした。 Error:バインドされた関数へのポインターは関数の呼び出しにのみ使用できます。 というエラーが発生します。 関数ポインタに外部参照でメソッドを代入することは出来ないのでしょうか? -----(1)------------------------------------------------------------------ #include "stdafx.h" #include <iostream> using namespace std; int f(int a, int b){ return a * b; } int _tmain(int argc, _TCHAR* argv[]) { typedef int (* FUNC_POINTER)(int, int); FUNC_POINTER fp; fp = f; cout << fp(1,2) <<endl; getchar(); return 0; } ------------------------------------------------------------------------- -----(2)------------------------------------------------------------------ #include "stdafx.h" #include <iostream> using namespace std; class MPointerList{ public: int f(int a, int b){ return a * b; } }; int _tmain(int argc, _TCHAR* argv[]) { typedef int (* FUNC_POINTER)(int, int); FUNC_POINTER fp; //fp = f; MPointerList mP; fp = mP.f; cout << fp(1,2) <<endl; getchar(); return 0; } -------------------------------------------------------------------------

  • C言語 ポインタ 関数

    キーボードから文字列”abcdefg”を入力し、main関数で配列aryに格納する。 main関数から配列aryの先頭アドレスを副関数に引き渡す。 副関数で配列aryの最後尾の要素の内容を';'に変更する。 main関数で配列aryの内容を表示する。 この問題が解けません... #include <stdio.h> int main (void) { char ary[]="abcdef"; int *p; int i,x; p=&ary[0]; func(&i); for (x=0;x<=7;x++){ printf("%s",ary[x]); void func (int i) if(i==\0) i=';' else i++ } return 0 } とりあえずこんな感じなんですけど、出来ませんでした...

  • C言語でポインタを使ってピタゴラスの定理の関数を作りたいです

    私は今あるプログラムを書いていて、その過程でどうしても関数を使ってピタゴラスの定理を作りたいのですが、ポインタの渡し方がうまくいきませんでした。ポインタを使わない場合は次の通りでした。 double pythagoras(double a, double b){ double c; c = a*a+b*b; c = sqrt(c); return c; } これはメイン関数で二つの値a,b(int型)をpythagoras関数に入れて、ピタゴラスの定理を適用させてメイン関数にc(double型)を戻り値として返すものです。 しかし2つの値a,bがint型ではなくポインタだとうまくいかないです。どのような関数を作ればいいか分かる人がいたらぜひ教えてください。ちなみに現在a,bは次のように宣言してあります。 struct node { int a; int b struct node *next; };

  • c言語 配列

    関数の中で複数の値を配列で返したいのですが,どうすればいいでしょう? 配列を関数に渡す時にはアドレスが渡されるので,ポインタと同様関数内で値を変えればmain関数の値も変わるのではないかと思ったのですが,上手くいきません. 知りたいのは,main関数の中の配列(できれば2次元配列)の値を他の関数から値を変更する方法です.下のプログラムはためしに書いてみたものです.質問を理解するうえで役立てば幸いです. #include<stdio.h> void func(double aaa[][3] ,double bbb[]); void main(void){ double array_a[3][3]={{1,2,3},{4,5,6},{7,8,9}}; double array_b[3]={0}; func(array_a,array_b); } void func(double aaa[][3] ,double bbb[]) { int i,j; for (i=0;i<3;i++) { for (j=0;j<3;j++) { bbb[i]=bbb[i]+aaa[i][j]; } } }

専門家に質問してみよう