インクリメントとデクリメント

変数の現在の値に対して1を加える、または減らす場合は、インクリメント演算子 ++ と、デクリメント演算子 -- という、特別な演算子が用意されています。これらの演算子は、1つの項しか受け取らない単項演算子に分類されます。これらの演算子は、左または右のどちらの項にも変数を指定できます。右項を指定する場合は、演算子を項よりも前に置くことから前置インクリメント演算子、前置デクリメント演算子などと呼ぶこともあります。

++変数名
--変数名

同じように左項を指定する場合は、演算子を項よりも後に置くことから後置インクリメント演算子、後置デクリメント演算子などと呼びます。

変数名++
変数名--

整数型の変数iが宣言されているものとして、前置インクリメント演算i++の結果はi += 1と同じです。同様に、前置デクリメント演算i--の結果はi -= 1 と同じです。どちらも、指定した変数の現在の値から 1 を加えるか、減らします。このような計算は、何らかの処理の回数を数える場合などで用いられます。インクリメント及びデクリメント演算子に指定する項は、代入演算子と同じように変更可能な値でなければなりません。よって、定数を項として指定した 10++ のような計算はエラーとなります。

サンプル05

#include <stdio.h>

int main(void)
{
    int i = 0;

    i++;
    printf("i = %d\n" , i);

    ++i;
    printf("i = %d\n" , i);

    i--;
    printf("i = %d\n" , i);

    --i;
    printf("i = %d\n" , i);

    return 0;
}

実行結果

サンプル05は、前置と後置、両方のインクリメント演算子及びデクリメント演算子を使って変数の操作し、その結果をprintf()関数で表示しています。インクリメント演算子を実行した後は、変数の値に1が加えられていることが確認できます。このように、変数の現在の値に1を加えることをインクリメントと呼びます。同様にデクリメント演算子を実行した後は、変数の値から1が引かれています。変数の現在の値を 1 減らすことをデクリメントと呼びます。

前置と後置は、変数に対する効果は同じですが、式として評価したときに返す結果が異なります。この部分は少し難しいのですが、インクリメント演算子やデクリメント演算子は、変数の値を変更するだけではなく、値を結果として返しているのです。上記のサンプルでは、その結果を受け取っていないので破棄されていますが、インクリメント演算やデクリメント演算を、他の式の中に組み込むことも可能です。

result = i++;

上記は、i変数に対するインクリメント演算の結果を、変数reusltに代入するというものです。このとき、変数 reusltには何が格納されるのでしょうか。インクリメント演算やデクリメント演算の結果は、前置か後置かで異なります。前置の場合、インクリメントやデクリメントした値を式の結果として返します。しかし、後置演算の場合は、インクリメントやデクリメントする前の変数の値を式の結果として返します。

サンプル06

#include <stdio.h>

int main(void)
{
    int i = 0, result;

    result = i++;
    printf("i = %d, result = %d\n", i, result);

    result = ++i;
    printf("i = %d, result = %d\n", i, result);


    return 0;
}

実行結果

サンプル06は、前置インクリメント演算子と、後置インクリメント演算子が返す結果が異なることを証明しています。実行結果のresult変数の値を見れば、前置と後置によって結果が異なることを確認できます。

最初に0で初期化されたint型の変数iとresultを宣言しています。その後、後置インクリメント演算子i++で変数をインクリメントし、結果をresult変数に代入しています。後置インクリメント演算子は、インクリメントを行う前の値を返すので、i変数の初期値0が返され、その後iの値がインクリメントされます。続いて、前置インクリメント演算子++iで変数をインクリメントしています。前置インクリメント演算子は、インクリメントを行った結果の値を返すので、i変数に1を加えた値が返されます。

最後に

本稿のサンプルの範囲であれば、コードを見れば変数にどのような値が格納されているか分かります。しかし、実践のプログラミングでは、実行時になるまで変数の内容が分からないことが多いでしょう。たとえば、ネットワーク通信で取得したデータや、ファイルから読み込んだデータなども、プログラムで扱うときには変数に保存されます。このような性質のデータは、データを取得するまで、中身が分かりません。それぞれの変数が、どのような性質のデータを保存するのか、プログラマが正しく管理し、予期しない不正な値を操作しないように注意しなければなりません。