インクリメント

出典: フリー百科事典『ウィキペディア(Wikipedia)』
ナビゲーションに移動 検索に移動

インクリメント、増量 (increment) は、一般には増加という意味だが、コンピュータ用語としては、変数の値を1増やす演算のことである[1]

逆に、1減らす演算はデクリメント (decrement) という[2]

概要[編集]

ループや逐次アドレッシングで使用頻度が極めて高いため、プロセッサレベルで専用のインクリメント命令が用意されていることが多い。また、プログラミング言語のレベルでも、インクリメントをするときのための「インクリメント演算子」が用意されていることが多い。さらに、コンパイラのレベルでも、インクリメント演算子に対して最適化してくれる場合が多い。その場合、算術演算子(C言語では「+」)や累算代入演算子(「+=」)を使うよりもインクリメント演算子(「++」)を使った方が、コンパイラがプロセッサのインクリメント命令を使うようなコードを生成してくれて高速になる可能性が高い。

しかし、「加算/減算」という概念とは別に「インクリメント/デクリメント」という概念を扱うのは初心者にとって煩雑になり、プロにとってもバグの元となる場合がある。またマイコンレベルでも必ずしも必須というわけではないため、インクリメント命令を搭載しない場合がある。また、コンパイラの最適化が進んでいた場合、インクリメントを使っても算術演算子を使っても、どちらも同じ(最も速くなる)機械語を生成するので、現代の有名開発環境を使っている場合は、あえてインクリメントを使って処理速度を稼ぐ必要はない。そのため、インクリメントという概念をあえて排除する場合もある。例えば、情報処理技術者試験で用いられる仮想計算機COMET IIの命令セットにはインクリメント命令が存在しない。また、プログラミング言語のPythonにも存在しない。

インクリメント命令は処理が速いので、ソフトウェア工学の未発達な時代は、インクリメントする必要がない時でも便利に使われることがあった。例えばbool型を持たないのでint型を代用に使っているANSI C(C89)において真偽判定を行う場合、int型変数「hoge」が真か偽か(非「0」か「0」か)を判定する際、「if(hoge == 0)」よりも「if(hoge ++)」の方が速い(両の式はいずれも、hogeが「-1」の時に「偽」を返し、hogeが「0」の時に「真」を返す)。しかし、むやみにインクリメント命令を使うと、致命的なバグを引き起こす場合もある。例えば、1985年から1987年にかけて知られる限り6つの過度の被曝事故を引き起こし、少なくとも5人の患者を死亡させたことで知られる放射線療法機器のセラック25においては、「for文」と「インクリメントを使った真偽判定」を組み合わせて使ったことで、hogeが「255」の時に「hoge ++」がオーバーフローして「0」、すなわち初回と256*n回目に偽に判定されるというバグがあったことが原因であった。セラック25は、ハードウェア的な安全チェックが存在せず、ソフトウェアに頼り切っていたが、「hoge ++」が「偽」と判定されると、装置の安全チェックをバイパスし、患者に過度の放射線が照射され、患者が死亡する可能性があった。当初メーカーはこのバグに気づかず、「事故は起こりえない」と回答したことが被害を拡大させた。このように、インクリメントは便利な一方で、インクリメントの便利さが甚大な災害を起こしたという、ソフトウェア工学において有名な事例がある。

C++では、リリース当初よりCと違ってbool型が存在するので、上の式は「if(boolHoge == false)」と表現できて解りやすいが、bool型にインクリメントできてしまうことから、「if(boolHoge ++)」とすることも可能で、セラック25と同様のバグが発生する懸念があった。C++98の時点でbool型に対するインクリメントが非推奨となり、多くの処理系ではbool型にどれだけインクリメントしてもtrueとなるようになっていた。C++17で、インクリメント演算子「++」がbool型に適用できないように定義され、bool型へのインクリメントが正式に削除された。

プロセッサでの扱い[編集]

通常、レジスタに数値を加算するには、1ワード加算命令とレジスタを表し、もう1ワードで加算する数値を表すので、計2ワードが必要だが、インクリメント命令を使えば1ワードで済む。ただし、プロセッサによっては、インクリメント命令は加算命令よりもオペランドの種類が限られる(たとえばアキュムレータのみに可能など)。

アセンブラの中には、1を加算する加算命令をインクリメント命令に最適化するものもある。

高水準言語での扱い[編集]

C言語[3]C++JavaJavaScript[1][2]などでは、インクリメント演算子(増量子)「++」が用意されている。前置インクリメントと後置インクリメントの2種類がある。字句は同じ「++」だが前置演算子として使うか(例: ++x)後置演算子として使うか(例: x++)で意味が違う。オペランドの値が整数の場合は1、ポインタの場合は指し示す対象1個ぶん変わるのはどちらも同じだが、式としての値が、前置の場合はインクリメントした後の値になる(この意味は += 1 と同じ)、後置の場合はインクリメントする前の値になる。

y = ++x;    // y = (x += 1); と同じ
y = x++;    // y = x; x = x + 1; と同じ

C++の演算子オーバーロードでは、通常の記法では前置インクリメントと後置インクリメントを区別できないので、便宜上、後置インクリメントには余分なint型引数を記述して区別する。ただし、古いC++コンパイラはこの後置インクリメントの宣言に対応していないことがある。

T& class T::operator++{ *this += 1; return *this; }                     // 前置インクリメントのオーバーロード
T class T::operator++(int){ T old = *this; *this += 1; return old; }    // 後置インクリメントのオーバーロード

デクリメント演算子「--」も同様である。

ネーミングでの使用[編集]

C++、Notepad++のように、改良版であることを示すためにインクリメント演算子「++」をつけることがある。

脚注[編集]