Making Comparisons: A Complete Guide to Relational Operators in C

Relational operators are the building blocks of decision-making in C programs. They allow you to compare values and determine relationships between them, producing results that control program flow through if statements, loops, and other conditional constructs. Understanding how these operators work—and their subtle behaviors—is essential for writing correct and efficient C code.

What Are Relational Operators?

Relational operators compare two operands and return either true (1) or false (0). They're used to create conditions that determine which path a program takes.

OperatorMeaningExampleResult
==Equal to5 == 51 (true)
!=Not equal to5 != 31 (true)
<Less than3 < 51 (true)
>Greater than5 > 31 (true)
<=Less than or equal to5 <= 51 (true)
>=Greater than or equal to5 >= 31 (true)

Basic Examples

#include <stdio.h>
int main() {
int a = 10, b = 20, c = 10;
printf("a = %d, b = %d, c = %d\n\n", a, b, c);
printf("a == b: %d\n", a == b);  // 0 (false)
printf("a != b: %d\n", a != b);  // 1 (true)
printf("a < b:  %d\n", a < b);   // 1 (true)
printf("a > b:  %d\n", a > b);   // 0 (false)
printf("a <= c: %d\n", a <= c);  // 1 (true)
printf("a >= c: %d\n", a >= c);  // 1 (true)
return 0;
}

Output:

a = 10, b = 20, c = 10
a == b: 0
a != b: 1
a < b:  1
a > b:  0
a <= c: 1
a >= c: 1

Using Relational Operators in Conditions

Relational operators are most commonly used in control structures:

#include <stdio.h>
int main() {
int score;
printf("Enter your test score (0-100): ");
scanf("%d", &score);
if (score >= 90) {
printf("Grade: A\n");
} else if (score >= 80) {
printf("Grade: B\n");
} else if (score >= 70) {
printf("Grade: C\n");
} else if (score >= 60) {
printf("Grade: D\n");
} else {
printf("Grade: F\n");
}
// Using relational operators in loops
int i = 1;
while (i <= 5) {
printf("%d ", i);
i++;
}
printf("\n");
return 0;
}

Common Pitfalls

1. Confusing = and ==

The single most common mistake in C programming:

#include <stdio.h>
int main() {
int x = 5;
// WRONG - assignment, not comparison
if (x = 10) {  // Assigns 10 to x, then tests x (which is now 10, true)
printf("This ALWAYS prints!\n");
}
// CORRECT - comparison
if (x == 10) {
printf("This prints only if x equals 10\n");
}
// Safer style to avoid this bug
if (10 == x) {  // If you accidentally write "10 = x", compiler error!
printf("x is 10\n");
}
return 0;
}

2. Floating-Point Comparisons

Floating-point arithmetic can lead to unexpected results:

#include <stdio.h>
#include <math.h>
int main() {
double a = 0.1 + 0.2;
double b = 0.3;
printf("0.1 + 0.2 = %.20f\n", a);
printf("0.3 = %.20f\n", b);
// This may not be true due to floating-point precision
if (a == b) {
printf("a equals b\n");
} else {
printf("a does NOT equal b\n");
}
// Correct way: use an epsilon (tolerance)
double epsilon = 0.0000001;
if (fabs(a - b) < epsilon) {
printf("a is approximately equal to b\n");
}
return 0;
}

Output:

0.1 + 0.2 = 0.30000000000000004441
0.3 = 0.29999999999999998890
a does NOT equal b
a is approximately equal to b

3. Character Comparisons

#include <stdio.h>
#include <ctype.h>
int main() {
char ch = 'M';
// Comparing characters (based on ASCII values)
if (ch >= 'A' && ch <= 'Z') {
printf("%c is an uppercase letter\n", ch);
}
if (ch >= 'a' && ch <= 'z') {
printf("%c is a lowercase letter\n", ch);
}
// Better to use ctype.h functions
if (isupper(ch)) {
printf("%c is uppercase (using isupper)\n", ch);
}
// Case conversion based on relational comparisons
char lower = ch + ('a' - 'A');  // Convert to lowercase
printf("Lowercase of %c is %c\n", ch, lower);
return 0;
}

