Operator Precedence in Programming

Operator Precedence, also known as operator hierarchy, is a set of rules that controls the order in which operations are performed in an expression without parentheses. It is a fundamental concept in programming languages and is crucial for writing correct and efficient code.

Table of Content

  • What is Operator Precedence?
  • Operator Precedence in Arithmetic Operators
  • Operator Precedence in Relational Operators
  • Operator Precedence in Logical Operators
  • Operator Precedence in Assignment Operators
  • Operator Precedence in Bitwise Operators
  • Operator Precedence in Conditional (Ternary) Operator
  • Operator Precedence in Unary Operators
  • Operator Precedence in Member Access Operators
  • Operator Precedence in Type Cast Operators
  • Importance of Operator Precedence

What is Operator Precedence?

Operator Precedence is a set of rules that defines the order in which operations are performed in an expression based on the operators between the operands.

Consider the following mathematical expression 2 + 3 * 4. If we perform the operations from left to right, we get (2 + 3) * 4 = 20. However, if we follow the mathematical rule of precedence (also known as BODMAS), which states that multiplication and division should be performed before addition and subtraction, we get 2 + (3 * 4) = 14. This rule of precedence is also applicable in programming.

Operator Precedence in Arithmetic Operators

Arithmetic operators follow the standard precedence rules that are used in mathematics. The precedence of arithmetic operators from highest to lowest is as follows:

  • Parentheses ()
  • Unary plus and minus + –
  • Multiplication, division, and modulus * / %
  • Addition and subtraction + –

Below is the implementation of Operator Precedence in Arithmetic Operators:

C++
#include <iostream>
using namespace std;

int main()
{
    int a = 10;
    int b = 5;
    int c = 2;

    // Using arithmetic operators
    // result1 is 20 because multiplication has higher
    // precedence than addition
    int result1 = a + b * c;
    cout << "a + b * c = " << result1 << endl;

    // result2 is 30 because parentheses change the order of
    // operations
    int result2 = (a + b) * c;
    cout << "(a + b) * c = " << result2 << endl;

    // result3 is 8 because division has higher precedence
    // than subtraction
    int result3 = a - b / c;
    cout << "a - b / c = " << result3 << endl;

    // result4 is 2 because parentheses
    // change the order of operations
    int result4 = (a - b) / c;
    cout << "(a - b) / c = " << result4 << endl;

    return 0;
}

// Note: the difference in output between the programs is due to the 
//different precedence rules and how parentheses are used to override those 
// rules in each language.
Java
public class Main {
    // Main method
    public static void main(String[] args) {
        // Variable declarations
        int a = 10;
        int b = 5;
        int c = 2;

        // Using arithmetic operators

        // result1 is 20 because multiplication has higher precedence than addition
        int result1 = a + b * c;
        System.out.println("a + b * c = " + result1);

        // result2 is 30 because parentheses change the order of operations
        int result2 = (a + b) * c;
        System.out.println("(a + b) * c = " + result2);

        // result3 is 8 because division has higher precedence than subtraction
        int result3 = a - b / c;
        System.out.println("a - b / c = " + result3);

        // result4 is 2 because parentheses change the order of operations
        int result4 = (a - b) / c;
        System.out.println("(a - b) / c = " + result4);
    }
}

// Note: the difference in output between the programs is due to the 
//different precedence rules and how parentheses are used to override those 
// rules in each language.
Python
# Initialize variables
a = 10
b = 5
c = 2

# Using arithmetic operators
# result1 is 20 because multiplication has higher
# precedence than addition
result1 = a + b * c
print("a + b * c =", result1)

# result2 is 30 because parentheses change the order of
# operations
result2 = (a + b) * c
print("(a + b) * c =", result2)

# result3 is 8 because division has higher precedence
# than subtraction, and in Python, division (/) returns
# a float result by default
result3 = a - b / c
print("a - b / c =", result3)

# result4 is 2 because parentheses
# change the order of operations
result4 = (a - b) / c
print("(a - b) / c =", result4)

# Note: The output may vary depending on the syntax used in the C++ code.
# In Python, division (/) returns a float result by default, which may lead to
# different results compared to C++ where integer division is used by default.
JavaScript
// Main function
function main() {
    let a = 10;
    let b = 5;
    let c = 2;

    // Using arithmetic operators
    // result1 is 20 because multiplication has higher
    // precedence than addition
    let result1 = a + b * c;
    console.log("a + b * c = " + result1);

    // result2 is 30 because parentheses change the order of
    // operations
    let result2 = (a + b) * c;
    console.log("(a + b) * c = " + result2);

    // result3 is 8 because division has higher precedence
    // than subtraction
    let result3 = a - b / c;
    console.log("a - b / c = " + result3);

    // result4 is 2 because parentheses
    // change the order of operations
    let result4 = (a - b) / c;
    console.log("(a - b) / c = " + result4);
}

