C言語の基本|インクリメントとデクリメント

++と--で値を1だけスマートに更新。前置と後置の違いを理解して、表示結果の迷いをなくそう。

C言語では、変数の値を1だけ増やしたり、1だけ減らしたりする処理がよく登場します。

たとえば、次のような値の更新です。

  • ループの実行回数を1増やす
  • 配列の添字を次へ進める
  • 試行回数を1増やす
  • 残り回数を1減らす
  • ページ番号を1つ進める
  • エレベーターの階数を1つ上げる

変数nの値を1増やす処理は、次のように書けます。

n = n + 1;

複合代入演算子を使うと、次のように短くできます。

n += 1;

さらに、C言語には1だけ増やすためのインクリメント演算子++が用意されています。

n++;

値を1だけ減らす場合は、デクリメント演算子--を使用します。

n--;

++と--には、変数の前に付ける前置と、変数の後ろに付ける後置があります。

++n
n++

どちらもnを1増やしますが、式の中で使った場合は、その場で使用される値が異なります。この違いを理解しておくと、代入やprintfと組み合わせたときの結果を正しく判断できるようになります。

インクリメント演算子とは

インクリメント演算子++は、変数の値を1増やす演算子です。

変数nを1増やす処理には、次の3つの書き方があります。

書き方意味
n = n + 1;nの現在値に1を加え、結果をnへ保存する
n += 1;複合代入演算子でnを1増やす
n++;または++n;インクリメント演算子でnを1増やす

たとえば、nの値が5の場合は、どの書き方でも最終的なnは6になります。

更新前:nは5
更新後:nは6

処理の目的は同じですが、++を使うと、1増やす処理であることを短く表現できます。

デクリメント演算子とは

デクリメント演算子--は、変数の値を1減らす演算子です。

変数nを1減らす処理にも、次の3つの書き方があります。

書き方意味
n = n - 1;nの現在値から1を引き、結果をnへ保存する
n -= 1;複合代入演算子でnを1減らす
n--;または--n;デクリメント演算子でnを1減らす

nの値が5の場合、どの書き方でも最終的なnは4になります。

更新前:nは5
更新後:nは4

図1:1だけ増やす処理と1だけ減らす処理

この図から分かること

インクリメント演算子++は、変数の現在値を1増やします。デクリメント演算子--は、変数の現在値を1減らします。

n = n + 1;、n += 1;、n++;は、nを1増やすという目的では同じです。

同様に、n = n - 1;、n -= 1;、n--;は、nを1減らします。

++と--は変数を更新する

++と--は、計算結果を表示するだけではなく、対象となる変数の値を実際に変更します。

int count = 5;

count++;

count++を実行すると、countの値は6になります。

実行前:countは5
実行後:countは6

次のデクリメントでは、countの値が1減ります。

count--;
行前:countは6
実行後:countは5

変数の値そのものが更新される点が重要です。

前置と後置の2つの書き方

インクリメント演算子とデクリメント演算子には、前置と後置があります。

種類インクリメントデクリメント
前置++n--n
後置n++n--

前置では、演算子を変数の前に書きます。

++n;
--n;

後置では、演算子を変数の後ろに書きます。

n++;
n--;

これらを単独の文として使う場合、前置でも後置でも、最終的な変数の値は同じです。

++n;
n++;

どちらもnを1増やします。

しかし、代入や関数呼び出しなど、ほかの処理を含む式の中で使うと、その場で使われる値が異なります。

前置は更新してから値を使う

前置インクリメント++nは、最初にnの値を1増やし、更新後の値を式の値として使います。

result = ++n;

nが5の場合、次の順番で処理されます。

1. nを5から6へ増やす
2. 更新後の6を式の値として使う
3. resultへ6を代入する

処理後の値は次のとおりです。

nは6
resultも6

前置デクリメント--nも同じ考え方です。

result = --n;

nが5の場合は、先にnを4へ減らし、その4をresultへ代入します。

nは4
resultも4

後置は値を使ってから更新する

後置インクリメントn++は、更新前のnの値を式の値として使い、そのあとでnを1増やします。

result = n++;

nが5の場合は、次の順番で処理されます。

1. 更新前のnの値5を式の値として使う
2. resultへ5を代入する
3. nを5から6へ増やす

処理後の値は次のとおりです。

nは6
resultは5

後置デクリメントn--も同じです。

result = n--;

nが5の場合は、5をresultへ代入してから、nを4へ減らします。

nは4
resultは5

nが5の場合の前置と後置の違い

書き方その場で使われる値実行後のn
++n66
n++56
--n44
n--54

前置では更新後の値が使われます。後置では更新前の値が使われます。

最終的にnが1増える、または1減る点は同じですが、別の変数へ代入される値に違いが出ます。

図2:前置と後置で使われる値の違い

この図から分かること

result = ++n;では、nを先に6へ更新してから、その6をresultへ代入します。そのため、nとresultはどちらも6になります。

