• ベストアンサー

ポインタのポインタが引数にある関数の使い方。

ポインタのポインタが引数にある関数の使い方。 現在、このポインタのポインタが引数にある関数の動きがわからず困っています。 int test(int ** head) { int * pTail = (int *)*head; pTail = pTail + 1; } もし、この関数を呼び出して使用した場合どのような動きをするのでしょうか? int * comm_msg; これをグローバルポインタ変数として宣言させて、 test((void **)&comm_msg); このように呼び出したとした場合とさせていただきます。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

ローカル変数pTailをincrementしているだけで、それ以外は何もしないんじゃないですか? 以下の関数ならcomm_msgをincrementします。 int *comm_msg; test(&comm_msg); int test(int ** head) { *head = *head + 1; }

techhouse
質問者

お礼

回答頂きありがとうございます。 今ちょっと動作がわからない関数プログラムというのがありまして、 int count_list(void ** head) { int cnt = 0; list_t * pTail = (list_t *)*head; if(*head != NULL) { while (1) { cnt++; if(pTail->next == NULL) break; pTail = pTail->next; } } return cnt; } linked listっていうプログラムらしいのですが、 このプログラムを comm_msg_t * comm_msg;  このポインター変数をグローバル宣言して、 int comm_msg_count() { return count_list((void **)&comm_msg); } この関数で呼び出すというプログラムがあるのですが、動作がいまいちわからないのです。 特になんですが、グローバルポインタ変数の”comm_msg”というのを count_list((void **)&comm_msg); この引数で呼び出すと、 count_list関数内で、 list_t * pTail = (list_t *)*head; このプログラムでpTailに”comm_msg”のアドレス番地をポイントするデータがメモリアドレスにポイントされると思うので、 ”pTail = pTail->next;”このプログラムで、グローバル変数内が書き換わってしまうと思うのですが、 プログラム動作としてはグローバル変数は書き換えないと聞いたのですが、本当にそのような動作なのでしょうか?

その他の回答 (2)

回答No.3

#2です。 pTailそのものはローカル変数であって、あくまでその値がglobal変数の内容を指しているだけです。 したがって、pTailを書き換えてもcomm_msgの内容は変わりません。 comm_msg_t型のデータがアドレス、ADR_AAA にあるとします。 comm_msgのアドレスを ADR_MSG とすると、 ADR_MSGのメモリ番地にADR_AAAというアドレス値が入っています。 count_list()を呼び出した時点で headには ADR_MSGというアドレス値が入っています。 pTaliは初期値でポインタ変数headの指す先の値が入るので、ADR_AAAが入ります。 この時、pTailはスタック上に作られたローカル変数なので、ADR_MSGとは違う場所のADR_PTAILとかいうアドレスに存在します。 ここでcmm_msg_t型の構造体の要素nextはcmm_msg_t型へのポインタになっていると思われますが、 ADR_AAAに存在する構造体のnextの値をADR_NEXTとすると  pTail = pTail->next; で書き換わるのはpTailだけです。 つまり  ADR_MSGの内容:ADR_AAAのまま  ADR_PTAILの内容:ADR_AAA -> ADR_NEXT となります。 あくまでローカル変数の値を書き換えてるだけで、ポインタの指す先を書き換えたりしてるわけじゃありません。

回答No.2

とりあえず関数の定義と呼び出しの型が違うので、エラーかワーニングが出ます。 int型のポインタ comm_msg が指すアドレスを ADR_AAA とします。 この comm_msg のアドレスをint型のポインタへのポインタとして関数に渡されています。 初期状態では head はポインタ変数 comm_msg のアドレスを指しています。  head -> &comm_msg 次にint型のポインタ変数 pTail に head の差すポインタの中身が渡されているわけですから、 pTali には comm_msg が指していたアドレス ADR_AAA が入ります。  pTail -> comm_msg (== ADR_AAA) 次にこのint型ポインタ変数をインクリメントしているので、 pTail の値は int型のデータ1つ分のサイズだけアドレスが加算されます。  pTail -> ADR_AAA + sizeof(int)