Relational Operators with Different Types

When comparing different types, C performs implicit conversions:

#include <stdio.h>
int main() {
int i = 10;
float f = 10.0;
double d = 9.999;
char c = 'A';  // ASCII value 65
printf("int vs float: %d == %f is %d\n", i, f, i == f);  // 1 (true)
printf("int vs double: %d < %f is %d\n", i, d, i < d);    // 0 (false)
printf("char vs int: '%c' (%d) > 60 is %d\n", c, c, c > 60);  // 1 (true)
// Integer promotion rules
short s = 32767;
int result = s > 30000;  // s promoted to int for comparison
printf("short > 30000: %d\n", result);
return 0;
}

Chaining Relational Operators (Common Mistake)

C does not support mathematical-style chaining:

#include <stdio.h>
int main() {
int x = 5;
// WRONG - this does NOT check if x is between 1 and 10
if (1 < x < 10) {
printf("This ALWAYS prints for any x > 1\n");
// Why? Because (1 < x) evaluates to 0 or 1, which is always < 10
}
// CORRECT - use logical AND
if (x > 1 && x < 10) {
printf("x is between 1 and 10\n");
}
return 0;
}

Step-by-step of the wrong version:

// For x = 5:
// 1 < 5 < 10
// (1 < 5) evaluates to 1 (true)
// 1 < 10 evaluates to 1 (true)
// Result is true regardless of x!
// For x = 100:
// 1 < 100 < 10
// (1 < 100) evaluates to 1 (true)
// 1 < 10 evaluates to 1 (true)
// Still true!

Truth Values in C

In C, relational operators return int values: 1 for true, 0 for false.

#include <stdio.h>
int main() {
int result;
result = (5 > 3);
printf("5 > 3 returns: %d\n", result);  // 1
result = (5 < 3);
printf("5 < 3 returns: %d\n", result);  // 0
// You can use these values in arithmetic!
int count = 0;
count += (5 > 3);  // Adds 1
count += (5 < 3);  // Adds 0
printf("Count: %d\n", count);  // 1
// Counting how many conditions are true
int a = 10, b = 20, c = 30;
int trueCount = (a > b) + (b > c) + (a < c);
printf("Number of true conditions: %d\n", trueCount);  // 1 (only a < c is true)
return 0;
}

Practical Examples

Example 1: Simple Calculator with Validation

#include <stdio.h>
int main() {
char operator;
double num1, num2;
printf("Enter operator (+, -, *, /): ");
scanf("%c", &operator);
printf("Enter two numbers: ");
scanf("%lf %lf", &num1, &num2);
// Validate operator
if (operator != '+' && operator != '-' && 
operator != '*' && operator != '/') {
printf("Invalid operator!\n");
return 1;
}
// Validate division by zero
if (operator == '/' && num2 == 0) {
printf("Error: Division by zero!\n");
return 1;
}
// Perform calculation
if (operator == '+')
printf("%.2f + %.2f = %.2f\n", num1, num2, num1 + num2);
else if (operator == '-')
printf("%.2f - %.2f = %.2f\n", num1, num2, num1 - num2);
else if (operator == '*')
printf("%.2f * %.2f = %.2f\n", num1, num2, num1 * num2);
else
printf("%.2f / %.2f = %.2f\n", num1, num2, num1 / num2);
return 0;
}

Example 2: Leap Year Detection

#include <stdio.h>
int main() {
int year;
printf("Enter a year: ");
scanf("%d", &year);
// Leap year rules:
// Divisible by 4 AND (not divisible by 100 OR divisible by 400)
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) {
printf("%d is a leap year\n", year);
} else {
printf("%d is not a leap year\n", year);
}
return 0;
}

Example 3: Temperature Converter with Alerts

