みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

C 関数とポインタ

ポインタと関数がよく分かりません。
(日本語がおかしくてすみません(^_^;))

たとえば↓のようなプログラムで、

#include <stdio.h>

void increase(int *i);

int main(void)
{
int x = 3;

increase(&x);
printf("%d\n", x);

return 0;
}

void increase(int *i)
{
(*i)++;
}

結果は4になりますが、increase(&x)が&xとなっていて、
関数はvoid increase(int *i)でint *iになっているのですが、
これはvoid increase(int *i)はint型の「ポインタ」なので、
increase(&x)も&xと「アドレス」を渡さなければいけないということですか??

そして、void increase(int *i)内では、アドレス&xの指す値をインクリメント、という考えで良いのでしょうか?

投稿日時 - 2007-04-18 22:46:03

QNo.2932028

暇なときに回答ください

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

★最初に考え方はあっています。
・increase 関数は、変数のアドレス(ポインタ)を受け取ってから、その変数の内容を
 インクリメントしています。アドレス(ポインタ)の参照は『*』演算子で行えるため
 『*i』としています。でもカッコがないと先に『*i』の内容(値)を評価してから、
 アドレス(ポインタ)値をインクリメントしてしまいます。注意!
・これは、インクリメントよりも『*』演算子の方が優先順位が高いからです。
 『*i++』⇒*i の値を評価した後にポインタをインクリメント。でも評価した値は捨てられる。
 『(*i)++』⇒*i の値に対してインクリメントする。
 そのほか、
 『*(i++)』⇒*i の値を評価してから i のポインタをインクリメントする。
 『*(++i)』⇒i のポインタをインクリメントしてから *i の値を評価する。
 ※『*i++』と『*(i++)』は同じことです。
 という処理になります。

・increase 関数で変数のアドレス(ポインタ)で受け取るように指定されているため、
 呼び出し元では x 変数のアドレスを『&』演算子で求めて渡しています。
 もし、x が普通の変数ではなくて配列の場合にはそのまま x を渡せばよい。
 これは配列変数の名前(識別名)が配列のアドレスを表しているため『&』演算子を
 使う必要がないためである。
 
 int x[] = { 1, 2, 3 };
 
 increase( x ); ←『&』をつけなくて良い
 printf( "%d\n", x[0] ); ←配列の先頭である x[0] だけ値がインクリメントされる
 表示は、
 x[0]⇒2
 x[1]⇒2
 x[2]⇒3
 となります。

まとめ:
・increase 関数は int 型のポインタを受け取るので、普通の変数を渡すときには『&』演算子で
 アドレス(ポインタ)値を渡して、配列や、すでにポインタの変数は、その変数名がアドレス値を
 意味しますのでそのまま名前を渡します。
・以上。おわり。

投稿日時 - 2007-04-19 11:11:33

お礼

詳しい説明までつけてくださって、ありがとうございます!
良く分かりました(^_^)

投稿日時 - 2007-04-19 20:27:27

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

increase()は、引数として渡された「int型へのポインタ」が
指す領域に1を加える、という仕事をするための関数です。

increase()に正しく仕事をしてもらうためには、呼び出す側は
increase()に「int型へのポインタ」を渡さなければなりません。
したがって、main()で定義した変数xのアドレス(&x)を
渡しているのです。

投稿日時 - 2007-04-18 23:03:10

お礼

ありがとうございます(*^_^*)

投稿日時 - 2007-04-19 20:26:51