インクリメントインクリメント (英: increment) は、一般には増加・増量・増分・増大という意味だが、コンピュータ用語としては、変数の値を1増やす演算のことである[1]。 逆に、1減らす演算はデクリメント (英: decrement) という[2]。 概要インクリメント操作はループにおけるカウンタの増減や、逐次アドレッシングなどで使用頻度が極めて高いため、プロセッサレベルで専用の命令が用意されていることが多い。また、プログラミング言語のレベルでも、インクリメントをするときのための「インクリメント演算子」が用意されていることが多い。さらに、コンパイラのレベルでも、インクリメント演算子に対して最適化してくれる場合が多い。その場合、算術演算子(C言語では しかし、「加算/減算」という概念とは別に「インクリメント/デクリメント」という概念を扱うのは初心者にとって煩雑になり、ある程度慣れたプログラマであっても演算子の評価順序を見誤るとバグの元となる場合がある[注釈 1]。またマイコンレベルでも必須というわけではないため、インクリメント命令を搭載しない場合がある。また、コンパイラの最適化が進んでいた場合、インクリメントを使っても算術演算子を使っても、どちらも同じ(最も速くなる)機械語を生成するので、現代の主要な開発環境およびコンパイラを使っている場合は、あえてインクリメントを使って処理速度を稼ぐ必要はない。そのため、インクリメントという概念をあえて排除する場合もある。例えば、情報処理技術者試験で用いられる仮想計算機COMET IIの命令セットにはインクリメント命令が存在しない。プログラミング言語のPascalにはインクリメント演算子がないが、Object Pascal(Delphi)には なお、PythonやVisual Basic .NETにはインクリメント演算子は存在しないが、 プロセッサでの扱い通常、レジスタに数値を加算するには、1ワードで加算命令とレジスタを表し、もう1ワードで加算する数値を表すので、計2ワードが必要だが、インクリメント命令を使えば1ワードで済む。ただし、プロセッサによっては、インクリメント命令は加算命令よりもオペランドの種類が限られる(たとえばアキュムレータのみに可能など)。 アセンブラの中には、1を加算する加算命令をインクリメント命令に最適化するものもある。 Windows APIではスレッドセーフなアトミック操作のための関数として、 高水準言語での扱いC言語[10]、C++、C#、Java、JavaScript[1][2]などでは、インクリメント(増分)演算子「 y = ++x; // y = (x += 1); と同じ
y = x++; // y = x; x = x + 1; と同じ
C++の演算子オーバーロードでは、通常の記法では前置インクリメントと後置インクリメントを区別できないので、便宜上、後置インクリメントには余分な T& class T::operator++() { *this += 1; return *this; } // 前置インクリメントのオーバーロード
T class T::operator++(int) { T old = *this; *this += 1; return old; } // 後置インクリメントのオーバーロード
デクリメント演算子「 しかし、前置と後置という些細な違いでプログラムの挙動が変わるので、可読性の低下やバグの要因となることが多い。Swiftには当初C言語と類似のインクリメント演算子とデクリメント演算子があったが、可読性の優先や言語学習コスト低減などの観点から、Swift 3.0で廃止(削除)された[12]。 真理値とインクリメントアセンブリ言語(アセンブラ)や初期のプログラミング言語は、真理値を表す専用のデータ型(ブーリアン型)を持たず、整数型で代用することが多かった。整数で代用する場合、通例0を偽 (false) として扱い、また0以外をすべて真 (true) として扱う。C言語はこの仕様を引きずっており、論理演算の結果は基本整数型 このようにブーリアン型として整数型を使用すると、本来インクリメントで記述する必要がない(インクリメントで記述してはいけない)コードにも、誤って使われてしまうことがある。例えば真理値を表すフラグ変数の値を偽から真に変更する場合、通常は変数に何らかの固定値(一般的な代表値としては1)を代入する。しかし、整数型では0をインクリメントすると1になることから、代入ではなくインクリメントでも偽から真に変更することができてしまう。 ソフトウェア工学や安全工学の未発達な時代に、不適切なインクリメント命令の使用が致命的なバグを生み、重篤な事故を引き起こした事例として、放射線療法機器のセラック25が挙げられる。セラック25は1985年から1987年にかけて知られる限り6つの重大な被曝事故を引き起こし、少なくとも5人の患者を死亡させた。事故原因には複数の要因があるが、まずセラック25は従来機に搭載されていた電気機械式の安全保護装置(ハードウェア・インターロック)を取り除き、(当時はハードウェア制御よりも安全だと思われていた)ソフトウェア制御に置き換えてしまっていた。装置を制御するコンピュータPDP-11のオペレーティングシステム[注釈 3]において、安全性を確保するためのソフトウェア・インターロックのひとつに使われていた、Class3と呼ばれるフラグ変数は、値が0以外の場合、装置に何らかの不一致があり、放射線治療を続行できないことを意味するものだった。セットアップテストのルーチンを通過するたびにClass3変数の値がインクリメントされるコードになっていたが、このClass3変数は1バイト(1オクテット)であり、十進数で0から255までの数値しか表現できない。値が255のときにインクリメントしてしまうと、オーバーフローが発生して0に戻ってしまう。この異常動作はセットアップテストを256回通過するたびに発生する。つまり、本来はフラグが真でなければならない場面で偽となり、障害が正しく検出されないというバグが存在していた[14]。これにより、装置の安全チェックがバイパスされてしまい、患者に過度の放射線が照射され、患者が死亡する可能性があった。当初セラック25のメーカーはこのバグに気づかず、「事故は起こりえない」と回答したことが被害を拡大させた。 なお、Cとは異なり、C++には、ISO規格として標準化される前にリリースされた段階で JavaやC#のような後発の安全な言語では、ブーリアン型へのインクリメントは登場当初から禁止されている。 ネーミングでの使用C++、Notepad++のように、改良版であることを示すためにインクリメント演算子「++」をつけることがある。 「increment」の形容詞形「incremental」は、インクリメンタルサーチやインクリメンタルビルド(増分ビルド)といったソフトウェア機能の名称に使われることもある。 脚注注釈出典
関連項目 |