💨

演算子 加算、代入、実行演算子

2022/11/01に公開

演算子

演算子(Operator: オペレーター)とは、与えられた変数や[1]リテラルに対してあらかじめ決められた処理を行うための記号。例えば 「=」演算子や「+」演算子など。また演算子によって処理される変数、リテラルをオペランドと呼ぶ

<?php
// = は 演算子(オペレーション)
// $operand と "operand" は非演算子(オペランド)
$operand = "operand";
?>

演算子はおおまかに以下の6つに分かれる
(1) 代数演算子 (= 算術演算子)
(2) 代入演算子
(3) 比較演算子
(4) 論理演算子
(5) ビット演算子
(6) その他演算子

演算子 概要
+ 数値の和 5+4 ⇒ 9
- 数値の差 6-4 ⇒ 2
* 数値の積 3*4 ⇒ 12
/ 数値の商 6/2 ⇒ 3
% 数値の余剰 13 % 4 ⇒ 1
** 数値の累乗 2**3 ⇒ 8
++ 前置加算(代入前に加算) $x = 3; $y = ++ $x => $yは4
++ 後置加算(代入後に加算) $x = 3; $y = $x ++ => $yは3
-- 前置減算(代入前に減算) $x = 3; $y = -- $x => $yは2
-- 後置減算(代入後に減算) $x = 3; $y = $x -- => $yは3
= 変数などの代入 $x = 10
+= 左辺と右辺の加算結果を左辺に代入 $x=5 $x+=2⇒ xは7
-= 左辺から右辺を減算結果を左辺に代入 $x=5 $x-=2 ⇒ xは3
*= 左辺と右辺の乗算結果を左辺に代入 $x=5 $x*=2 ⇒ xは10
**= 左辺と右辺の累乗結果を左辺に代入 $x=5 $x*=2 ⇒xは25
/= 左辺を右辺で除算結果を左辺に代入 $x=5 $x/=2 ⇒xは2.5
%= 左辺を右辺で除算結果の余りを左辺に代入 $x=5 $x%=2 ⇒xは1
.= 左辺と右辺の文字結合を左辺に代入 $x='foo' $x .='bar' ⇒xはfoobar
??= 左辺が非NULLならその値、nullなら右辺の値を代入 $x=10 $x??=1 ⇒xは10

文字列混在の演算

代数演算子では数値だけでなく文字列も演算できる

<?phpprint '108' + '15'; //結果:123print '108' + '1.5XYZ'; //結果:109.5print '108' + 'XYZ10'; //結果:108print '108' + '1.5XYZ'; //結果:109.5print '108' + '1.5E1'; //結果:123print '108' + '0b11'; //結果:108print '108' + '010'; //結果:118print '108' + '0x1A'; //結果:108

解説
①通常の足算
②,③,④ 文字列を無視した足算
3の場合文字列が先にきているので後ろの整数は無視される。
⑤は例外で指数表現とみなされる

指数表現とは

以下の形式であらわされるリテラルのこと。
 <仮数部>e<符号><指数部>
以下で元の小数値に変換可能する。
 <仮数部>×10の<符号><指数部>
1.2e3 → 1.2×10の3乗 → 1200.0

⑥,⑦,⑧
2/8/16進数であるが変換されることはなく文字部分を無視した足し算が行われる

加算子(++) 減算子(--)

「++」と「--」は与えられたオペランドに対して1を加算/減算するための演算子。
$X ++ ⇦⇨ $x = $x + 1;
$X -- ⇦⇨ $x = $x - 1;

<?php
    // 前置演算子
    //$xの加算を行った後に$yへの代入を行う
    $x = 10;
    $y = ++ $x;
    echo $x; //結果 11
    echo $y; //結果 11

    //後置演算子
    //$yの代入が終わった後に$xを加算する
    $x = 10;
    $y = $x ++;
    echo $x; //結果 11
    echo $y; //結果 10
?>

マジカルインクリメント

文字列を++を用いて加算すこともできる。
Z以降は次の文字が当て込まれる。
英数字混合の連番数字を作るときに用いられる。

<?php
$i = 'Z';
print ++ $i; //結果: AA
print ++ $i; //結果: AB
print ++ $i; //結果: AC

$j = 'T8';
print ++$j; //結果T9
print ++$j; //結果U0
print ++$j; //結果U1
?>

配列の結合

加算演算子の結合の注意点
加算演算子(+)は配列の加算にも対応している。
しかし、左の配列に存在しないキーの要素を右の配列から取り出し左の配列に追加する特性がある。
要するに同じキーが加算される場合、値の上書きが発生しないのである。通常、配列の結合をするには、「+」演算子ではなくarray_mergeを使うべきである。

<?php
//配列の結合
$array1 = [
    'Apple' => 'red',
    'Orange' => 'Yellow',
    'Melon' => 'Green',
];

