Why Programs Need Branches
Every program so far has run straight through: line 1, line 2, line 3. Real programs make decisions. Is the password correct? Is the number negative? Did the file open? The if statement is how C asks a question and runs code only when the answer is yes.
The condition temperature > 30 is tested once. It holds, so the message prints. The final line is outside the braces, so it prints no matter what. Change 31 to 18 and run it again - the first message disappears and the second stays.
Syntax: Parentheses, Braces, and No Semicolon
An if in C has a fixed shape:
if (condition) {
// runs when condition is nonzero
}
Three rules worth memorising early. The parentheses around the condition are required. There is no then keyword. And there is no semicolon after the closing parenthesis - a stray one ends the statement right there:
// BUG: the if does nothing; the printf always runs
if (x > 10);
{
printf("big\n");
}
That compiles cleanly. The ; is an empty statement that becomes the body of the if, and the braces below it are just a free-standing block that always executes. Compiling with gcc -Wall catches it.
The braces themselves are optional for a single statement, but leave them in. A brace-less if that later grows a second line is a classic source of bugs, because indentation does not group statements in C.
else and else if
else supplies the other path:
For more than two outcomes, chain with else if. C checks each condition in order and stops at the first one that holds:
Order matters enormously here. Because the chain stops at the first match, the second test only ever sees scores below 90 - which is why score >= 80 does not need to also say && score < 90. Write the chain from the most restrictive condition to the least, or every value falls into the first branch.
The trailing else is optional. Include one whenever the chain is meant to cover every case; its absence means "if nothing matched, do nothing", which is fine but should be deliberate.
Truthiness: 0 Is False, Everything Else Is True
C's core language has no separate boolean type in conditions. An if simply asks whether the expression is nonzero.
The last two lines show the other half of the rule: comparison operators are ordinary expressions that produce 1 for true and 0 for false. That is why if (5 > 2) works - it is really if (1).
This is also why -3 is true in C. The rule is nonzero, not positive. If you want to know whether a number is positive, say if (n > 0), not if (n).
C99 added <stdbool.h> with a real bool type plus true and false, which reads better in new code. Under the hood they are still 1 and 0, so nothing about the rule above changes - see Booleans in C.
The comparison and logical operators you will use in conditions:
== equal to && logical AND (both sides true)
!= not equal to || logical OR (either side true)
< less than ! logical NOT
> greater than
<= less than or equal
>= greater than or equal
&& and || short-circuit: a && b never evaluates b if a is false, and a || b never evaluates b if a is true. That is a guarantee, not an optimisation, so it is safe to write if (n != 0 && total / n > 5) - the division cannot run when n is zero.
The = vs == Bug
This is the single most common mistake in C conditions:
// BUG: assigns 5 to x, then tests 5 (nonzero), so this ALWAYS runs
if (x = 5) {
printf("x is five\n");
}
C allows assignment inside an expression, so the line is legal. It stores 5 in x, produces the value 5, and 5 is nonzero - the branch runs every single time, and x has been quietly overwritten.
Two defences. First, always compile with warnings on:
gcc -Wall -Wextra program.c -o program
GCC and clang both flag "suggest parentheses around assignment used as truth value". Second, some programmers write the constant before the variable - if (5 == x) - so that a typo'd if (5 = x) is a hard compile error rather than a silent bug. That style is a matter of taste; turning warnings on is not.
Nesting
An if can contain another if. Nesting expresses conditions that only make sense once an earlier one holds:
Two levels are readable. Four are not. When nesting deepens, look for a way to flatten it - often by combining conditions with &&, or by handling the failure cases first and returning early:
// flatter: deal with the exceptions, then get on with the work
if (age < 18) { printf("Adults only.\n"); return 0; }
if (!hasTicket) { printf("Please buy a ticket.\n"); return 0; }
printf("Welcome in.\n");
The Dangling else
When a brace-less if is nested inside another, which if does an else belong to? C's rule: an else binds to the nearest unmatched if, regardless of how the code is indented.
// The else belongs to the INNER if, despite the indentation
if (a > 0)
if (b > 0)
printf("both positive\n");
else
printf("a is not positive\n"); // WRONG - runs when a > 0 and b <= 0
The indentation says the else pairs with the outer if. The compiler pairs it with the inner one. Braces remove the ambiguity entirely, which is the real argument for always using them:
if (a > 0) {
if (b > 0) {
printf("both positive\n");
}
} else {
printf("a is not positive\n");
}
The Ternary Operator
When a branch exists only to choose a value, the conditional operator ? : says it in one expression:
Read cond ? x : y as "if cond then x otherwise y". Exactly one of the two branches is evaluated, and the whole thing produces a value - which is why it can be assigned or passed as an argument where a statement could not be.
Keep it for simple value choices. Nested ternaries (a ? b : c ? d : e) are legal and almost always harder to read than the else if chain they replace.
Frequently Asked Questions
How do you write an if else statement in C?
Put the condition in parentheses and the code in braces: if (score >= 60) { printf("Pass\n"); } else { printf("Fail\n"); }. The else block runs only when the condition is false, and there is no then keyword in C.
What counts as true in a C if statement?
Any value that is not zero. C has no dedicated boolean type in its core syntax, so if (n) runs when n is anything except 0, and if (!n) runs only when n is exactly 0. Comparison operators such as == and < produce 1 for true and 0 for false.
What is the difference between = and == in C?
== compares, = assigns. Writing if (x = 5) assigns 5 to x and then tests 5, which is nonzero, so the branch always runs. It compiles without error, which is why it is the most common beginner bug in C conditions - most compilers warn about it with -Wall.
How does the ternary operator work in C?
condition ? valueIfTrue : valueIfFalse is an expression that produces one of two values, so it can sit inside an assignment or a printf argument: int max = a > b ? a : b;. Use it for picking a value, and a regular if when you need to run statements.