Conditions with if and else
if runs code only when a condition is true, and else gives an alternative. Together with comparisons and logical operators, they let a program make decisions — validate input, choose a price band, react to errors.
if
#include <stdio.h> int main(void) { int temperature = 31; if (temperature > 30) { printf("It's hot - drink water.\n"); } printf("Have a nice day.\n"); return 0; }
It's hot - drink water. Have a nice day.
The condition goes in parentheses. If it's true (non-zero), the block runs; otherwise it's skipped.
else and else if
#include <stdio.h> int main(void) { int scores[] = { 95, 82, 67, 40 }; for (int i = 0; i < 4; i++) { int score = scores[i]; char grade; if (score >= 90) { grade = 'A'; } else if (score >= 75) { grade = 'B'; } else if (score >= 50) { grade = 'C'; } else { grade = 'F'; } printf("%d -> %c\n", score, grade); } return 0; }
95 -> A 82 -> B 67 -> C 40 -> F
Conditions are checked from top to bottom, and only the first true branch runs — so order matters. Here a score of 95 also satisfies >= 75, but the >= 90 branch is reached first.
Combining conditions
#include <stdio.h> #include <stdbool.h> int main(void) { int age = 16; bool with_adult = true; if (age >= 18 || with_adult) { printf("Entry allowed.\n"); } int hour = 14; if (hour >= 9 && hour < 17) { printf("The shop is open.\n"); } if (!(hour >= 9 && hour < 17)) { printf("The shop is closed.\n"); } return 0; }
Entry allowed. The shop is open.
Note hour >= 9 && hour < 17: C has no 9 <= hour < 17 shorthand. That expression is valid but means something else — (9 <= hour) < 17, which is always true.
Truthiness
Any non-zero value counts as true, so you can test a value directly:
#include <stdio.h> int main(void) { int unread = 3; if (unread) { printf("You have %d unread messages.\n", unread); } int errors = 0; if (!errors) { printf("No errors.\n"); } return 0; }
You have 3 unread messages. No errors.
Writing if (unread != 0) says the same thing more explicitly; both styles are common.
Always use braces
Braces are optional when a branch is a single statement, but leaving them out invites a famous bug: adding a second line that looks as if it belongs to the if but doesn't.
#include <stdio.h> int main(void) { int logged_in = 0; if (logged_in) printf("Welcome back!\n"); printf("Loading your account...\n"); return 0; }
main.c:7:9: warning: misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]
The second printf runs regardless of logged_in. GCC's -Wall includes this warning; with Clang, add -Wmisleading-indentation (as here). Always writing braces avoids the problem entirely.
Nested conditions and early returns
Deeply nested ifs are hard to follow. Checking for problems first and leaving early keeps the main logic flat:
#include <stdio.h> int shipping_cost(int weight_grams, int express) { if (weight_grams <= 0) { return -1; // invalid } if (weight_grams > 30000) { return -1; // too heavy to ship } int cost = weight_grams <= 2000 ? 5 : 12; if (express) { cost *= 2; } return cost; } int main(void) { printf("%d %d %d\n", shipping_cost(500, 0), shipping_cost(5000, 1), shipping_cost(40000, 0)); return 0; }
5 24 -1
Comparing floating-point values and strings
Two common mistakes in conditions: comparing doubles with == (use a tolerance; lesson 9), and comparing strings with ==, which compares addresses, not text (use strcmp; lesson 29).
Try it yourself
Classify a body-mass index: under 18.5 is underweight, under 25 healthy, under 30 overweight, otherwise obese.
BMI 22.7: healthy