Ternary Conditional Operator and Precedence in C

This guide provides an overview of the ternary conditional operator in the C programming language, detailing its syntax, functional behavior, and evaluation rules. You will learn how the operator acts as an inline alternative to if-else branching, how its relatively low precedence level interacts with other C operators, and how its right-to-left associativity governs nested expressions.

Understanding the Ternary Operator

The ternary conditional operator (?:) is the only operator in C that takes three operands. It provides a compact way to evaluate a condition and return one of two values.

Its basic syntax is:

condition ? expression_if_true : expression_if_false;

When this expression executes:

  1. The condition is evaluated first.
  2. If the condition evaluates to true (any non-zero value), expression_if_true is evaluated and becomes the result of the entire expression.
  3. If the condition evaluates to false (0), expression_if_false is evaluated and becomes the result.

The unused expression is completely ignored. This behavior guarantees short-circuit evaluation, meaning side effects in the unselected branch will not occur:

int a = 5;
int b = (a > 0) ? 10 : (a++); // a++ is never executed

Operator Precedence in C

In C's operator precedence hierarchy, the conditional operator ranks very low. It sits just above the assignment operators (=, +=, etc.) and the comma operator (,), but below almost everything else, including:

  • Arithmetic operators (+, -, *, /)
  • Relational operators (<, >, <=, >=)
  • Equality operators (==, !=)
  • Logical operators (&&, ||)
  • Bitwise operators (&, ^, |)

Because logical and relational operators have higher precedence than the conditional operator, you do not need parentheses around the condition in standard comparisons:

// Valid without extra parentheses:
int max = a > b ? a : b; 

// Evaluated as:
int max = (a > b) ? a : b;

Similarly, arithmetic operations in the return branches are resolved before the ternary operator takes effect:

int result = condition ? x + 5 : y * 2;

// Evaluated as:
int result = condition ? (x + 5) : (y * 2);

Precedence with Assignment Operators

Assignment operators have lower precedence than the conditional operator. Consequently, attempting to perform an assignment directly inside a branch without parentheses will lead to a compilation error:

// Syntax Error:
x ? y = 1 : z = 2;

// Correct usage:
x ? (y = 1) : (z = 2);

Associativity (Right-to-Left)

Unlike most binary operators in C, which associate from left to right, the conditional operator groups from right to left.

This property is critical when nesting multiple ternary operators. Consider the following expression:

int result = cond1 ? val1 : cond2 ? val2 : val3;

Because of right-to-left associativity, the compiler groups the expression from the right side:

int result = cond1 ? val1 : (cond2 ? val2 : val3);

This naturally mirrors a standard if ... else if ... else structure:

if (cond1) {
    result = val1;
} else if (cond2) {
    result = val2;
} else {
    result = val3;
}

Type Compatibility

The second and third operands must have compatible types. C applies the usual arithmetic conversions so that the entire expression evaluates to a single common type. If one branch evaluates to an int and the other to a double, the entire ternary expression evaluates to a double, regardless of which branch is selected:

int condition = 1;
double result = condition ? 1 : 2.5; // Evaluates to (double)1.0