result = n++;では、更新前の5をresultへ代入したあと、nを6へ更新します。そのため、nは6、resultは5になります。

前置と後置の違いは、変数が最終的に更新されるかどうかではなく、式の中で更新前と更新後のどちらの値を使うかです。

エレベーターの階数で前置と後置の違いを確認するプログラム

ファイル名:6_6_1.c

#include <stdio.h>

int main(void)
{
    int floor = 4;
    int displayed_floor;

    /* 前置:先に階数を増やし、その値を代入する */
    displayed_floor = ++floor;

    printf("前置インクリメント:表示階=%d、現在階=%d\n",
           displayed_floor, floor);

    floor = 4;  /* 確認のため元の値へ戻す */

    /* 後置:現在の値を代入し、そのあと階数を増やす */
    displayed_floor = floor++;

    printf("後置インクリメント:表示階=%d、現在階=%d\n",
           displayed_floor, floor);

    return 0;
}
実行結果の例
前置インクリメント:表示階=5、現在階=5
後置インクリメント:表示階=4、現在階=5

前置と後置を確認するプログラムの解説

最初に、変数floorを4で初期化しています。

int floor = 4;

前置インクリメントでは、次の代入を実行しています。

displayed_floor = ++floor;

++がfloorの前にあるため、floorを先に4から5へ増やします。その更新後の5がdisplayed_floorへ代入されます。

更新前のfloor:4
++floorで更新:5
displayed_floorへ代入する値:5

そのため、floorとdisplayed_floorはどちらも5です。

後置の動きを同じ初期値で確認するため、floorを4へ戻しています。

floor = 4;

続いて、後置インクリメントを実行します。

displayed_floor = floor++;

floor++では、更新前の値4が先にdisplayed_floorへ代入されます。そのあとでfloorが5へ増えます。

更新前のfloor:4
displayed_floorへ代入する値:4
更新後のfloor:5

そのため、displayed_floorは4、floorは5になります。

printfは変数の値を変更しない

printfは、指定された値を画面へ表示する関数です。変数をprintfへ渡しても、その変数の値は変わりません。

int count = 5;

printf("%d\n", count);

このprintfを実行しても、countの値は5のままです。

表示される値:5
表示後のcount:5

printfはcountの値を読み取って表示しているだけです。

printfの引数に++や--を書いた場合

printfの引数に++や--を含めると、対象の変数は更新されます。

printf("%d\n", ++count);

この場合、countを変更しているのはprintfではなく、前置インクリメント++です。

countが5の場合、先に6へ更新され、その6がprintfによって表示されます。

表示される値:6
表示後のcount:6

後置インクリメントの場合は、更新前の値がprintfへ渡されます。

printf("%d\n", count++);

countが5の場合、画面には5が表示されますが、文の実行後にはcountが6になります。

表示される値:5
表示後のcount:6
書き方表示される値表示後のcount
printf("%d\n", count);55
printf("%d\n", ++count);66
printf("%d\n", count++);56

実践問題:前置と後置を使い分けよう

次のプログラムの空欄①と②へ式を入れ、指定された実行結果になるようにしてください。

最初の変数pre_valueとpost_valueは、どちらも4です。

#include <stdio.h>

int main(void)
{
    int result;
    int pre_value = 4;
    int post_value = 4;

    result = ①;

    printf("pre_value: %d\tresult: %d\n",
           pre_value, result);

    result = ②;

    printf("post_value: %d\tresult: %d\n",
           post_value, result);

    return 0;
}

実行結果は次のとおりです。

pre_value: 5	result: 5
post_value: 5	result: 4

最初の代入では、pre_valueを5へ増やしたあと、その5をresultへ代入する必要があります。

2つ目の代入では、更新前のpost_valueである4をresultへ代入し、そのあとpost_valueを5へ増やす必要があります。

したがって、空欄へ入る式は次のとおりです。

  • ①は++pre_value
  • ②はpost_value++
前置と後置を使って指定された結果を表示するプログラム

ファイル名:6_6_2.c

#include <stdio.h>

int main(void)
{
    int result;
    int pre_value = 4;
    int post_value = 4;

    /* 先にpre_valueを増やし、その値をresultへ代入する */
    result = ++pre_value;

    printf("pre_value: %d\tresult: %d\n",
           pre_value, result);

    /* 更新前の値をresultへ代入し、そのあと増やす */
    result = post_value++;

    printf("post_value: %d\tresult: %d\n",
           post_value, result);

    return 0;
}
実行結果の例
pre_value: 5	result: 5
post_value: 5	result: 4

実践問題の解説

最初の代入では、前置インクリメントを使用しています。

result = ++pre_value;

pre_valueの初期値は4です。++pre_valueによって、先に5へ更新されます。その更新後の5がresultへ代入されます。

pre_value:4から5へ更新
result:5

2つ目の代入では、後置インクリメントを使用しています。

result = post_value++;

