問題 メインプログラムを実行した後,メインプログラムの変数X,Yの値はいくつになるか。ここで,仮引数Xは値呼出し(call by value),仮引数Yは参照呼出し(call by reference)であるとする。
メインプログラム
X=2;
Y=2;
add(X,Y);
手続 add(X,Y)
X=X+Y;
Y=X+Y;
return;
今日は応用情報技術者試験の平成25年春期第20問および平成28年春期第20問のこの問題を解説します。
なんてことはない問題ですが、うっかり間違えやすい問題です。
この問題のポイントは値呼び出しと参照呼出しです。それではいきましょう。
プログラミング経験がない人向けにかなりかみくだいて説明しています。
この問題ってそもそも何?
この問題が意味わからん!という人のために超かみくだいて説明します。
解き方が分からないだけの人は飛ばしてください。
この問題、プログラミングをやったことのない人にはそもそも「なんじゃこれ」となるかもしれませんね。
プログラミングはコンピュータにどう動いてほしいかを記述します。
その時、プログラミングではたいてい、「大きな流れ」と「小さい流れ」を書きます。
最初から細かいものを書いているとわかりにくいし、ミスも起こりやすいので、「大まかな段取り」を書いてから「細かい段取り」を書きます。
例えば、学校の文化祭のスケジュールを考えてみましょう。
文化祭のスケジュール
12時 軽音楽ライブ
1時 漫才大会
2時 大喜利大会
3時 歌うま選手権
これだけでは、「だいたい」しか分からないので、細かいスケジュールも用意されているはずです。
例えば、漫才大会の細かいスケジュールも用意されているはずです。
漫才大会のスケジュール
1時~1時5分 大会説明
1時5分~1時35分 予選(1組ネタ時間3分)
出演コンビ おにぎりさんかく 東京タイガース はちゃめちゃboy ホワイトペッパーズ
ホットドッグマン トレンディルシファー
1時35分~1時40分 点数発表
1時40分~1時50分 上位3組による決勝
1時50分~1時57分 結果発表 表彰
プログラミングでも「大まかな流れ」と「細かい流れ」を書くということをします。
ここでいうと、メインプログラムの
X=2; (2をXに入れる) ※プログラミングでは基本的に右辺から考えます
Y=2; (2をYに入れる)
add(X,Y); (XとYを使ってaddという関数を実行する)
これがいわゆる「大きな流れ」の部分です。
「関数」というのは何らかの手続きをまとめてセットにしたものです。
プログラミングでは、繰り返し使う手続きなどは、セットにして名前を付けることで、簡単に同じ手続きを行うことができます。ここでは、addという名前をつけています。
(X,Y)の部分は「引数(ひきすう)」と呼ばれるもので、手続きの登場人物を表しています。
add(X,Y)というのは「addという手続きを行います。その際、XとYを使いますよ」という意味です。
「じゃあaddという手続きは具体的に何をするのか」と問われると、以下に書いてあります。いわゆる「細かい流れ」の部分です。
手続 add(X,Y)
X=X+Y;
Y=X+Y;
return;
先ほど書いた通り、式は右辺から考えます。これらの式の意味はこんな感じです。
X=X+Y;(XにYを足したものをXに置き換える)
Y=X+Y;(XにYを足したものをYに置き換える)
return; (計算結果を返す)
値呼び出しと参照呼出し
この問題を解くために必要な知識が「値呼び出し」と「参照呼出し」です。
値呼び出し(値渡し)
値呼び出しというのは、ざっくりいうと元々の変数の値そのものをコピーする渡し方で、関数で計算しても元々の変数は変わらないですよ、というもの。問題を解くだけならこれで十分かと思います。
一応ちょっとだけ詳しい説明をしておきます。

番地は分かりやすくするために適当(というか嘘)なので気にしないでください。
XやYに一番最初に数値が入っており、ここでは100番地と101番地に入っています。
何か関数を実行する際は、新しいメモリ領域に作業用スペースを作るのですが、値呼び出しの場合、元々の変数から値だけ受け取ってそこで計算します。(ここでは258番地と259番地)
当然違う場所で計算しているので、元々の100番地、101番地に入っている変数に影響はありません。
「値だけ」受け取って計算するので「値呼び出し」というわけですね。
参照呼出し
あたかも変数自体を渡しているような呼び出しを参照呼出しといいます。(問題を解くだけならこの説明で十分)
変数そのものがいじられるので、元々の変数の値が変わってしまいますよ、ということです。
ここでも、少しだけ詳しく説明します。(問題が解ければOKな方は飛ばしてくださいね)
厳密にはこの説明は嘘で、参照呼出しは変数のメモリ番地を渡します。
関数を計算するときにメモリ内にスペースを確保する(Xは258番地、Yは259番地に対応)のは変わらないのですが、
そこには「元々の変数のメモリ番地」を渡します。

例えば関数の計算でXを使用する際、まず258番地を見るのですが、「100番地を参照しろ」と書いてあるわけです。だから「参照呼出し」といいます。
そうなると、100番地の変数Xをそのまま計算に使います。計算結果は100番地にそのまま置き換えられます。
その結果、変数の値が計算によって書き換えられるというわけです。
問題解説
問題 メインプログラムを実行した後,メインプログラムの変数X,Yの値はいくつになるか。ここで,仮引数Xは値呼出し(call by value),仮引数Yは参照呼出し(call by reference)であるとする。
メインプログラム
X=2;
Y=2;
add(X,Y);
手続 add(X,Y)
X=X+Y;
Y=X+Y;
return;
まず、Xが値呼び出し、Yが参照呼出しであることを確認しましょう。
X = 2, Y=2なので、
X= 2 + 2 = 4となります。
Xは値呼び出しで元々の変数は2のままなので、関数addの計算をしている間だけX=4になります。
またYは、 Y= X + Y = 4 + 2 = 6 となります。
Yは参照呼出しなので、元々の変数Yの数値が6に書き換えられています。
よって(X, Y) =(2, 6)が答えになります。
まとめ
この問題は値呼び出しと参照呼出しさえ知っていれば簡単です。
値呼び出しの場合、色々計算しているのに値が変わらないというのは不思議な感じがしますね。
今後も情報処理技術者試験の解説を載せていきますので、今後もご覧ください。