式 (プログラミング)

式（しき、expression）とは、プログラミングにおいて、言語によって定められた優先順位や結びつきの規定に則って評価される値、変数、演算子、関数などの組み合わせである。数学における式と同様、式は評価された値を持つ。言語によっては式が副作用を持つこともあり、参照透過性がない場合もある。
式と文.
手続き型プログラミング言語では、式と「文」が、はっきりと分けられていることが多い。そういった言語では、プロシージャは複数個の文から成り、式から成る「式文」という文がある、といったような感じの構文（syntax）が多い。構文的に見て、セミコロン等によって式や文を分割する、あるいは終端する、という言語が多く、改行でもそうなるものもある。
文を特殊なカッコで囲むと式にできる、というような言語もあるが、あまり多くない。GCCでは独自拡張としてサポートされている。
式と文がはっきり分かれていない言語もある。
部分を持たない式.
変数や、いくつかの種類のリテラルは、内部にそれ以上細かい部分を持たない（配列のリテラルなどは、さらに内部に式がある）。
手続呼出.
プロシージャをサブルーチンとして呼び出す式。
codice_1
といったように、表面上の見た目では数学における関数の記法と同様な構文であることが多い。これは、関数型言語ではないプログラミング言語でも、多くはこのような記法であり、あるいはこの言語機能を持っている。
演算子式.
演算子と項から成る式である。
二項演算子.
数式などで見慣れている以下のような、
codice_2
というような構文となる。FORTRANのように数値計算のことだけを考えていれば良かった時代にはごく普通の言語機能だと考えられていたが、その後あらゆるデータ型をプログラミング言語が扱うようになった際に、それらのデータ型と演算子をどう扱うかは、言語ごとにまちまちとなった。言語によっては、代入なども、代入演算子などによる式でおこなうという設計の場合もある。
このような構文における頭痛のタネに、「演算子の結合性」（）と「演算子の優先順位」（operator precedence）がある。直感的には、少なくとも初等教育以来ずっと慣れている「乗除が先、加減が後」という規則があったほうがわかりやすいが、その他にもいくつもの「コンピュータのプログラミングではこれも使いたい」という演算、たとえばビット演算などを追加してゆくと、階層が何段階も増えてしまう。
C言語の設計ミスに、ビット演算子の codice_3 や codice_4 の優先順位が codice_5 よりも低い、という点があるが、これは以前にはC言語に論理演算子の codice_6 や codice_7 が無く、文脈によって演算子の意味が変わるという仕様であったことが遠因である。
そういったように、演算子が関係する文法の仕様を設計するのは難しく、さらに近年は前述のようにデータ型が増えたことによって余計に難しい要素が増えている。後述するような、他の種類の演算子も含めるとさらに複雑になる。
単項演算子.
前置演算子.
やはり初等教育以来慣れている前置マイナス演算子を使いたいという要求はあるが、そうすると対称性のためにプラスの演算子も欲しいということになったり、そうすると前述の二項演算と同じ記号を使うことで字句解析・構文解析が複雑になることもある。単純にするために、前置マイナス演算子を codice_8 以外の記号とすることもある。C言語のように多くの前置演算子がある言語もある。
後置演算子.
C言語の場合、（後置の）codice_9 と codice_10 すなわちインクリメントとデクリメントの演算子の他、codice_11 と codice_12 のような構造体などの要素の選択も構文的には後置演算子である。
代入.
代入が文である言語もあれば、「代入演算子」による式である言語もある。普通はわざわざ混乱させたりはしないが、C#とVB.NETを「同じ.NET系言語」だから、として似たものと考えてしまうのか、混乱して考えられてしまうこともあるようである。
C#においては代入は式であるが、同じ.NET系言語であるVB.NETでは代入は文である。そのため、似たようなコードではあるが全く違う処理結果を得る。
// C#
dynamic x = 123;
dynamic y = 234;
dynamic z;
z = y = x;
Console.WriteLine(x); // 123
Console.WriteLine(y); // 123
Console.WriteLine(z); // 123
' VB.NET
Dim x = 123
Dim y = 234
Dim z
z = y = x
Console.WriteLine(x) '123
Console.WriteLine(y) '234
Console.WriteLine(z) 'False