post_valueの初期値は4です。後置では更新前の4が先にresultへ代入され、そのあとpost_valueが5へ更新されます。

result:4
post_value:4から5へ更新

どちらも変数は最終的に5になりますが、resultへ代入される値が異なります。

\tは表示位置をそろえるタブ

printfの書式文字列で使っている\tは、水平タブを表すエスケープシーケンスです。

printf("pre_value: %d\tresult: %d\n",
       pre_value, result);

\tを使うと、次の表示項目まで一定の区切りを入れられます。

pre_value: 5	result: 5

\tは表示を整えるための記号であり、pre_valueやresultの値を変更するものではありません。

表示するだけの処理と更新する処理

式の計算結果をprintfで表示するだけでは、計算に使った変数の値は変わりません。

printf("%d\n", a + b);

この文ではa + bを計算し、その結果を表示します。aとbの値はそのままです。

計算結果をあとから使いたい場合は、変数へ代入して保存します。

sum = a + b;

変数そのものを更新したい場合は、代入、複合代入、インクリメントなどを使います。

a = a + 1;
b += 1;
sum++;
書き方計算結果の表示変数の更新
printf("%d\n", a + b);行うaとbは変化しない
sum = a + b;行わないsumへ結果を保存する
a = a + 1;行わないaを1増やす
b += 1;行わないbを1増やす
sum++;行わないsumを1増やす
表示・代入・複合代入・インクリメントの違いを確認するプログラム

ファイル名:6_6_3.c

#include <stdio.h>

int main(void)
{
    int left = 6;
    int right = 8;
    int total;

    /* 計算結果を表示するだけ */
    printf("表示だけ:left + right = %d\n", left + right);
    printf("表示後:left = %d、right = %d\n", left, right);

    /* 計算結果を変数へ保存する */
    total = left + right;
    printf("totalへ保存した値 = %d\n", total);

    /* 代入を使ってleftを1増やす */
    left = left + 1;
    printf("代入で更新後:left = %d\n", left);

    /* 複合代入を使ってrightを1増やす */
    right += 1;
    printf("複合代入で更新後:right = %d\n", right);

    /* インクリメントを使ってtotalを1増やす */
    total++;
    printf("インクリメント後:total = %d\n", total);

    return 0;
}
実行結果の例
表示だけ:left + right = 14
表示後:left = 6、right = 8
totalへ保存した値 = 14
代入で更新後:left = 7
複合代入で更新後:right = 9
インクリメント後:total = 15

表示と更新の違いを確認するプログラムの解説

最初のprintfでは、left + rightの計算結果を表示しています。

printf("表示だけ:left + right = %d\n", left + right);

6 + 8の結果である14が表示されますが、leftとrightは変更されません。

leftは6のまま
rightは8のまま

続いて、計算結果をtotalへ保存しています。

total = left + right;

この代入によって、totalには14が保存されます。leftとrightの値は変わりません。

leftは、通常の代入で1増やしています。

left = left + 1;

rightは、複合代入によって1増やしています。

right += 1;

totalは、インクリメント演算子を使って1増やしています。

total++;

3つの書き方は異なりますが、いずれも対象の変数を1増やす処理です。

図3:表示と値の更新は別の処理

この図から分かること

printfでleft + rightを表示しても、leftとrightの値は変化しません。printfは計算結果を受け取り、画面へ表示しているだけです。

変数を更新するには、代入、複合代入、インクリメント、デクリメントなどの処理が必要です。

printfの引数に++や--を書いた場合は、printfが変数を変更しているのではなく、++や--によって変数が更新されています。

前置と後置を単独で使う場合

次のように、インクリメントだけを1つの文として実行する場合を考えてみましょう。

++count;
count++;

どちらもcountを1増やします。ほかの変数への代入や、関数の引数として使っていないため、更新前と更新後のどちらを式の値として使うかは結果に影響しません。

デクリメントも同じです。

--count;
count--;

どちらもcountを1減らします。

単独の文では前置と後置の結果が同じなので、ループのカウンタ更新などでは後置のi++がよく使われます。

読みやすさを優先した書き方

前置と後置を式の中で使うと、処理を短く書けます。

result = count++;

ただし、慣れていないうちは、値を使う処理と更新処理を分けると分かりやすくなります。

result = count;
count++;

この2行は、更新前のcountをresultへ代入し、そのあとcountを1増やします。

表示と更新も、次のように分けられます。

count++;
printf("%d\n", count);

この書き方なら、countを先に増やしてから表示することが明確です。

前置と後置を読み取るときは、次の点を確認しましょう。

  • ++nと--nは、先に変数を更新してから値を使う
  • n++とn--は、更新前の値を使ってから変数を更新する
  • 単独の文なら、前置と後置で最終的な変数の値は同じ
  • printfだけでは変数の値は変わらない
  • printfの引数に++や--があれば、その演算子によって値が変わる
  • 処理が分かりにくい場合は、値を使う文と更新する文を分ける