C++
 Computer >> コンピューター >  >> プログラミング >> C++

C言語における演算子の優先順位と結合規則の徹底解説

C言語において、演算子の優先順位(operator precedence)は、式中の項がどのようにグループ化されるかを決定し、式がどのような順序で評価されるかを左右します。すべての演算子に同じ優先順位が与えられているわけではなく、たとえば乗算演算子(*)加算演算子(+)よりも高い優先順位を持ちます。

具体例を挙げましょう。

x = 7 + 3 * 2;

この場合、変数 x に代入されるのは 20 ではなく 13 です。なぜなら、* 演算子の方が + よりも優先順位が高いため、まず 3 * 2 が計算され、その結果 6 に 7 が加算されるからです。

演算子の優先順位一覧表

以下の表では、優先順位が最も高い演算子が表の上部に、最も低い演算子が表の下部に配置されています。同じ式の中では、優先順位の高い演算子から順に評価されます。

分類 演算子 結合規則 
後置(Postfix) () [] -> . ++ -- 左から右 
単項(Unary) + - ! ~ ++ -- (type) * & sizeof 右から左 
乗除算(Multiplicative) * / % 左から右 
加減算(Additive) + - 左から右 
シフト(Shift) << >> 左から右 
関係(Relational) < <= > >= 左から右 
等価(Equality) == != 左から右 
ビット単位AND 左から右 
ビット単位XOR 左から右 
ビット単位OR 左から右 
論理AND && 左から右 
論理OR || 左から右 
条件(Conditional) ?: 右から左 
代入(Assignment) = += -= *= /= %=>>= <<= &= ^= |= 右から左 
カンマ(Comma) 左から右 

サンプルコード

次のプログラムは、括弧の付け方によって評価順序がどう変わるかを確認できる例です。

#include <stdio.h>
int main() {
    int a = 20;
    int b = 10;
    int c = 15;
    int d = 5;
    int e;

    e = (a + b) * c / d;      // (30 * 15) / 5
    printf("Value of (a + b) * c / d is : %d\n", e);

    e = ((a + b) * c) / d;    // (30 * 15) / 5
    printf("Value of ((a + b) * c) / d is : %d\n", e);

    e = (a + b) * (c / d);    // (30) * (15 / 5)
    printf("Value of (a + b) * (c / d) is : %d\n", e);

    e = a + (b * c) / d;      // 20 + (150 / 5)
    printf("Value of a + (b * c) / d is : %d\n", e);

    return 0;
}

実行結果

Value of (a + b) * c / d is : 90
Value of ((a + b) * c) / d is : 90
Value of (a + b) * (c / d) is : 90
Value of a + (b * c) / d is : 50

ポイントまとめ

  • 優先順位が同じ演算子が並んだ場合は、結合規則に従って評価されます。
  • 代入系の演算子や条件演算子(?:)は右から左へ結合します。
  • 計算順序を明確にしたい場合は、意図的に括弧 () を使用するのが安全で可読性も向上します。
  • なお、現行のC標準では main()int main(void) のように戻り値の型を明示することが推奨されています。
  1. JavaScriptの「!=」と「!==」演算子の違いをわかりやすく解説

    JavaScriptには、値が等しくないことを判定する不等価演算子として「!=」と「!==」の2種類が用意されています。この2つは似た名前ですが、動作に重要な違いがあります。本記事では、それぞれの特徴と具体的な使い分け方について解説します。 「!=」比較演算子(緩い不等価)とは 「!=」は型のチェックを行わない不等価演算子です。比較の前に、両オペランドのデータ型を自動的に変換(型強制・暗黙的な型変換)してから値を比較します。 そのため、数値と文字列のように異なる型同士でも、値が同じであれば等しいと判断されます。例えば、1 != 1 は文字列 1 が数値 1 に変換されて比較されるため、結果は

  2. 【JavaScript入門】Rest演算子とSpread演算子の違いと使い方を徹底解説

    Rest演算子(...)を使用すると、関数を任意の数の引数で呼び出し、余分な引数を1つの配列として受け取ることができます。また、配列やオブジェクトの分割代入(デストラクチャリング)の際にも活用できる便利な構文です。 一方、Spread演算子(...)は、配列などの反復可能なオブジェクト(イテラブル)を個々の要素へと展開するために使用します。 Rest演算子とSpread演算子の主な違い 両者は同じ「...」という記法ですが、使用する場所によって役割が異なります。 Rest演算子: 関数の仮引数や分割代入の左辺など、「複数の値をまとめて1つに集約」する場面で使用します。 Spread演算子: