関数の引数にポインタを使うときの初歩的な質問

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ケトン

関数の引数にポインタを使うときの初歩的な質問

#1

投稿記事 by ケトン » 7年前

たとえば次の関数を宣言(定義)するときに

コード:

void swap (int *pX,int *pY);
引数には*pX,*pYの二つ(変数の値!)があって,

関数を呼び出すときに

コード:

swap (&num1,&num2);
引数には二つの変数のアドレス!を使います。

なぜ,宣言(定義)するときは値で,実際使うときはアドレスを引数にするのですか?
理由もしくは考え方の間違っているところをおしえてください。お願いします。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 関数の引数にポインタを使うときの初歩的な質問

#2

投稿記事 by みけCAT » 7年前

アドレスは値の一種です。
ケトンさんの考える「値」「アドレス」の定義を教えていただけますか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ケトン

Re: 関数の引数にポインタを使うときの初歩的な質問

#3

投稿記事 by ケトン » 7年前

例えば変数aを

コード:

int a = 10;
で初期化したとき、10がaの値、&aがaのアドレスということです。
*pAは僕のいう「値」で、pAは「アドレス」のはずなのに、どうして質問のようなことが起こるのでしょうか。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 関数の引数にポインタを使うときの初歩的な質問

#4

投稿記事 by みけCAT » 7年前

ケトン さんが書きました:

コード:

void swap (int *pX,int *pY);
引数には*pX,*pYの二つ(変数の値!)があって
ありません。
引数はint *型(ポインタ型 = アドレスが入る)のpXとpYです。

コード:

int *pA = &a;
でポインタ型の変数pAにaのアドレスを入れるのと同じようなものですね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

C6b14

Re: 関数の引数にポインタを使うときの初歩的な質問

#5

投稿記事 by C6b14 » 7年前

あ 質問の 意味が 閃いた ので 書いておきます。 この場合は 関数 の 問題です。
厳密にいうと a には 値 と アドレス が あって 中身 と 箱 の関係 です。
引数には 2種類あって 仮引数 と 実引数 です。
void swap (int *pX,int *pY);
この関数の場合は a  のアドレスを コピーして渡し て くださいと 言っています。(機械語ではスタックメモリーをアドレスが入る分用意する) 
void swap (int pX,int pY);
この関数の場合は a  の値(中身)を コピーして渡し て くださいと 言っています。(機械語ではスタックメモリーを値が入る分用意する)
関数の宣言時 欲しいの はスタックメモリーの用意する容量であって つまりは型情報 です。( int * ,int * )だけで pX ,pY は何でもよいので Foo, Hoge でもいいはずです。

呼び出すときは swap (&num1,&num2);
の num1, num2 は int として 「宣言」 が必要です。

[ アドレス渡し]  [値 渡し]  については
我々はあまりにも常識化して疑問がわかないけれど 誰もが 一度は 疑問に 思ったはずです。

C6b14

Re: 関数の引数にポインタを使うときの初歩的な質問

#6

投稿記事 by C6b14 » 7年前

あごめんなさい。 a のところは pX, pY の間違い です。

あんどーなつ
記事: 171
登録日時: 7年前
連絡を取る:

Re: 関数の引数にポインタを使うときの初歩的な質問

#7

投稿記事 by あんどーなつ » 7年前

カーニハン、リッチー著「プログラミング言語C 第2版」のp. 114に非常に興味深い記述があります。
(※著者はC言語の開発者)
ポインタipの宣言

int * ip

は記号表現として、*ipという表現がintであることを表わす。変数に対するこの宣言の構文は、変数が現われる式の構文を真似たものである。この解釈は関数の宣言にも当てはまる。例えば

double *dp, atof(char *);

は、ある式の中で*dpとatof(s)がdoubleの型をもち、atofの引数がcharへのポインタであることを表わす。
私は上記のことをアフォーダンスに優れているとは思いませんが、答えにはなっているでしょう。

値渡し、アドレス渡しというのは、あまり考えなくてよいと思います。江戸幕府の成立はいつなのか、というような議論と同じだとおもってください。

C6b14

Re: 関数の引数にポインタを使うときの初歩的な質問

#8

投稿記事 by C6b14 » 7年前

失礼いたしました。”値渡し、アドレス渡しというのは”  間違い。 ”関数の アドレス を呼びだす 仕組みは” とかくつもりが 今読むと変な事を書いてました。 ごめんなさい。

box
記事: 2002
登録日時: 13年前

Re: 関数の引数にポインタを使うときの初歩的な質問

#9

投稿記事 by box » 7年前

ケトン さんが書きました:

コード:

void swap (int *pX,int *pY);
引数には*pX,*pYの二つ(変数の値!)があって,
ここを即値とお考えでしたらちょっと違うと思います。
int *型の値ですから、中身は変数のアドレス値です。一方、
ケトン さんが書きました: 関数を呼び出すときに

コード:

swap (&num1,&num2);
呼び出す側では、変数のアドレスという値を渡しています。
何もおかしくないと思います。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

ケトン

Re: 関数の引数にポインタを使うときの初歩的な質問

#10

投稿記事 by ケトン » 7年前

>>4 みけCAT氏
>>9 box氏
なるほど、int型の*pXではなく、int*型のpXを宣言したと考えればよいのですね。
そうだとすれば、

コード:

int *pX Y;
という宣言は、int*型のpXとint型のYを宣言したと考えてよいですか?

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 関数の引数にポインタを使うときの初歩的な質問

#11

投稿記事 by みけCAT » 7年前

ケトン さんが書きました:

コード:

int *pX Y;
という宣言は、int*型のpXとint型のYを宣言したと考えてよいですか?
いいえ。
マクロ定義がなければ、コンパイルエラーになるでしょう。
コンマを追加した

コード:

int *pX, Y;
なら、int*型のpXとint型のYになりますね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ケトン

Re: 関数の引数にポインタを使うときの初歩的な質問

#12

投稿記事 by ケトン » 7年前

>>11 みけCAT氏

おっと、カンマつけ忘れていました。

C6b14

Re: 関数の引数にポインタを使うときの初歩的な質問

#13

投稿記事 by C6b14 » 7年前

お使いの C  コンパイラ では この コード は 正常に動きますか?

コード:

#include <stdio.h>
void swap(int *, int *);//[宣言]
int Global_pX=100, Global_pY =999;
void main(void)
{
	printf("%d:%d\n", Global_pX, Global_pY);
	swap(&Global_pX, &Global_pY);         //[実行]
	printf("%d:%d\n", Global_pX, Global_pY);
}
void swap(int *pX, int *pY) //[定義]
{
	int Temp; Temp = *pX; *pX = *pY; *pY = Temp;
}
100:999
999:100

VC++2015 では コンパイル できます。C ではなく C++  です。C では どうだったか?

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 関数の引数にポインタを使うときの初歩的な質問

#14

投稿記事 by みけCAT » 7年前

C6b14 さんが書きました:C ではなく C++  です。
このコードはVC++ではコンパイルできるとしても、main関数の戻り値の型がintではないのでC++の規格に違反しています。
C言語では処理系定義で許されることがあるかもしれません。
void main()をめぐるどうでもいい話 - Qiita
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

C6b14

Re: 関数の引数にポインタを使うときの初歩的な質問

#15

投稿記事 by C6b14 » 7年前

ありがとうございます。
最近は C と言っても C++ 上 の 例が 多い から こういう 宣言 を 見かけるのですね。

void swap(int *, int *);//[宣言]

最近の C++ の void は int を 返すとみなされる というように 記憶してます。

ただ このような 宣言 は いまは C++  上 で動いているのものは 許されても
C 言語 の 規約では 許されて いるのか  いないのか。 初心者 にとっては この書き方

の方が 迷わない 親切な 書き方 なんだな と思ったものです から 質問しました。

C6b14

Re: 関数の引数にポインタを使うときの初歩的な質問

#16

投稿記事 by C6b14 » 7年前

この ページ は まともな ことが書いてあると 思います。( あいまいな ページ が おおい です )
http://www.cc.kyoto-su.ac.jp/~yamada/ap ... ument.html
「実引数が関数に引き渡されるとき,その実引数自身ではなく,実引数のコピーが引き渡される.」

( たとえ その 実引数 が 「ポインター型」 でも )  [ ややこしい ので いつも 迷う 話 ... ]

閉鎖

“C言語何でも質問掲示板” へ戻る