第6章 ユーザー定義関数 / 第1回 模擬試験
次のコードの実行結果として正しいものはどれか。 ```php $val = 'a'; $val = 'b'; print ('【A】' . $val); function func($val = 'c') { $val = 'd'; print ('【B】' . $val); global $val; print ('【C】' . $val); $val = 'e'; print ('【D】' . $val); $val = 'f'; } $val = 'g'; func($val); print ('【E】' . $val); ```
【A】b 【B】c 【C】g 【D】e 【E】g
【A】b 【B】c 【C】b 【D】e 【E】f
【A】b 【B】c 【C】b 【D】e 【E】g
【A】b 【B】d 【C】g 【D】e 【E】f
正解
解説
グローバルスコープとローカル(関数内)スコープ、および`global`キーワードの挙動を問う設問です。
・トップレベルで`$val = 'a';` → `$val = 'b';`としているため、【A】の時点のグローバル変数`$val`は`'b'`です。
・`$val = 'g';`でグローバル変数`$val`が`'g'`に更新されてから`func($val)`が呼び出されるため、関数の引数には値渡しで`'g'`が渡ります(仮引数のデフォルト値`'c'`は使われません)。関数内で`$val = 'd';`とするのは、この「渡された値のローカルコピー」への代入のため、グローバル変数には影響しません。よって【B】は`'d'`。
・続く`global $val;`は、これ以降のこの関数内での`$val`という変数名を、ローカルの引数変数ではなくグローバル変数`$val`への参照に切り替える宣言です。この時点のグローバル`$val`は(ローカルでの変更の影響を受けていないため)`'g'`のままなので、【C】は`'g'`。
・`global`宣言後の`$val = 'e';`はグローバル変数そのものを書き換えるため、【D】は`'e'`、この時点でグローバル`$val`も`'e'`になります。
・さらに`$val = 'f';`でグローバル変数は`'f'`になります。
・関数を抜けた後、トップレベルで【E】として出力される`$val`は、`global`経由で書き換えられたグローバル変数そのものなので`'f'`です。
実機で確認:
```
$val = 'g';
func($val);
echo $val; // f
```
ポイントは、「`global`宣言より前のローカルな`$val`への代入(【B】)」と「`global`宣言後の`$val`への代入(【D】【E】)」とでは、書き換える対象がまったく別の変数になるという点です。
(参照: 独習PHP 第4版 第6章 関数 6.3節 引数の渡し方(値渡し・参照渡し))