インクリメント演算子とデクリメント演算子は、オペランドを1ずつ増減させる単項演算子です。
これらは命令型プログラミング言語でよく見られます。C言語のような言語では、各演算子に2つのバージョン(前置演算子と後置演算子)があり、意味がわずかに異なります。
Bから構文的に派生した言語(Cとその派生言語を含む)では、インクリメント演算子は++、デクリメント演算子はと表記されます--。他のいくつかの言語では、inc(x)とdec(x)関数が使用されます。
インクリメント演算子はオペランドの値を1増やし、デクリメント演算子はオペランドの値を1減らします。オペランドは算術型またはポインタ型のデータ型を持ち、変更可能なデータオブジェクトを参照する必要があります。ポインタの値は、メモリ内で隣接する次の(または前の)要素を指すように、増減されます。
両方のバージョンの演算子をサポートする言語の場合:
インクリメント/デクリメントが式ではない言語(例:Go)では、1つのバージョンのみが必要です(Goの場合は、後置演算子のみ)。
インクリメント/デクリメント演算子はオペランドを変更するため、同じ式内でそのようなオペランドを複数回使用すると、言語によっては未定義の結果が生じる可能性があります。たとえば、C言語[ 1 ]では、のような式ではx - ++x、減算と増分演算をどのような順序で実行すべきかが明確ではありません。このような式は未定義の動作を引き起こすため、避けるべきです。
C のような型付きポインタを持つ言語では、インクリメント演算子はポインタをその型の次の項目に進めます。つまり、ポインタの値をその型のサイズ分だけ増やします。ポインタ (適切な型) が配列内の任意の項目を指している場合、インクリメント (またはデクリメント) すると、ポインタはその配列の「次の」(または「前の」) 項目を指すようになります。したがって、整数へのポインタをインクリメントすると、次の整数を指すようになります (通常はポインタの値が 4 増加します)。[ 2 ] 106 バイトのサイズの構造体へのポインタをインクリメントすると、ポインタの値を 106 だけ増やして、次の構造体を指すようになります。[ 3 ]
以下のC言語のコード断片は、前置インクリメント演算子と後置インクリメント演算子、および前置デクリメント演算子と後置インクリメント演算子と前置デクリメント演算子の違いを示しています。
int x ; int y ;// インクリメント演算子// 前置インクリメント: x を 1 増やし、y に x の値を代入しますx = 1 ; y = ++ x ; // x は 2 になり、y も 2 になります// 後置インクリメント: y に x の値が代入され、その後 x が 1 増加します。x = 1 ; y = x ++ ; // y は 1、x は 2 になります// デクリメント演算子// 事前デクリメント: x を 1 減らし、y に x の値を代入しますx = 1 ; y = -- x ; // x は 0 になり、y も 0 になります// 後置デクリメント: y に x の値が代入され、その後 x が 1 減らされるx = 1 ; y = x -- ; // y は 1、x は 0 になるこれらの演算子を持たない言語では、同等の結果を得るには追加のコード行が必要になります。
# 前置インクリメント: y = ++x x = 1 x = x + 1 # x は 2 になります (Python では "x += 1" と書くことができます) y = x # y も 2 になります# 後置インクリメント: y = x++ x = 1 y = x # y は 1 x = x + 1 # x は 2 になります後置インクリメント演算子は、配列の添え字でよく使用されます。例:
// 配列の要素の合計float sum_elements ( float arr [], int n ) { float sum = 0.0 ; int i = 0 ;while ( i < n ) sum += arr [ i ++ ]; // i を後置インクリメントし、// 配列の n 個の要素を順に処理するreturn sum ; }後置インクリメント演算子はポインタでもよく使用されます。
// ある配列を別の配列にコピーするvoid copy_array ( float * src , float * dst , int n ) { while ( n -- > 0 ) // n からゼロまでカウントダウンするループ* dst ++ = * src ++ ; // 要素 *(src) を *(dst) にコピーし、// 両方のポインタをインクリメントする}これらの例は、 C++、Java、C#などの他のC言語に似た言語でも機能します。
#include <stdio.h> int main () { int c = 2 ; printf ( "%d \n " , c ++ ); // この文は 2 を表示し、その後 c を 1 増やして 3 にします。printf ( "%d" , ++ c ); // この文は c を 1 増やし、その後 c を表示します。return 0 ; }2 4以下のリストは、完全なものではなく、すべてを網羅しているわけではありませんが、インクリメント演算子とデクリメント演算子をサポートする主要なプログラミング言語の一部を示しています。
AppleのSwiftはかつてこれらの演算子をサポートしていましたが、バージョン2.2以降は非推奨となり[ 14 ]、バージョン3.0以降は削除されました[ 15 ] [ 16 ] 。
Pascal、Delphi、Modula-2、およびOberonは、演算子の代わりに関数(inc(x)および)を使用します。Tclはコマンドを使用します。dec(x)incr
この概念は、 1969年頃にケン・トンプソンによってBプログラミング言語で導入されました。[ 17 ]
トンプソンはさらに一歩進んで、インクリメントまたはデクリメントを行う++演算子と--演算子を発明しました。これらの演算子の接頭辞または接尾辞の位置によって、変更がオペランドの値の記録前か後かが決まります。これらはBの初期バージョンには含まれていませんでしたが、開発の過程で登場しました。CとUnixが最初に普及したDEC PDP-11が提供する自動インクリメントおよび自動デクリメントアドレスモードを使用するために作成されたと推測されることがよくあります。しかし、Bが開発された当時はPDP-11が存在しなかったため、これは歴史的に不可能です。ただし、PDP-7には、間接メモリ参照によってセルがインクリメントされるという特性を持つ「自動インクリメント」メモリセルがいくつかありました。この機能がトンプソンにこれらの演算子を思いつかせたのかもしれません。接頭辞と接尾辞の両方に使えるように一般化したのは彼自身です。実際、自動インクリメントセルは演算子の実装に直接使用されたわけではなく、この革新のより強い動機は、++x の変換が x=x+1 の変換よりも小さいという彼の観察だった可能性が高い。
{{cite book}}: CS1 maint: 複数の名前: 著者リスト (リンク)++--