Evaluation of OR'd if conditions
Categories:
Understanding Short-Circuit Evaluation in C's Logical OR Operator

Explore how C's logical OR (||
) operator evaluates conditions, focusing on short-circuiting behavior and its implications for performance and side effects.
In C programming, understanding how logical operators evaluate their operands is crucial for writing efficient and bug-free code. The logical OR operator (||
) is particularly interesting due to a concept known as 'short-circuit evaluation'. This article delves into what short-circuit evaluation is, how it works with ||
, and its practical implications for your C programs.
What is Short-Circuit Evaluation?
Short-circuit evaluation is an optimization technique used by compilers for logical operators (&&
and ||
). It means that the second operand of a logical expression is only evaluated if the first operand is not sufficient to determine the value of the entire expression. For the logical OR operator (||
), if the first operand evaluates to true (non-zero), the entire expression is already known to be true, regardless of the second operand's value. Therefore, the second operand is not evaluated.
flowchart TD A[Start Evaluation] --> B{Is first operand true?}; B -- Yes --> C[Result is TRUE]; B -- No --> D[Evaluate second operand]; D --> E{Is second operand true?}; E -- Yes --> C; E -- No --> F[Result is FALSE]; C --> G[End Evaluation]; F --> G;
Flowchart illustrating short-circuit evaluation for logical OR (||
)
Practical Implications and Examples
Short-circuit evaluation has significant practical implications, especially when operands involve function calls or expressions with side effects. It can prevent unnecessary computations and guard against errors like dereferencing null pointers. Consider the following C code examples to understand its behavior.
#include <stdio.h>
int func_a() {
printf("func_a called\n");
return 1; // True
}
int func_b() {
printf("func_b called\n");
return 0; // False
}
int main() {
printf("--- Test 1 ---\n");
if (func_a() || func_b()) {
printf("Condition is true\n");
}
printf("\n--- Test 2 ---\n");
if (func_b() || func_a()) {
printf("Condition is true\n");
}
return 0;
}
Demonstrating short-circuit evaluation with function calls
In 'Test 1', func_a()
is called first. Since it returns 1
(true), the ||
operator short-circuits, and func_b()
is never called. The output will only show "func_a called". In 'Test 2', func_b()
is called first. It returns 0
(false), so the ||
operator proceeds to evaluate func_a()
. Since func_a()
returns 1
(true), the condition becomes true. Both "func_b called" and "func_a called" will be printed.
if (ptr != NULL || *ptr == value)
is incorrect. The correct way to guard against null pointer dereference with ||
is if (ptr == NULL || *ptr->member == value)
. If ptr
is NULL
, the first condition is true, and the second (which would dereference NULL
) is skipped. However, for checking if ptr
is NOT NULL
AND then dereferencing, &&
is typically used: if (ptr != NULL && *ptr == value)
.Order of Evaluation and Side Effects
The order of evaluation in C's logical operators is strictly left-to-right. This strict ordering, combined with short-circuiting, means you can rely on the first operand being fully evaluated before the second, if the second is evaluated at all. This is crucial when operands have side effects, such as modifying a variable or performing I/O operations. Be mindful of these side effects, as they might not occur if the expression short-circuits.
#include <stdio.h>
int main() {
int x = 5;
int y = 10;
// Example 1: Short-circuit prevents increment
if (x == 5 || ++y > 10) {
printf("Condition 1: x=%d, y=%d\n", x, y); // y remains 10
}
// Example 2: No short-circuit, increment occurs
x = 6; // Change x so first condition is false
if (x == 5 || ++y > 10) {
printf("Condition 2: x=%d, y=%d\n", x, y); // y becomes 11
}
return 0;
}
Side effects and short-circuit evaluation
In 'Condition 1', x == 5
is true, so ++y
is never executed, and y
remains 10
. In 'Condition 2', x == 5
is false, so ++y
is executed, incrementing y
to 11
before the second part of the condition is evaluated. This demonstrates how side effects are conditional on the evaluation path.