Conditionals in C — if, else if, else and switch without detours
Conditionals in C if else switch work with the same logic as Python — same concept, different syntax. If you understood if/elif/else in Python, you already understand how decisions work in C. What changes is the notation: curly braces instead of indentation, else if instead of elif, and a switch that works identically to the one you saw in Java.
This article covers all of it with direct comparisons to Python and the mistakes that cost the most time in IC2.
Table of Contents
The if statement in C
The basic structure:
# Python
if grade >= 5:
print("Passed")
// C
if (grade >= 5) {
printf("Passed\n");
}
Three differences from Python:
Parentheses around the condition — mandatory in C. In Python the condition was written directly. In C it must be enclosed in ().
Curly braces instead of indentation — the block that belongs to the if is delimited by { }. Indentation in C is visual only — the compiler ignores it entirely.
Semicolon at the end of printf — every statement in C ends with ;.
if/else if/else
# Python
if grade >= 9:
print("Outstanding")
elif grade >= 7:
print("Merit")
elif grade >= 5:
print("Passed")
else:
print("Failed")
// C
if (grade >= 9) {
printf("Outstanding\n");
} else if (grade >= 7) {
printf("Merit\n");
} else if (grade >= 5) {
printf("Passed\n");
} else {
printf("Failed\n");
}
elif in Python becomes else if in C — two separate words. The logic is identical: Python evaluates conditions in order from top to bottom and executes the first block that matches. C does exactly the same.
Comparison operators — identical to Python
== // equal (DOUBLE == — never single =) != // not equal > // greater than < // less than >= // greater or equal <= // less or equal
Logical operators — different names, same logic
# Python if a > 0 and b > 0: if a > 0 or b > 0: if not active:
// C
if (a > 0 && b > 0) { /* and → && */
if (a > 0 || b > 0) { /* or → || */
if (!active) { /* not → ! */
The logic is identical — just different symbols. && requires both conditions to be true. || requires at least one. ! inverts a boolean value.
If without curly braces — when it’s valid and when it’s a trap
In C if a block has only one statement you can omit the curly braces:
if (grade >= 5)
printf("Passed\n"); // correct — one statement
But this is a classic trap with multiple statements:
if (grade >= 5)
printf("Passed\n");
printf("Congratulations\n"); // TRAP — this line always executes
// it's NOT inside the if
The indentation deceives you — without curly braces only the first line belongs to the if. The second always executes regardless of the condition.
Recommendation for IC2: always use curly braces, even for single-statement blocks. It prevents this error and makes the code clearer:
if (grade >= 5) {
printf("Passed\n");
printf("Congratulations\n"); // now correctly inside the if
}
The = vs == trap — the most dangerous in C
In Python using = inside an if gives an immediate syntax error. In C it compiles without error but behaves in a completely unexpected way:
int x = 5;
if (x = 10) { // assigns 10 to x, then evaluates 10 as true
printf("This runs\n"); // always runs — 10 is non-zero = true
}
// x is now 10 — modified inside the condition
if (x == 10) { // compares x with 10 — correct
printf("x is 10\n");
}
This is one of the hardest bugs to find — the program compiles and runs, but the variable gets modified silently and the condition is always true. Use -Wall when compiling to get a warning:
gcc program.c -o program -Wall # warning: suggest parentheses around assignment used as truth value
A defensive trick used in C: put the constant on the left side of the comparison. If you accidentally write = instead of ==, it’s now trying to assign to a constant — which gives a compile error:
if (10 = x) // compile error — can't assign to 10 if (10 == x) // correct
The ternary operator in C
Identical to Java and Python:
/* Python */
result = "Passed" if grade >= 5 else "Failed"
/* C */
const char *result = (grade >= 5) ? "Passed" : "Failed";
printf("%s\n", result);
/* Or directly in printf */
printf("%s\n", (grade >= 5) ? "Passed" : "Failed");
switch in C — identical to what you saw in Java
If you read the Java article, the switch in C is exactly the same — same structure, same break, same default, same fall-through behaviour:
# Python — no direct equivalent # (match/case exists in Python 3.10+ but wasn't in FP1)
// C switch — identical to Java
switch (option) {
case 1:
printf("Option 1\n");
break;
case 2:
printf("Option 2\n");
break;
case 3:
printf("Option 3\n");
break;
default:
printf("Invalid option\n");
}
Why break is mandatory — fall-through
Without break, execution falls through to the next case:
int day = 2;
switch (day) {
case 1:
printf("Monday\n");
case 2:
printf("Tuesday\n"); // executes (day == 2)
case 3:
printf("Wednesday\n"); // also executes (no break in case 2)
break;
case 4:
printf("Thursday\n"); // doesn't execute (break in case 3)
}
// Output: Tuesday
// Wednesday
This is intentional behaviour in C — the same as Java. Use it deliberately when multiple cases should do the same thing:
switch (day) {
case 1:
case 2:
case 3:
case 4:
case 5:
printf("Weekday\n");
break;
case 6:
case 7:
printf("Weekend\n");
break;
default:
printf("Invalid day\n");
}
switch vs if/else — when to use each
Use switch: → comparing one variable against exact integer or char values → 3 or more distinct cases → values are int or char (NOT double or float) Use if/else: → ranges (grade >= 5, grade < 7...) → conditions mixing multiple variables → 1 or 2 cases → comparing doubles (switch doesn't work with doubles)
// switch — perfect for exact int values
switch (month) {
case 1: printf("January\n"); break;
case 2: printf("February\n"); break;
// ...
}
// if/else — necessary for ranges
if (grade >= 9.0) {
printf("Outstanding\n");
} else if (grade >= 7.0) {
printf("Merit\n");
}
// This CANNOT be done with switch — grade is double
A complete program
#include <stdio.h>
int main() {
double grade;
int option;
char subject;
printf("=== GRADE SYSTEM ===\n\n");
printf("Enter grade (0-10): ");
scanf("%lf", &grade);
/* Validation with if */
if (grade < 0 || grade > 10) {
printf("Error: grade must be between 0 and 10\n");
return 1; /* exit with error code */
}
/* Classification with if/else if */
printf("\n--- Classification ---\n");
if (grade >= 9.0) {
printf("Outstanding\n");
} else if (grade >= 7.0) {
printf("Merit\n");
} else if (grade >= 5.0) {
printf("Passed\n");
} else {
printf("Failed\n");
}
/* Ternary operator */
printf("Status: %s\n", (grade >= 5.0) ? "PASS" : "FAIL");
/* Menu with switch */
printf("\nWhat do you want to do?\n");
printf("1. See grade as percentage\n");
printf("2. See points needed to pass\n");
printf("3. See grade letter\n");
printf("Option: ");
scanf("%d", &option);
switch (option) {
case 1:
printf("Percentage: %.1f%%\n", grade * 10);
break;
case 2:
if (grade >= 5.0) {
printf("Already passed — %.1f points above pass mark\n",
grade - 5.0);
} else {
printf("Need %.1f more points to pass\n", 5.0 - grade);
}
break;
case 3:
if (grade >= 9.0) subject = 'A';
else if (grade >= 7.0) subject = 'B';
else if (grade >= 5.0) subject = 'C';
else subject = 'F';
printf("Letter grade: %c\n", subject);
break;
default:
printf("Invalid option\n");
}
return 0;
}
Compile and run:
gcc grade_system.c -o grade_system -Wall ./grade_system
Visualise with Python Tutor
Select C from the dropdown and paste in pythontutor.com:
#include <stdio.h>
int main() {
int x = 5;
if (x > 3 && x < 10) {
printf("Between 3 and 10\n");
}
switch (x) {
case 3: printf("Three\n"); break;
case 5: printf("Five\n"); break;
case 7: printf("Seven\n"); break;
default: printf("Other\n");
}
return 0;
}
Step through it and watch how C evaluates x > 3 && x < 10 — both conditions in sequence. Then watch how the switch jumps directly to case 5 without checking cases 3 or 7. Compare this with an if/else if chain where Python/C evaluate each condition in order until one matches — switch is more efficient for exact value matching because it can jump directly to the right case.
Quick summary
/* IF/ELSE IF/ELSE */
if (condition) {
/* runs if condition is true */
} else if (other_condition) {
/* runs if other_condition is true */
} else {
/* runs if no condition is true */
}
/* MANDATORY RULES */
/* 1. Condition in parentheses: if (x > 5) */
/* 2. Always use { } — even for single statements */
/* 3. == to compare, = to assign — never mix them */
/* 4. elif in Python = else if in C (two words) */
/* COMPARISON OPERATORS */
== != > < >= <=
/* LOGICAL OPERATORS */
/* Python: and or not */
/* C: && || ! */
/* TERNARY OPERATOR */
type var = (condition) ? value_if_true : value_if_false;
/* SWITCH */
switch (variable) { /* int or char only — not double */
case value1:
/* code */
break; /* mandatory — prevents fall-through */
case value2:
/* code */
break;
default:
/* code */
}
/* SWITCH vs IF/ELSE */
/* switch → exact int/char values, 3+ cases */
/* if/else → ranges, doubles, complex conditions */
/* = vs == TRAP */
if (x = 5) /* assigns 5 to x, always true — BUG */
if (x == 5) /* compares x with 5 — correct */
/* Use -Wall flag to catch this: gcc ... -Wall */
/* FALL-THROUGH — without break all cases below execute */
/* Intentional use: multiple cases, same action */
case 1:
case 2:
case 3:
printf("1, 2 or 3\n");
break;
In the next article we practice C conditionals with three real programs in Fedora.

One Comment