10 Most Common Errors with Conditionals
In this tutorial, we’ll go over some of the most common errors that beginners (and even experienced programmers) make. This tutorial is designed to make you aware of these errors, so that you can spot them in your own code when you’re debugging your code.
Mistake 1: Missing Parentheses
While writing conditional statements, the most common error is to forget using parentheses around the condition.
Examine the following code:
// Incorrect code
#include <stdio.h>
int main() {
int x = 10;
if x > 5 { // Missing parentheses
printf("x is greater than 5");
}
return 0;
}
Output:
Error: expected '(' before 'x'
The C programming language doesn’t allow us to omit parentheses around the condition. The following is the correct one:
// Correct code
#include <stdio.h>
int main() {
int x = 10;
if (x > 5) { // Parentheses are added.
printf("x is greater than 5");
}
return 0;
}
Output:
x is greater than 5
Mistake 2: Mathematical Comparison
In mathematics, we are quite familiar with the comparisons like 0 <= x <= 10
. This comparison is used to check if the value of x falls between 0 and 10. However, the same comparison may not work in C programming as expected. Consider the following program:
// Incorrect code
#include <stdio.h>
int main() {
int x = 20;
if (0 <= x <= 10) {
printf("x lies between 0 and 10.");
}
return 0;
}
Output:
x lies between 0 and 10.
What’s wrong with the code? The compound condition 0 <= x <= 10
is not evaluated like we’d expect in math. First, 0 <= x
is evaluated, which results in 1 (True). Now, the condition becomes 1 <= 10
(it’s not that the value of x is compared with 10), which is also 1 (True). So the compound condition is True, and hence the output.
To avoid this situation, we need to re-write our code as follows:
// Correct code
#include <stdio.h>
int main() {
int x = 20;
if (0 >= x && x <= 10) {
printf("x lies between 0 and 10.");
}
return 0;
}
Output:
No Output
Mistake 3: Misusing Assignment Operators
The most common mistake among beginners is to confuse the assignment operator (=) with the equality operator (==). This potentially leads to unexpected output. Consider the following program:
// Incorrect code
#include <stdio.h>
int main() {
int x = 10;
if (x = 5) {
printf("x is 5");
} else {
printf("x is not 5");
}
return 0;
}
Output:
x is 5
Clearly, the output is incorrect as x is not 5; it is 10. The statement x = 5
assigns 5 to x. As the value of x is non-zero, therefore it is truthy (means it is True), and hence “x is 5” is printed on the screen. To avoid this situation, replace the assignment operator with the equality operator as shown:
// Correct code
#include <stdio.h>
int main() {
int x = 10;
if (x == 5) {
printf("x is 5");
} else {
printf("x is not 5");
}
return 0;
}
Output:
x is not 5
Now, the output is correct 🙂
Mistake 4: Semicolon after the if statement
Semicolons should only be placed after executable statements, like when calling the printf function or assigning a value to a variable. The if statement is not an executable statement, as it only checks a condition. Therefore, a semicolon should not be placed after the if statement.
The following program is incorrect:
// Incorrect code
#include <stdio.h>
int main() {
int x = 10;
if (x == 5); { // not allowed to add a semicolon here.
printf("x is 5");
}
return 0;
}
Output:
x is 5
This is not what we wanted. Right? Here’s why we’re getting “x is 5”. The block “{ printf(“x is 5″); }” is no longer part of the if statement because of the semicolon. Remember, the semicolon marks the end of the statement, and adding a semicolon after the if statement means that the following block is not part of the if statement. So, the condition “x == 5” has no effect on the printf function. The printf function will be evaluated regardless of whether x is 5 or not.
The correct version of the above program is as follows:
// Correct code
#include <stdio.h>
int main() {
int x = 10;
if (x == 5) {
printf("x is 5");
}
return 0;
}
Output:
No output
Mistake 5: Use of equality or inequality Operators with Strings
A string is a sequence of characters like a name of a person or may be someone’s home address. Although, it is fine to compare single characters using equality or inequality operators, but comparing strings is not a good idea.
Consider the following program in which character ‘A’ is compared with character ‘B’:
// Correct Code
#include <stdio.h>
int main() {
char ch = 'A';
if (ch == 'B') {
printf("The character is B.");
} else {
printf("The character is A.");
}
return 0;
}
Output:
The character is A.
The above code is working just fine. Now, consider the following code:
// Incorrect Code
#include <stdio.h>
int main() {
char* name = "Mike"; // This is how strings are defined in C. Nothing is wrong here.
if (name == "Mike") {
printf("Your name is Mike.");
} else {
printf("Your name is something else.");
}
return 0;
}
Output:
Your name is something else.
In C programming, when comparing strings, we should not use the equality (==) or inequality (!=) operators. These operators will compare the memory addresses of the two string literals, and not the actual content. So, in our program, name == “Mike”
is not necessarily true because the string literal “Mike” stored in the name
variable can have a different memory address than the string literal “Mike” to whom it is compared to.
Keep in mind that this behavior isn’t always guaranteed. You may get “Your name is Mike” as the output. This is because some compilers use string pooling or string interning to optimize memory usage. In other words, some compilers may store identical literals in the same memory location. So, it’s possible that the string literal “Mike” stored in the name
variable takes up the same memory location as the string literal “Mike”. This means we may get the correct output. But, in reality, the string literals aren’t being compared; their addresses are being compared. To ensure consistent behavior across all compilers, we shouldn’t use the equality or inequality operators with strings.
We’ll get into strings in more depth in future articles. If something isn’t clear, don’t worry, we’ll cover it in more detail later.
Mistake 6: Not taking care of Precedence Rules
Just like in math, multiplication and division should be done before addition and subtraction in an expression, the same thing goes for logical AND (&&) and logical OR (||) operators. The precedence of logical AND is greater than that of logical OR. So, the following two statements are not equivalent:
a && b || c
a && (b || c)
In the first statement, a&&b
is evaluated first followed by b || c
. In the second statement, the precedence of b || c
is increased because of the parentheses, and hence it will be evaluated first.
So, it is always advisable to use parentheses when necessary. However, the best practice is to use parentheses even when it is not necessary to express the intent of your code.
Mistake 7: Underestimating Short Circuiting
Consider the expression a && b
. If a is false, then it does not matter what b evaluates to. The entire expression is false. Similarly, if we consider a || b
, and if a evaluates to true, then it does not matter what b evaluates to. The entire expression is true. This means that based on the truth value of a, it might be possible that b will never be executed. This concept is called short circuiting. This is done to save some CPU cycles which are otherwise used to execute b. This is the reason why short circuiting is common among the vast majority of programming languages.
Short circuiting can be used for our own advantage. Consider the following lines of code:
if (a != NULL && a[0] == 5) {
// Some code.
}
Assume that there is an array ‘a’ (an array is simply a list of items. We will discuss more about it later.) whose first item we want to access and compare it with value 5. If both are equal, we will execute some code. What if there is no such array in the program? In that case, we are trying to access a memory location which does not exist. This may produce a “Segmentation Fault” error which indicates that we are trying to access a memory location which does not even exist. To avoid this, we can check if a is NULL
beforehand (NULL is a special value that indicates something does not exist). If a is NULL
, then we know that the first condition evaluates to true, which means that the second condition will not be evaluated because of short circuiting. In this way, we can avoid the program to run into an error.
So, short circuiting is pretty useful. We can use it to our advantage.
Mistake 8: Not Using Curly Braces for Multi-line Statements
It’s common to forget adding curly braces for multi-line statements because we’re used to not adding them for single-line statements. It’s easy to get lazy and skip adding curly braces for single-line statements, but this can cause us to forget to add them for multi-line statements too. This can lead to unexpected results.
For example, consider the following code in which the curly braces are intentionally omitted around the multi-line statements of the if statement.
#include <stdio.h>
int main() {
int x = -1;
if (x > 0)
printf("x is positive\n");
printf("This statement is always executed\n"); // Incorrect indentation
return 0;
}
Output:
This statement is always executed
The indentation might trick us into thinking the second printf() function is part of the conditional, but that’s not the case. In reality, only the first printf() function is part of the if statement. In the C programming language, indentation is just used to make the code look nice. It cannot and should never be used as a replacement for curly braces. So, it’s always a good idea to use curly braces even for single-line statements. This will help you avoid silly errors like this in your code.
The correct code is given as follows:
#include <stdio.h>
int main() {
int x = -1;
if (x > 0) {
printf("x is positive\n");
printf("This statement is always executed\n"); // Incorrect indentation
}
return 0;
}
Output:
No output
Mistake 9: Forgetting break in switch Statements
If you ask me to rank these mistakes from most common to least common among beginners, this one would be at the top of the list. People tend to forget adding
the break keyword after each case in the switch, which can lead to some
potentially unwanted output.
Here is the program demonstrating the same:
#include <stdio.h>
int main() {
int x = 1;
switch(x) {
case 1:
printf("Case 1\n");
case 2:
printf("Case 2\n");
case 3:
printf("Case 3\n");
default:
printf("Default case");
}
return 0;
}
Output:
Case 1
Case 2
Case 3
Default case
As x = 1
, we want that only case 1 should be evaluated. But, because of not adding the break keyword after each case, all the subsequent cases are executed too. The correct code is as follows:
#include <stdio.h>
int main() {
int x = 1;
switch(x) {
case 1:
printf("Case 1\n");
break;
case 2:
printf("Case 2\n");
break;
case 3:
printf("Case 3\n");
break;
default:
printf("Default case.");
}
return 0;
}
Output:
Case 1
Mistake 10: Not handling default case in switch Statements
Adding the default case at the end of a switch statement is a good way to handle the situation when none of the cases match the switch condition. If none of the cases match, then the default case will be executed. This can be used to display an error message or take corrective measures. If the default case is not added, then the statements following the switch statement will be executed.
Consider the following programs where the switch statements are written with and without default case:
Without default case:
#include <stdio.h>
int main() {
int option = 3;
switch (option) {
case 1:
printf("Option 1 selected\n");
break;
case 2:
printf("Option 2 selected\n");
break;
}
printf("Program continues after the switch statement\n");
return 0;
}
Output:
Program continues after the switch statement
As the default case is not mentioned, the printf()
function following the switch statement will be executed, and hence the output.
With default case:
#include <stdio.h>
int main() {
int option = 3;
switch (option) {
case 1:
printf("Option 1 selected\n");
break;
case 2:
printf("Option 2 selected\n");
break;
default:
printf("Invalid option!\n");
break;
}
printf("Program continues after the switch statement\n");
return 0;
}
Output:
Invalid option!
Program continues after the switch statement
This time, we’re properly handling the situation when none of the cases match. The default case has been executed, which makes it easier to catch errors in the program. It’s also helpful to tell users to enter the correct response.
Leave a comment