// Call the main function to execute the example usage
main();

// Note: the difference in output between the programs is due to the 
//different precedence rules and how parentheses are used to override those 
// rules in each language.

Output
a + b * c: 20
(a + b) * c: 30
a - b / c: 8
(a - b) / c: 2

Operator Precedence in Relational Operators

Relational operators are used to compare two values. The precedence of relational operators from highest to lowest is as follows:

  • Less than, greater than, less than or equal to, greater than or equal to < > <= >=
  • Equality and inequality == !=

Below is the implementation of Operator Precedence in Relational Operators:

C++
#include <iostream>
using namespace std;

int main()
{
    int a = 15;
    int b = 20;
    int c = 35;

    // Using relational operators
    // b < c is evaluated first, which results to 1 and then
    // 1 != 35 is evaluated which results to true
    bool result1 = b < c != c;
    // c != c is evaluated first, which results to 0 and
    // then 20 < 0 is evaluated which results to false
    bool result2 = b < (c != c);

    // Print the results
    cout << "(b < c != c) = " << result1 << endl;
    cout << "(b < (c != c)) = " << result2 << endl;

    return 0;
}

Output
a < b: 1
b > c: 0
a <= c: 1
c >= b: 1
a == b: 0
b != c: 1

Operator Precedence in Logical Operators

Logical operators are used to combine two or more conditions. The precedence of logical operators from highest to lowest is as follows:

  • Logical NOT !
  • Logical AND &&
  • Logical OR ||

Below is the implementation of Operator Precedence in Logical Operators:

C++
#include <iostream>
using namespace std;

int main()
{
    // Using logical operators
    // true && false is evaluated first which results to
    // false and then true || false is evaluated which
    // results to true
    bool result1 = true || false && false;
    // true || false is evaluated first which results to
    // true and then true && false is evaluated which
    // results to false
    bool result2 = (true || false) && false;

    cout << "true || false && false = " << result1 << "\n";
    cout << "(true || false) && false = " << result2
         << "\n";
    return 0;
}

Output
a && b: 0
a || b: 1
!a: 0
a && (b || c): 1

Operator Precedence in Assignment Operators

Assignment operators are used to assign values to variables. The assignment operator = has the lowest precedence.

Below is the implementation of Operator Precedence in Assignment Operators:

C++
#include <iostream>
using namespace std;

int main()
{
    int a = 5;
    int b = 10;

    // Using assignment operators
    a = b; // a is now 10
    cout << "a = b: " << a << endl;

    a += b; // a is now 20
    cout << "a += b: " << a << endl;

    a -= b; // a is now 10
    cout << "a -= b: " << a << endl;

    a *= b; // a is now 100
    cout << "a *= b: " << a << endl;

    a /= b; // a is now 10
    cout << "a /= b: " << a << endl;

    a %= b; // a is now 0
    cout << "a %= b: " << a << endl;

    return 0;
}
Java
public class Main {
    public static void main(String[] args) {
        int a = 5;
        int b = 10;

        // Using assignment operators
        a = b; // a is now 10
        System.out.println("a = b: " + a);

        a += b; // a is now 20
        System.out.println("a += b: " + a);

        a -= b; // a is now 10
        System.out.println("a -= b: " + a);

        a *= b; // a is now 100
        System.out.println("a *= b: " + a);

        a /= b; // a is now 10
        System.out.println("a /= b: " + a);

        a %= b; // a is now 0
        System.out.println("a %= b: " + a);
    }
}
Python
# Initialize variables
a = 5
b = 10

# Using assignment operators
a = b  # a is now 10
print("a = b: ", a)

a += b  # a is now 20
print("a += b: ", a)

a -= b  # a is now 10
print("a -= b: ", a)

a *= b  # a is now 100
print("a *= b: ", a)

a /= b  # a is now 10
print("a /= b: ", a)

a %= b  # a is now 0
print("a %= b: ", a)

Output
a = b: 10
a += b: 20
a -= b: 10
a *= b: 100
a /= b: 10
a %= b: 0

Operator Precedence in Bitwise Operators

Bitwise operators operate on binary representations of integers. The precedence of bitwise operators from highest to lowest is as follows:

  • Bitwise NOT ~
  • Bitwise SHIFT <<, >>
  • Bitwise AND &
  • Bitwise XOR ^
  • Bitwise OR |