//配列の結合
$array2 = [
    'Grape' => 'Purple',
    'Apple' => 'Green',
    'Strawberry' => 'Red',
];
$result = $array1 + $array2;
var_dump($result);
//result
//{ ["Apple"]=> string(3) "red" ["Orange"]=> string(6) "Yellow" ["Melon"]=> string(5) "Green" ["Grape"]=> string(6) "Purple" ["Strawberry"]=> string(3) "Red" }
$result2 = array_merge($array1, $array2);
var_dump($result2);
//{ ["Apple"]=> string(5) "Green" ["Orange"]=> string(6) "Yellow" ["Melon"]=> string(5) "Green" ["Grape"]=> string(6) "Purple" ["Strawberry"]=> string(3) "Red" }
?>

「+」演算子では既出のキーの上書きが発生しておらず、array_merge関数では同じキーの値が上書きされていることが分かる。

代入演算子

参照(リファレンス)をより深く理解する。
変数は値を格納する箱という表現をしたが、厳密には以下の説明が正しい。

値を格納するのはコンピュータ上に用意されたメモリである。
メモリにはそれぞれ連番が割り振られている。
連番を指定してメモリに保存した値を取り出すのは不便であるため、
人間が分かりやすいように名前をつけれるようにした仕組みを変数と呼ぶ。
変数とは値の格納先に対してつけられた名札のようなものである。

「=」演算子で変数を変数に代入する場合は、値による代入が基本となる。
値による代入とは、メモリ上の値を別のアドレスにコピーをすることをいう。
値による代入では代入した変数と代入された変数では別物なので
元の変数が上書きされても影響がない。

<?php
    $x = 1; 
    $y = $x; //$xの値を$yにコピー
    $x = 5; //$xの値を変更
    // echo $y;
?>

がしかし、参照(リファレンスによる代入)はメモリ上のアドレスそのものを引き渡すことをいい、参照元の変更が参照先の値へ影響を受けることになる。

<?php
    $x = 1;
    $y = &$x; //$xのアドレスを$yにコピー
    $x = 5; //$xの値を変更
    echo $y; //結果:5($yも影響を受ける)
?>

参照による代入を行う場合は「=」演算子の後方に
参照を表す「&」演算子を指定する。
複合代入演算子の「&=」と混同しないように注意。

分割代入

分割代入とは、配列/連想配列などを分解し、
配下の要素を個々の変数に代入するための構文です。
これには左辺に変数の数だけ変数を列挙し、全体をブラケットでくくる。

<?php
    $data = ["長男","次男","三男","四男","五男"];
    [$a,$b,$c,$d,$e] = $data;
    print $a; //長男
    print $b; //次男
    print $c; //三男
    print $d; //四男
    print $e; //五男
?>

これによって右辺のリストが個々の要素に分解されて
それぞれ対応する変数a~eに代入される。
※左辺の要素数は、右辺の要素数と等しいもしくは少なくないとエラーが発生するので注意。

<?php
$data = [1,2,3,4];
[$a,$b,$c,$d,$e] = $data;
//$eに入れるデータがないため undefined array key4 のエラーが発生

$data = [1,2,3,4,5];
[$a,$b,$c] = $data;
//4,5は無視されて$aに1,$bに2,$cに3が代入される。
?>

一部の要素を切り捨てる
分割代入で途中の要素を無視するのであれば「インデックス値 ⇛ 変数 」の形式で特定の要素だけを分割代入することも可能。

<?php
$data = [1,2,3,4,5];
[1 => $a, 4 => $b] = $data;
echo $a; //結果2
echo $b; //結果5
?>

これを応用すると連想配列でも同様のことができる。

<?php
$map = ['title' => 'PHP学び直し', 'impression' => '楽しい'];
['title' => $title, 'impression' => $impression] = $map;
echo $impression; // 楽しい
?>

入れ子の配列を分割することもできる

<?php
$data = [1,2,[33,34,35]];
[$a,$b,$c] = $data;
print_r($a); //1
print_r($b); //2
print_r($c); //Array ( [0] => 33 [1] => 34 [2] => 35 )

[$x,$y,[$z1,$z2,$z3]] = $data;
print $x; //1
print $y; //2
print $z1; //33
print $z2; //34
print $z3; //35
?>

単に変数を列挙した場合には対応する変数に入れ子の配列がそのまま代入される。
入れ子の配列も展開したいならば代入先もブラケットで入れ子にしてあげる。

実行演算子

実行演算子 (``)はバッククォートで囲ったブロックをシェルコマンドとして実行。

<?php
$result = `dir`; // dirコマンドを実行
print mb_convert_encording($result,'YTF-8','SJIS');
?>

実行結果
ドライブ C のボリューム ラベルは Windows です ボリューム シリアル番号は BA8E-C756 です C:\xampp\htdocs\php のディレクトリ 2022/11/04 12:24
. 2022/11/04 12:24
.. 2022/11/08 11:30 109 index.php 2022/11/04 12:24 5,799 index.php_bk 2 個のファイル 5,908 バイト 2 個のディレクトリ 51,707,793,408 バイトの空き領域

脚注
  1. ソースコードの中に直接書きこんである文字や数字など 「直値(チョクチ)=リテラル」 ↩︎

Discussion