コンピュータプログラミングにおいて、演算子はプログラミング言語内で定義される構成要素であり、一般的には関数のように動作しますが、構文的または意味的に異なります。
一般的な単純な例としては、算術演算( を使用した加算など+)、比較( を使用した「より大きい」など>)、論理演算(一部の言語でANDも記述されるなど&&)が挙げられます。より複雑な例としては、代入(通常は=または:=)、レコードまたはオブジェクト内のフィールドアクセス(通常は)、スコープ解決演算子(多くの場合または)などがあります。言語では通常、組み込み演算子のセットが定義されており、場合によっては、ユーザーが既存の演算子に新しい意味を追加したり、まったく新しい演算子を定義したりすることもできます。
.::.
構文
構文的には、演算子は通常、関数と対照的です。ほとんどの言語では、関数は、固定の優先順位と結合性を持つ特別な形式のプレフィックス演算子と見なすことができます。多くの場合、括弧が必須です (例Func(a): (または(Func a)Lisp ) )。ほとんどの言語はプログラマ定義の関数をサポートしていますが、プレフィックス表記法と複数の優先順位レベルがない限り、プログラマ定義の演算子をサポートしていると主張することはできません。意味的には、演算子は、異なる呼び出し表記法と限られた数のパラメーター (通常は 1 または 2) を持つ特別な形式の関数と見なすことができます。
演算子のオペランドに対する位置は、接頭辞 、中置、または後置 のいずれかであり、演算子を含む式の構文は、そのアリティ(オペランドの数)、優先順位、および(該当する場合)結合性によって決まります。ほとんどのプログラミング言語は、二項演算子といくつかの単項演算子 をサポートしていますが、いくつかの言語では、より多くのオペランドをサポートしています。たとえば、C 言語の?:演算子は三項演算子です。単項マイナス などの接頭辞単項演算子と、ポストインクリメント-xなどの接尾辞単項演算子があり、二項演算は またはなどの中置です。アリティの高い中置演算には、追加の記号が必要です。たとえば、 C 言語の三項演算子?: は – と記述されます。これは唯一の一般的な例であるため、三項演算子と呼ばれることがよくあります。ただし、接頭辞と接尾辞の演算は、 などの任意のアリティをサポートできます。
x++x + yx = ya ? b : c1 2 3 4 +
時々[1] [2]言語の一部は、言語の記述や実装を簡素化するために、「matchfix」演算子または「circumfix」演算子[3] [4]として記述されることがあります。circumfix 演算子は、オペランドを囲む 2 つ以上の部分で構成されます。circumfix 演算子は最も優先順位が高く、その内容が評価され、その結果の値が周囲の式で使用されます。最もよく知られている circumfix 演算子は、上記の括弧で、式のどの部分を他の部分よりも先に評価するかを示すために使用されます。物理学からの別の例としては、ディラックのブラケット表記の内積表記があります。circumfix 演算子は、多数のオペランドまたは可変数のオペランドを含む演算を表すのに特に便利です。
言語の仕様では、サポートされる演算子の構文が指定されますが、プログラマ定義の演算子をサポートするPrologなどの言語では、構文をプログラマが定義する必要があります。
セマンティクス
演算子のセマンティクスは、特に値、評価戦略、および引数の受け渡しモード (ブール値の短絡など) によって異なります。簡単に言うと、演算子を含む式は何らかの方法で評価され、結果の値は単なる値 (右辺値) の場合もあれば、代入可能なオブジェクト (左辺値) の場合もあります。
単純なケースでは、これは通常の関数呼び出しと同じです。たとえば、加算はx + y一般に関数呼び出しadd(x, y)と との小なり比較x < yに相当しますlt(x, y)。つまり、引数は通常の方法で評価され、何らかの関数が評価され、結果が値として返されます。ただし、セマンティクスは大幅に異なる場合があります。たとえば、代入ではa = bターゲットはa評価されませんが、代わりにその場所(アドレス) が の値を格納するために使用されます。これは、 call-by-referencebセマンティクスに対応します。さらに、代入はステートメント (値なし) の場合もあれば、値自体は r-value (単なる値) または l-value (代入可能) のいずれかである式 (値) の場合もあります。別の例として、スコープ解決演算子 :: と要素アクセス演算子 . ( または の場合)は、値ではなく名前に対して操作され、基本的には名前呼び出しセマンティクスであり、値は名前です。
Foo::Bara.b
演算子のオペランドとしての l-value の使用は、単項の増分演算子と減分演算子で特に顕著です。たとえば、C では、次のステートメントは正当かつ明確に定義されており、配列のインデックス付けによって l-value が返されるという事実に依存しています。
x = ++ a [ i ];
重要な用途は、左結合二項演算子が左引数を変更し(または副作用を生成し)、その引数を左辺値として評価する場合です。[a]これにより、元の引数にすべて影響を与える演算子のシーケンスが可能になり、メソッドカスケードに似た流れるようなインターフェースが可能になります。一般的な例は、C++ライブラリの演算子で、次のように流れるような出力が可能になります。
<<iostream
cout << "Hello" << " " << "world!" << endl ;
ユーザー定義演算子
言語には、固定数の組み込み演算子(例:CおよびC++、PHPの+、-、*、<、<=、!、=など)が含まれている場合もあれば、プログラマが定義した演算子の作成を許可している場合もあります(例:Prolog、[5] Seed7、[6] F#、OCaml、Haskell )。プログラミング言語によっては、演算子記号を+や:=などの特殊文字に制限しているものもあれば、次のような名前も許可しているものもあります(例:Pascal)。
div
ほとんどの言語には組み込みの演算子セットがありますが、構文解析が著しく複雑になるため、ユーザー定義の演算子は許可されていません。[b]多くの言語では、組み込み型にのみ演算子を使用できますが、既存の演算子をユーザー定義型に使用できる言語もあります。これは、演算子のオーバーロードとして知られています。ただし、一部の言語では、コンパイル時または実行時に新しい演算子を定義できます。これには、メタプログラミング(別の言語で演算子を指定する)や言語自体が含まれる場合があります。新しい演算子の定義、特に実行時定義では、言語の構文がチューリング完全である可能性があるため、プログラムの正しい静的分析が不可能になることがよくあります。そのため、構文ツリーの構築でさえ、不可能な停止問題を解決する必要がある場合があります。これは、たとえばPerlやLispの一部の方言で発生します。
例
関数と構文的に異なる一般的な例としては、関係演算子(「より大きい」を表す「>」など)が挙げられます。関係演算子の名前は、多くの場合、言語の関数識別子セットの範囲外にあり、関数呼び出しの言語構文とは異なる構文で呼び出されます。関数として、「より大きい」は、通常、gtまたはなどの識別子で名前が付けられgreater_than、関数として呼び出されます( gt(x, y))。代わりに、この演算では、特殊文字(字句解析>中に個別にトークン化されます)と中置表記法( )が使用されます。
x > y
意味的に異なる一般的な例 (引数の受け渡しモードによる) は、ブール演算です。ブール演算は、短絡評価を特徴とすることがよくあります。たとえば、厳密な値渡し関数を持つ言語では、前の引数が偽でない場合にのみ後の引数を評価する短絡結合 (X AND Y) があります。これは、if/then/else と同様に動作します。
あまり一般的ではない演算子は次のとおりです。
- カンマ演算子:
e, f - 逆参照演算子:
*pおよびアドレス演算子:&x - ?:または三項演算子:
number = spell_out_numbers ? "forty-two" : 42- エルヴィスオペレーター:
x ?: y
- エルヴィスオペレーター:
- ヌル合体演算子:
x ?? y - 宇宙船演算子(3者間比較用):
x <=> y - 複合演算子は、 2 つ以上のアトミック操作を1 つに組み合わせて、式を簡略化したり、基盤となるハードウェア実装に応じてコンパイラの最適化を容易にしたり、速度やサイズのパフォーマンスを改善したりします。例としては、C/C++ の複合代入演算子 (拡張代入とも呼ばれます) のセットがあります: 、、
+=、-=、*=、/=、%=、<<=、>>=、&=、^=同様|=に、一部のデジタル信号プロセッサは、乗算累算(MAC/MAD) や融合乗算加算(FMA) などの融合演算用の特別なオペコードを提供しており、一部の高性能ソフトウェア ライブラリは、処理速度の向上やコード サイズ削減のために、 cis x = cos x + i sin xなどの関数をサポートしています。
コンパイル
コンパイラは、サブルーチン呼び出しまたはインライン コードを使用して演算子と関数を実装できます。言語でサポートされている組み込み演算子の中には、中央処理装置で一般的に見られる少数の命令に直接マッピングされるものもありますが、他の演算子 (文字列の連結を表すために使用される '+' など)は実装が複雑になる場合があります。
演算子のオーバーロード
一部のプログラミング言語では、演算子がアドホック多態的、つまり複数の種類のデータの定義を持つ場合があります ( Javaでは、演算子は数値の加算と文字列の連結の両方に使用されます)。このような演算子は、オーバーロードされて+いると言われます。プログラマによる演算子のオーバーロードをサポートする言語 ( C++など) では、演算子のセットが限られているため、演算子のオーバーロードは、演算子のカスタマイズされた使用を定義するためによく使用されます。
例では、演算子は(より大きい)、および(より小さい) です。
IF ORDER_DATE > "12/31/2011" AND ORDER_DATE < "01/01/2013" THEN CONTINUE ELSE STOP>AND<
オペランドの強制
一部の言語では、演算子のオペランドを暗黙的に適切なデータ型に変換(強制変換)して、演算を実行することもできます。たとえば、Perl の強制変換ルールでは12 + "3.14"、 という結果が生成されます15.14。テキストは、"3.14"加算が行われる前に数値 3.14 に変換されます。さらに、12は整数であり、3.14は浮動小数点数または固定小数点数(小数点を含む数値)のいずれかであるため、整数はそれぞれ浮動小数点数または固定小数点数に変換されます。
JavaScript は逆のルールに従います。つまり、上記と同じ式を見つけると、整数を12文字列 に変換し"12"、次に 2 つのオペランドを連結して を形成します"123.14"。
言語に強制型が存在する場合、プログラマーは微妙なプログラミングミスを避けるために、オペランドの型と演算結果の型に関する特定のルールを認識している必要があります。
プログラミング言語の演算子機能
次の表は、いくつかのプログラミング言語における演算子の機能を示しています。
参照
注記
参考文献
- ^ 「演算子入力フォーム—Wolfram言語ドキュメント」reference.wolfram.com。
- ^ 「Maxima 5.42.0 マニュアル: 7. 演算子」. maxima.sourceforge.net .
- ^ 「接頭辞、接尾辞、および接尾辞演算子」。mythryl.org。
- ^ 「演算子」. doc.perl6.org .
- ^ "SWI-プロローグ -- op/3". www.swi-prolog.org。
- ^ 「演算子を宣言する」。seed7.sourceforge.net。
- ^ 「LANGUAGE B のチュートリアル入門」。
- ^ 「PHP: エラー制御演算子 - マニュアル」. php.net .
- ^ 「演算子」. docs.perl6.org .
- ^ 「関数」. docs.perl6.org .
- ^ Goldberg, Adele. 「Smalltalk-80: 言語とその実装」、p. 27、ISBN 0-201-11371-6 (PDF)。
