• ベストアンサー

引数の受け渡し

以下のコード(C言語)を見てください。 int i; int a[3]; void swap(int x, int y); void main() { i= 1; a[0]= 2; a[1]= 1; a[2]=0; swap (i, a[i]); printf("%d %d %d %d\n", i,a[0],a[1],a[2]); swap (a[i], a[i]); printf("%d %d %d \n",a[0],a[1],a[2]); } void swap(int x, int y) { x=2; y=0; x = x+y; y = x-y; x = x-y; } 今取り組んでいる問題が 上のC言語風のコードを実行したとき、 以下の引数の渡し方をすると、このプログラムはどんな値を 返しますか(printfでどんな値を表示するか) a. pass-by-value (値渡し) b. pass-by-result (引数を右から左への順で渡す) c. pass-by-reference (参照渡し) d. pass-by-value-result e. pass-by-name (名前渡し) という問題です。 eのpass-by-nameというのがいまいちよくわからないので 上のコードを例に解説、アドバイスをいただきたいと思い、質問しました。どなたかアドバイスをいただけないでしょうか。 あと、他の4問も自分の答えが合っているか確かめたいので、もしよろしければみていただけないでしょうか。お願いします。 a. 1 2 1 0 / 2 1 0 b. 2 2 0 0 / 2 0 2 c. 0 2 2 0 / 0 2 0 d. 0 2 2 0 / 2 2 0

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

  • ベストアンサー
  • colder
  • ベストアンサー率43% (30/69)
回答No.3

pass-by-nameは#1さんが紹介されているページにも書かれているとおり、 仮引数を実引数の式で置き換えたかのように動作します。 たとえば foo(int a, int b) { b = 1; a = 2; b= 3; } という関数を i = 0; foo(i,x[i])と呼び出したとき foo { x[i] = 1; //ここでは、x[0]の値を変える。 i = 2: x[i] = 3; //直前の行でi=2になるため、ここでは、x[2]の値を変える。 } と書かれているように動作します。

ilnmfay
質問者

お礼

2度も回答していただきほんとにありがとうございます。 pass-by-nameで 0212/012 という結果を得られました。 少しケアレスミスをしていたようです。 ありがとうございました

その他の回答 (2)

  • colder
  • ベストアンサー率43% (30/69)
回答No.2

>pass-by-resultは ... >ただし、y,zからc,dに値を移すときに >y -> c >z -> d >という順に値を移すとはかぎりません。 > >y->d >z->c >と移すこともあります。 >これはコンパイラによって解釈が違うそうです。 そういう意味なのですか? y -> c z -> d この二つをどちらから実行するかが決まっていないという意味ではないでしょうか。 この意味の場合、cとdが同じ変数の場合、結果が異なります。 >ところで、pass-by-nameですが確かにpass-by-referenceと同じになりました。 どのように確認したのでしょうか? Cの関数形マクロは、pass-by-nameで引数を渡します。 その結果は 0 2 1 2 / 0 1 2 になります。

ilnmfay
質問者

補足

回答ありがとうございます。 >pass-by-result つい先日、授業で習ったのですが、 先生は「コンパイラによって右から移したり、左から移したりするから Platformによって返り値が変わってくる。この点でPass-by-resultはportabilityにかける」とおっしゃっていました。実行の仕方が決まっていないというわけではなさそうです。 はじめて聞いた話だったので私にはその先生の話が正しいか判断する能力はなかったです。あくまで「私の先生によれば…」ということです。自分でも調べてみます。 >どのように確認したのでしょうか? すみません。NO.1さんの参考URL中の内容を自分で吟味した結果、 pass-by-nameとpass-by-referenceが同じではないかと 考えたという意味です。 不確かなことを言って申し訳ありません。 しかし、0210/012という結果になるのですか? できればどのようにpass-by-nameが値を渡すか解説をお願いしたいのですが、よろしいですか? もしよければお願いします。

  • hogejo
  • ベストアンサー率42% (11/26)
回答No.1

pass-by-name というのは知りませんでしたが 参考URLで説明されているようなことなんじゃないでしょうか? bとdは分からないのですが、知っていれば教えて欲しいです。 ※C言語の問題ではなく、C言語風のコードで書かれている問題なんですよね? C言語は値渡ししかないので、aは実行すれば分かるでしょう。 cはeと同じ結果になるのでは?C++ならば参照渡しも使えますし、試してみれば良いと思います。(C言語+ポインタでもいいけど)

参考URL:
http://web.sfc.keio.ac.jp/~hattori/prog-theory/main_c6_s2.html#doc1_call-by-name
ilnmfay
質問者

補足

回答ありがとうございました。 a.はCでコードを書いて確認しました。 pass-by-resultは 関数の引数の値を関数の変数に代入するとでも言うのでしょうか。 英語で勉強してるもので、それをうまく訳せずすみません。 例としては、 void f(int y, int z){ y=1; z=2; } という関数において f(c,d) という関数を呼んだとします。 まず、c,dのメモリが確保され、次にy,zのメモリが確保されます。 次に、y,zにそれぞれ1,2が代入されます。 最後に、y,zの値をc,dに移す。 ただし、y,zからc,dに値を移すときに y -> c z -> d という順に値を移すとはかぎりません。 y->d z->c と移すこともあります。 これはコンパイラによって解釈が違うそうです。 引数を左から右に渡すコンパイラであれば f(c,d)を左から読み取って c=y=1 d=z=2 引数を右から左に渡すコンパイラであれば f(c,d)を右から読み取って c=z=1 d=y=2 となります pass-by-value-resultは 上の例を使うと まずpass-by-valueのように メモリcのcopyとしてメモリyをつくる メモリdのcopyとしてメモリzをつくる 関数内のコードを実行し、 コピーセルyの値をコピー元のcに戻す コピーセルzの値をコピー元のdに戻す これがpass-by-value-resultです。 referenceとほとんどかわらないのですが void p(int x, int y) { x++; y++; } int a=1; p(a,a); のようなコードでは pass-by-reference と pass-by-value-resultで別の値になります。 ところで、pass-by-nameですが確かにpass-by-referenceと同じになりました。ご協力ありがとうございます

関連するQ&A