0
0

More than 3 years have passed since last update.

PHP5上級試験/準上級試験の上級合格に挑戦(3) 3章関数中編

Last updated at Posted at 2021-02-16

前回

上級Ⅱ3章関数前編

  • 副作用をもつ関数
  • 関数表記方法・変数との表記方法の違い

スコープ

  • グローバル(つまり関数の外側)スコープ・関数レベルのスコープ
  • マクロで言う、Public/Private
  • 関数内から、外にある変数にアクセスしたいときはglobalを使う
  • ここからの出題は、スコープを使って出力がどうなるかを問う問題が多い

スコープに関する問題

さて、下記は1を出力するか否か?

index.php

function test() {
  $x = 1;
 }
$x = test();
echo $x; 

解答

正解は、「何も出力しない」
なぜなら、 関数内で、$x = 1を出していてもそれを関数の外に出す処理をしていないため
外側の$xには何も値が入らないからである。

正確には、下のように書けば、1が出力される。

index.php

function test() {
  $x = 1;
  return $x;
 }
$x = test();
echo $x; 

つまり、「return」で、$xを外に出せるようになるということ。

スコープに関する問題2

さて、下記は1を出力するか否か?

index.php

function test() {
  global $x;
  echo $x;
 }
$x = 1;
test();

解答

正解は「Yes」
functionは本処理の前でも後ろでもどこにおいてもOK。(今回は前においてる)
ただし、処理の順番は本処理からで、$x=1がはいり、test()をコールする、という順番になる。
関数の外で$xに1が代入され、その後にtest()をコール。
globalがついているので、関数内の$xには1が入る。
それを出力するので1となる。
                ※

こんなふうに出題されるときは、スコープ変換、returnのあるなしによって値が入るかどうかを見る問題が多いです。

 スタティック(静的)変数

  • 関数内の変数は関数の呼び出しが完了したら消える
  • それを防ぐのがstaticキーワード。関数呼び出し後も変数の値を保持する
  • ただし、staticキーワードがついた関数の代入は最初の呼び出しのときだけ

さて、以下の出力は何になるか?
答えを見る前に考えよう (問題以下にちょっと空白入れます)

index.php

function test() {
  static $x = 0;
  $x++;
  echo $x,"\n";
 }
test();
test();
test();

 
 
 
 
 
呼び出されるのは$xだが、1回目は0から1に変化。
staticの場合、その(親)関数の最初の呼び出しのときだけ変数の代入が行われる
そのため2回めに呼び出されたときは、staticで$xは0に初期化されない。
そのため、結果は、下記の通り、



というような文字が出力される。(\nは「改行」。なければ123に)
これが大原則。

問題としては、複数のスタティック変数を用意し、処理結果が何になるかという応用問題が考えられる。
というわけでちょっと作ってみた。

さて、以下の出力は何になるか?
答えを見る前に考えよう。

index.php
static $y = 10;
function test() {
  static $x = 0;
  global $y;
  $x++;
  $y++;
  echo $x."<br>";
  echo $y. "<br>";
 }
test();
test();
test();
echo $x."<br>";
echo $y;

自分で適当にやっててこんな凶悪な、もとい、応用問題作れると思わなかった。
ですがこれは解きがいがあっておもしろい。

まず大原則として、プログラムは上から下へ流れるという性質がある。

したがって、1行目のstatic変数$y=10;は
グローバル・スタティックな変数としてまず認識される。

つぎの行はfunctionなので、とばしていくと、test()が3回ある。
test()を3回繰り返すということ。

では次にfunction内で、test()の中身を。
static変数$xが定義され、$xの値は0。
次に、globalでグローバル変数$yへアクセス可能に。
ここで$yには10が入る。
つぎに$xと$yにそれぞれ1ずつ足す。 それぞれ1と、11。
それらがエコー。
それを2回繰り返す。ただし、staticは最初の1回だけなので、ここは無視される。
そしてそれぞれ2回繰り返されるので2と12,3と13がでる。
つぎにグローバルで、$xをエコーするが、
$xは関数の中だけの変数なので、$xは何も入っていないため空白が出力。
$yはグローバル変数でかつ、関数内にアクセスされ、+3されたので、13が出力

というわけで答えは、

1
11
2
12
3
13
(空白)
13

となる。

記事作成の裏側

上記の問題を実際にコードで書いて実行してみたら、エラーになってしまって、修正をしていたが、
$ははいってる、;もある、なぜだ。。。とドツボにハマった。
結局はコードの前のスペースが半角ではなく全角スペースになっていたから。
Qiitaだとタブがきかないので、スペースで入れるが、時々半角にするの忘れて全角で入れるミスがある。
気をつけたい。
こういうこともあるのだなということで共有。
次回は、値渡しと参照渡し、パラメータのデフォルト値、可変関数、匿名関数、言語構造になる。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0