Below is the implementation of Operator Precedence in Bitwise Operators:

C++
#include <iostream>
using namespace std;

int main()
{
    int a = 5, b = 9, c = 3;
    int result;

    // Bitwise AND has higher precedence than Bitwise OR
    result = a & b | c;
    cout << "a & b | c = " << result << endl;

    // Bitwise AND has higher precedence than Bitwise XOR
    result = a ^ b & c;
    cout << "a ^ b & c = " << result << endl;

    // Bitwise Shift has higher precedence than Bitwise OR
    result = a | b << 2;
    cout << "a | b << 2 = " << result << endl;


    return 0;
}

Output
a & b: 12
a | b: 61
a ^ b: 49
~a: -61
a << 2: 240
a >> 2: 15

Operator Precedence in Conditional (Ternary) Operator

The conditional (ternary) operator ?: has lower precedence than arithmetic, relational, and logical operators but higher precedence than the assignment operator.

Below is the implementation of Operator Precedence in Conditional Operators:

C++
#include <iostream>
using namespace std;

int main()
{
    int a = 55;
    int b = 100;

    // Using conditional (ternary) operator
    string result = (a > b) ? "a is greater than b"
                            : "a is not greater than b";

    // Print the result
    cout << result << endl;

    return 0;
}

Output
a is not greater than b

Operator Precedence in Unary Operators

Unary operators operate on a single operand. The precedence of unary operators is higher than arithmetic, relational, logical, and assignment operators.

Below is the implementation of Operator Precedence in Unary Operators:

C++
#include <iostream>
using namespace std;

int main()
{
    int x = 5;
    int y = 3;

    int result = ++x * -y;
    cout << "(++x * -y) = " << result << endl;

    x = 5; // Reset x to its initial value

    result = (++x) * (-y);
    cout << "After expression (++x) * (-y) = " << result
         << endl;

    x = 5; // Reset x to its initial value

    result = -x * -y;
    cout << "After expression (-x * -y) = " << result
         << endl;

    x = 5; // Reset x to its initial value

    result = (-x) * (-y);
    cout << "After expression (-x) * (-y) = " << result
         << endl;

    return 0;
}

Output
+a: 5
-a: -5
a++: 6
a--: 5
!a: 0

Operator Precedence in Member Access Operators

Member access operators . and -> have the highest precedence.

Below is the implementation of Operator Precedence in Member Access Operators:

C++
#include <iostream>
using namespace std;

// Define a simple class
class MyClass {
public:
    int myVar;
    MyClass()
        : myVar(10)
    {
    }
};

int main()
{
    MyClass obj;

    // Using dot operator to access member directly
    cout << "obj.myVar: " << obj.myVar << endl;

    // Create a pointer to the object
    MyClass* ptr = &obj;

    // Using arrow operator to access member via pointer
    cout << "ptr->myVar: " << ptr->myVar << endl;

    return 0;
}

Output
obj.myVar: 10
ptr->myVar: 10

Operator Precedence in Type Cast Operators

Type cast operators are used to convert one data type to another. They have higher precedence than arithmetic, relational, logical, and assignment operators.

Below is the implementation of Operator Precedence in Type Cast Operators:

C++
#include <iostream>
using namespace std;

int main()
{
    double a = 5.7;
    double b = 3.5;
  
      int result = (int)a + b;
      
      cout << "(int)a + b = " << result << "\n";

      result = (int)a * b;
      cout << "(int)a * b = " << result << "\n";
    return 0;
}

Output
(int)a + (int)b: 8
(int)(a + b): 8

Importance of Operator Precedence:

Understanding operator precedence is essential for several reasons:

  • Correctness: Misunderstanding operator precedence can lead to bugs that are hard to detect. For example, the expression a = b == c in C++ is not an error, but it probably doesn’t do what the programmer intended. It’s equivalent to a = (b == c), not (a = b) == c.
  • Readability: Code that correctly uses operator precedence is easier to read and understand. Using parentheses to make the order of operations explicit can often make code more readable, even if they’re not strictly necessary.
  • Performance: In some cases, understanding operator precedence can help write more efficient code. For example, knowing that bitwise AND (&) has higher precedence than bitwise OR (|) might allow you to avoid unnecessary parentheses or temporary variables.

In conclusion operator precedence is a Important concept in programming that affects how expressions are evaluated. It is essential to understand the rules in the language we are using to avoid bugs and write clear and efficient code.