#include <stdio.h>
int main() {
double celsius, fahrenheit;
int choice;
printf("Temperature Converter\n");
printf("1. Celsius to Fahrenheit\n");
printf("2. Fahrenheit to Celsius\n");
printf("Enter choice: ");
scanf("%d", &choice);
if (choice == 1) {
printf("Enter temperature in Celsius: ");
scanf("%lf", &celsius);
fahrenheit = (celsius * 9/5) + 32;
printf("%.1f°C = %.1f°F\n", celsius, fahrenheit);
} else if (choice == 2) {
printf("Enter temperature in Fahrenheit: ");
scanf("%lf", &fahrenheit);
celsius = (fahrenheit - 32) * 5/9;
printf("%.1f°F = %.1f°C\n", fahrenheit, celsius);
} else {
printf("Invalid choice!\n");
return 1;
}
// Weather alerts based on temperature
if (choice == 1) {
if (celsius > 40)
printf("🔥 Extreme heat warning!\n");
else if (celsius > 30)
printf("☀️ Hot day\n");
else if (celsius < 0)
printf("❄️ Freezing conditions!\n");
}
return 0;
}

Example 4: Sorting Three Numbers

#include <stdio.h>
int main() {
int a, b, c;
int temp;
printf("Enter three numbers: ");
scanf("%d %d %d", &a, &b, &c);
printf("Original order: %d, %d, %d\n", a, b, c);
// Sort using relational operators
if (a > b) {
temp = a;
a = b;
b = temp;
}
if (b > c) {
temp = b;
b = c;
c = temp;
}
if (a > b) {
temp = a;
a = b;
b = temp;
}
printf("Sorted order: %d, %d, %d\n", a, b, c);
// Check if they form a triangle
if (a + b > c && a + c > b && b + c > a) {
printf("These numbers can form a triangle.\n");
// Check triangle type
if (a == b && b == c)
printf("Equilateral triangle\n");
else if (a == b || b == c || a == c)
printf("Isosceles triangle\n");
else
printf("Scalene triangle\n");
} else {
printf("These numbers cannot form a triangle.\n");
}
return 0;
}

Example 5: Password Strength Checker

#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
char password[100];
int length;
int hasUpper = 0, hasLower = 0, hasDigit = 0, hasSpecial = 0;
int strength = 0;
printf("Enter a password: ");
scanf("%s", password);
length = strlen(password);
// Check each character
for (int i = 0; i < length; i++) {
if (isupper(password[i]))
hasUpper = 1;
else if (islower(password[i]))
hasLower = 1;
else if (isdigit(password[i]))
hasDigit = 1;
else
hasSpecial = 1;  // Assume any non-alphanumeric is special
}
// Calculate strength
strength = (hasUpper + hasLower + hasDigit + hasSpecial);
printf("\nPassword Analysis:\n");
printf("Length: %d characters\n", length);
printf("Uppercase: %s\n", hasUpper ? "Yes" : "No");
printf("Lowercase: %s\n", hasLower ? "Yes" : "No");
printf("Digits: %s\n", hasDigit ? "Yes" : "No");
printf("Special: %s\n", hasSpecial ? "Yes" : "No");
printf("\nStrength: ");
if (length >= 8 && strength >= 3)
printf("Strong\n");
else if (length >= 6 && strength >= 2)
printf("Medium\n");
else
printf("Weak\n");
// Specific recommendations
if (length < 8)
printf("Recommendation: Make password at least 8 characters\n");
if (!hasUpper)
printf("Recommendation: Add uppercase letters\n");
if (!hasLower)
printf("Recommendation: Add lowercase letters\n");
if (!hasDigit)
printf("Recommendation: Add digits\n");
if (!hasSpecial)
printf("Recommendation: Add special characters\n");
return 0;
}

Operator Precedence

Relational operators have lower precedence than arithmetic operators but higher than assignment operators:

#include <stdio.h>
int main() {
int result;
// Arithmetic happens before comparison
result = 5 + 3 > 2 * 4;  // (5+3) > (2*4) = 8 > 8 = 0
printf("5 + 3 > 2 * 4 = %d\n", result);  // 0
// Comparison happens before assignment
int x = 5, y = 10;
result = x < y;  // result = (x < y) = 1
printf("x < y = %d\n", result);  // 1
// Parentheses clarify intent
result = (x + 5) > (y - 3);
printf("(x + 5) > (y - 3) = %d\n", result);  // (10 > 7) = 1
return 0;
}