techhouse
質問者

お礼

回答頂きありがとうございます。 今ちょっと動作がわからない関数プログラムというのがありまして、 int count_list(void ** head) { int cnt = 0; list_t * pTail = (list_t *)*head; if(*head != NULL) { while (1) { cnt++; if(pTail->next == NULL) break; pTail = pTail->next; } } return cnt; } linked listっていうプログラムらしいのですが、 このプログラムを comm_msg_t * comm_msg;  このポインター変数をグローバル宣言して、 int comm_msg_count() { return count_list((void **)&comm_msg); } この関数で呼び出すというプログラムがあるのですが、動作がいまいちわからないのです。 特になんですが、グローバルポインタ変数の”comm_msg”というのを count_list((void **)&comm_msg); この引数で呼び出すと、 count_list関数内で、 list_t * pTail = (list_t *)*head; このプログラムでpTailに”comm_msg”のアドレス番地をポイントするデータがメモリアドレスにポイントされると思うので、 ”pTail = pTail->next;”このプログラムで、グローバル変数内が書き換わってしまうと思うのですが、 プログラム動作としてはグローバル変数は書き換えないと聞いたのですが、本当にそのような動作なのでしょうか?

関連するQ&A

  • 関数ポインタについて

    関数ポインタを使用する際に、 指定する先の関数でデフォルト引数が指定されている場合、 関数ポインタを用いて、その引数を省略して呼び出すことはできるのでしょうか? 以下例とします。 void function(int a = 10){}; typedef void (*test)(int a); test a = &function; a(); //このように呼び出したい

  • ポインタを引数で使用する場合

    初心者です。 ローカル関数でポインタを引数で使用する場合の定義で int A (int *x,int *y) とする場合の*はポインタの宣言としての*なのでしょうか? これまでの例題ではメイン関数のなかでポインタを宣言しアドレスを代入し・・・という使い方だったのですがローカル関数で引数を使用するさいはメイン関数内ではポインタの宣言はないので関数の定義と同時にint *x とint *yを宣言するという事なのでしょうか? それ以降の*は間接参照演算子ですね。

  • ポインタ引数をさらにポインタ引数に渡す方法

    ポインタ引数をさらに関数のポインタ引数として設定するには、 どうしたらよいのでしょうか? イメージとしては、 int 関数A(*a *b) { *a = 5; *b =3; 関数B(*a *b) } またポインタ引数の関数内で、 ポインタ指定せずに変数を使えるのでしょうか? int 関数A(*a *b) { a = 5; b =3; 関数B(*a *b) }

  • 関数の仮引数は宣言か式か

    ”関数の仮引数の宣言”は”変数の宣言・定義”と同じように”宣言”と明確に考えるべきなのか”関数の仮引数”を”式”と考えて良いのかという問題です。 私が迷ってしまったのは"配列を仮引数"にとった例です。 規則として ”int a[ ] が int *a と同じ意味になるのは、唯一、関数の仮引数の宣言のばあいだけである”という規則がありますが、これは”関数の仮引数の宣言”は変数の宣言・定義”と同じように”宣言”と明確に考えている例だとおもいます。 int a[ ] が int *a と型名 変数名(引数名)と宣言の形をとっているので当然だと思いますが、一方 配列は、式の中で「先頭へのポインタ」によみかえられる。               ↓ 関数の引数は式なので、配列は「先頭へのポインタ」に読み変えられる←引数部分を”宣言”ではなく”式”と捉えてる←ここが私の迷っているところ               ↓ よって、関数に渡ってくるのは、結局はつねにポインタだ。 という説明もあります。 私の今までの理解ではc言語では”宣言の部分”と”式”の部分は明確に区別されるものと考えていました。”宣言部分の初期化の="と”代入の=”とは明確に区別されていました。 それと同じように”関数の仮引数の宣言”は”宣言部分”と捕らえるのか”式”ととらえるのか ”宣言”と”式”が私の頭の中混乱しています。 宜しくお願いします。

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

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

  • 参照型の変数をポインタ引数を持つ関数に引数を書く方法

    C++の参照を使って以下のソースを試したのですが、 memmoveの引数のところでエラーが出ます。 memmoveの引数はポインタ型で合いません。 実体コピーしたい場合、どのようにすればよいのでしょうか? const AA &aとすれば、a自体が関数内で書き換わる心配がないので、 C++の参照型は、ポインタより安全と理解しているのですが その認識は間違っていないでしょうか? struct aa{ int x; int y; }AA; void test(AA &a) { AA b; memmove(b, a, sizeof(AA)); } void main(){ AA c; test(c); }

  • ポインタのポインタを引数にもった関数から値を得たい

    すいません。 似たような題も多かったのですが、初心者のため、わかりませんでした。 質問させてください。  ポインタのポインタを引数にもった関数を作りたいのですが、まったくわかりません。 (ポインタであれば、何とかできたのですが…) 例を作ってみました。下記で、dd[2][2]にtest2関数から値を得るとします。 ?1と?2、?3に何を入れたらよいでしょうか?  (?1で得られる値は何でもかまいません。) きわめて抽象的で、申し訳ないのですが、どうぞよろしくお願い致します。 void test2(double **d1) { ?1 } void C_testDlg::OnBnClickedButton1() { // TODO: ここにコントロール通知ハンドラ コードを追加します。 double dd[2][2]; ?2 test2(?3); CString cs; cs.format("%g", dd[1][2]) ::AfxmessageBox(cs); }

  • 関数の引数表記なしについて

    はじめまして。C言語初心者です。 質問させてください。 関数を宣言して引数を表記しないで使用することは可能なのでしょうか? またどのような場合に使用するのでしょうか? 例として以下コードになります。 ----------------------- #include<stdio.h> int test1(int a); void test2(int b); void main(){ int i = 0; int j = 0;       //この部分 i = test1; printf("%d\n", i);        //この部分 j = test2; printf("%p\n", j); } int test1(int a){ return a + 1; } void test2(int b){ printf("test"); } --------------------------- 出力結果を見ると関数のアドレスが帰ってくるように思われますが、詳細が分かりません。 詳しい方がいらしましたら教えてください。 宜しくお願いいたします。

  • SystemC言語の文法(関数の引数にポインタ?)

    SystemC言語の文法について質問です。 ある雑誌で、ビット宣言変数のアドレスを関数に渡しており、 私も真似て作ってみたのですが、エラーが発生してしまいます。 --- (例) 引数にポインタを入れる処理 // 引数 sc_uint<32> *s の関数 void test::Calc_func( sc_uint<32> *s ) { cout << "s[0] = " << s[0]; // 32bitのデータ出力? } // これがmain文の代わりです void test::A_func(void) { sc_biguint<2048> a; sc_uint<12> i; for( i = 0; i < 2048; i++ ) { a[i] = 0; } Calc_func( &a[0] ); // ←問題! } // Error内容 Calc_funcの引数の入れ方が駄目! --- 色々、Calc_funcへの型を変えてやってみたのですが、 全くびくともしません。 雑誌が間違っている可能性は低いと思いまして、 今回、このような質問をさせていただきました。 インターネット上の情報でも、このような処理を 見つけることができませんでした。 どうぞよろしくお願いいたします。

  • 関数ポインタの型をtypedefしたとき

    C言語において、関数ポインタの型をtypedefで作ると、 typedef int (*MyFunc)(int*,int*); と宣言でき、関数ポインタの変数は、 int FuncA(int* a, int* b) { ~ } void main_loop() { MyFunc pf = FuncA; ~ (*pf)(pa,pb); } というように使うと思います。 ここで疑問なのですが、この実際に呼び出される関数、FuncAの定義に、typedef(ここではMyFunc)を使えないものでしょうか? 同じことを2回やっているようで、無駄に思えてしまいます。

専門家に質問してみよう