式の英単語はexpressionです。
式と言うと、数学的イメージがありますが、英単語のexpressionの直訳では、
「表現すること」と訳されます。
そして、プログラミングの世界では、データを表現することになります。
データを表現する箇所は、if( 式 ) や、while( 式 )、
printf("%d" , 式 ) などとさまざまです。
つまりデータを表現できるものは何でも式になります。つまり、
定数の単体の表現や、
変数の単体の表現や、
戻り値がある関数呼び出しの表現、
そしてこれらを演算子で組み合わせた表現!
これらすべては、データ表現しているので、式といえます。
(そして、式は ; のセミコロンを付けることで、
単純文というifやwhileなどで制御可能な実行の単位になります。)
演算子で構成した式は、プログラマが指示できる最も小さい処理単位です。
そして、使うと使わずに関わらず、データを表現しているというわけです。
複数の演算子で、式を構成する場合、
ひとつ演算子で得られる結果のデータが、次の演算子の処理対象になります。
(この演算対象は、演算子のオペランドと呼ばれます。)
そうやって、
ひとつずつ演算が行われて、最終的に全体の処理結果となるデータを指示します。
つまり演算子を使う場合は、どの演算子から処理を行わせるかを、明確に指示できなければなりません。
その実行する順番は、優先順位の高いものから行われます。
また同じ優先順の場合は結合規則で実行することになっています。
その優先順位と結合規則の表を以下に示します。
表の上の方の演算子の優先順位が高く、同じ行は同じ優先順位になっていて、
その時は結合規則に従って、処理順が 決ります。
以下に簡単な例を示します。例えば、
int a[5] = { 4, 2, 6 }; の配列とint n; の変数が用意されているとします。
この後の実行例で、n = a[2] - a[0] * a[1];と行うと、nに記憶されるデータは、-2になります。
ここで、使われる=演算子と、-演算子、*演算子は、
左右に2つのオペランドを持つので2項演算子と呼ばれます。
ここで=や-より*の方の優先順位が高いので、a[0] * a[1]が先行して8が演算結果になります。
それが、-の右項のオペランドになり、
a[2] - 8の演算が行われ、その結果のデータ-2が、最終的に=演算子でnに記憶されます。
そして=演算子の結果として、その記憶内容の-2が得られます。(ここで、このデータは使われません。)
では、n = a[2] - - a[0] * a[1];ではどうでしょうか? nに記憶されるデータは、16です。
こんどは、2番目にある-は単項演算子(オペランド1つ)が、ここで掛け算より高い優先順位になります。
よって、a[0] * a[1]の前に、- a[0]が働き、-4の演算結果が得られます。
これとa[1]が、*のオペランドになり、-8が得られます。
そして、これが2演算子の - のオペランドになり、
6 - -8 の計算結果である14が得られます。
最後に=演算子でnに記憶され、その記憶内容の14が=演算子の結果として得られます。(このデータは使われません。)
例えば、printf("%d", n = a[2] - - a[0] * a[1]);という実行文であれば、=演算子の結果
である14がprintfの引数で使われることになります。
単項演算子は右側がオペランドになり、右から左へ結合します。
sizeofは、オペランドが配列名の場合に配列全体のバイト数を結果にし、
オペランドが式の場合は『その式の演算結果を記憶するために必要なバイト数』を演算子としての結果にします。
よって、int型サイズが4byteの場合、n = sizeof aとすると、
上記例の配列は5個で、要素がint型なので、5掛ける4の20が演算結果として得られて、その20がnに記憶されます。
n = sizeof a[2]とすると、[]演算子が優先されて、この要素の6を記憶するに必要なint型サイズ4byteの4がnに記憶されます。
この式が、n = ! sizeof aになると、どうなるでしょうか?
この場合は、sizeof演算子と、!演算子の優先順位は同じなので、結合規則より、右から作用して、先にsizeof aが働いて、
20の結果が得られます。それに !が働きます。!は、右の条件の論理値を反転します。つまり右が0以外(成立)なら、0の結果が得られます。
よってこの結果は0になり、nに0が記憶されます。
n = sizeof ! aはどうなるでしょうか?
この場合は、sizeof演算子と、!演算子の優先順位は同じなので、結合規則より、右から作用して、まず ! aの結果をだします。
!は、右の条件の論理値を反転します。つまり右が0以外(成立)なら、0の結果が得られます。それはint型なので、
これをオペランドとするsizeofの演算結果は4になり、その4がnに記憶されます。