Precedence Table (highest to lowest):

LevelOperatorsAssociativity
1() [] -> .Left to right
2! ~ ++ -- + - * & sizeofRight to left
3* / %Left to right
4+ -Left to right
5< > <= >=Left to right
6== !=Left to right
7&&Left to right
8||Left to right
9?:Right to left
10= += -= etc.Right to left
11,Left to right

Relational Operators with Pointers

Pointers can be compared using relational operators:

#include <stdio.h>
int main() {
int arr[] = {10, 20, 30, 40, 50};
int *ptr1 = &arr[1];  // points to 20
int *ptr2 = &arr[3];  // points to 40
printf("ptr1 points to: %d\n", *ptr1);
printf("ptr2 points to: %d\n", *ptr2);
// Compare addresses
if (ptr1 < ptr2) {
printf("ptr1 is before ptr2 in memory\n");
}
// Check if pointer is within array bounds
int *start = arr;
int *end = &arr[4];
if (ptr1 >= start && ptr1 <= end) {
printf("ptr1 points to an element within the array\n");
}
// Pointer difference
printf("Elements between ptr1 and ptr2: %ld\n", ptr2 - ptr1);
return 0;
}

Short-Circuit Evaluation

Relational operators combined with logical operators use short-circuit evaluation:

#include <stdio.h>
int main() {
int x = 5;
int y = 0;
// Short-circuit: if x > 10 is false, y/x is never evaluated
if (x > 10 && (y / x) > 0) {
printf("This won't execute\n");
} else {
printf("Safe - division was never attempted\n");
}
// This is safe because of short-circuiting
if (x != 0 && (y / x) > 0) {
printf("Division safe because x != 0\n");
}
// OR short-circuit: if first is true, second not evaluated
if (x > 0 || (y / x) > 0) {
printf("First condition true, division never evaluated\n");
}
return 0;
}

Common Interview Questions

Q: What's the output of this code?

int x = 5;
int y = 10;
int z = 15;
printf("%d", x < y < z);

A: 1 (true) because x < y evaluates to 1 (true), then 1 < z is true. This demonstrates why chaining doesn't work as expected.

Q: What's the difference between = and ==?
A: = is assignment, == is comparison. Using = in a condition often leads to bugs.

Q: Why can't we compare floating-point numbers directly?
A: Due to precision errors, floating-point calculations may produce slightly different results. Use an epsilon tolerance instead.

Best Practices

  1. Use parentheses for clarity, even when not strictly needed
  2. Don't confuse = with == – consider the constant == variable style
  3. Use epsilon for float comparisons – never compare floats with ==
  4. Avoid chaining – use && and || instead
  5. Consider signed/unsigned comparisons – mixing can cause subtle bugs
  6. Use meaningful variable names – makes conditions self-documenting
  7. Keep conditions simple – complex conditions can be broken into smaller pieces

Common Mistakes Checklist

  • [ ] Using = instead of == in conditions
  • [ ] Chaining comparisons like a < b < c
  • [ ] Comparing floating-point numbers directly
  • [ ] Forgetting about integer promotion rules
  • [ ] Not considering short-circuit evaluation
  • [ ] Mixing signed and unsigned comparisons
  • [ ] Assuming relational operators return boolean (they return int)

Conclusion

Relational operators are fundamental to C programming, enabling programs to make decisions based on comparisons. While they seem simple, their proper use requires understanding of:

  • True/false representation as 1 and 0
  • Operator precedence relative to other operators
  • Type conversions when comparing different types
  • Short-circuit evaluation in logical expressions
  • Floating-point precision issues

Mastering relational operators is essential for writing correct control flow in C. Combined with logical operators (&&, ||, !), they form the basis of all decision-making in your programs. Always remember: a single misplaced equals sign can turn a working program into a buggy one, so pay attention to the details!

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper