In this blog post, we will explore equality and relational operators in C programming with simple code examples. These operators are widely used in decision-making and loop constructs, so mastering them is essential for writing correct and efficient programs.
What Are Relational and Equality Operators?
Relational and equality operators are binary operators in C. Their purpose is to compare values and return the result of that comparison. They compare two operands and return an integer result:
- They return 1 (true) if the condition is satisfied.
- They return 0 (false) if the condition is not satisfied.
👉 Note: The result of any relational or equality expression is always of type int.
List of relational and equality operators:
The following table shows the operators (relational and equality), their purpose, and some examples:
| Operator | Relationship Tested | Example | Result |
|---|---|---|---|
> |
First operand greater than second operand | 10 > 2 |
1 |
>= |
First operand greater than or equal to second operand | 13 >= 14 |
0 |
< |
First operand less than second operand | 40 < 15 |
0 |
<= |
First operand less than or equal to second operand | 16 <= 27 |
1 |
== |
First operand equal to second operand | 18==17 |
0 |
!= |
First operand not equal to second operand | 13 != 5 |
1 |
Note:Â The equality operators (==, !=) have lower precedence than relational operators (<, <=, >, >=).
Relational Operators in C With Example:
Here is a simple C program that demonstrates all relational and equality operators:
#include<stdio.h>
int main()
{
int a = 6, b = 27;
printf("a = %d\n", a);
printf("b = %d\n\n", b);
// Test a is greater than b?
printf("a > b : %d\n", a > b);
// Test a is greater than or equal to b?
printf("a >= b : %d\n", a >= b);
// Test a is smaller than b?
printf("a < b : %d\n", a < b);
// Test a is smaller than or equal to b?
printf("a <= b : %d\n", a <= b);
// Test a is equal to b?
printf("a == b : %d\n", a == b);
// Test a is not equal to b?
printf("a != b : %d\n", a != b);
return 0;
}
Output:

Precedence And Associativity of Relational Operator:
In C, operator precedence determines the order in which expressions are evaluated, while associativity defines the direction (left-to-right or right-to-left) in which operators of the same precedence are processed. Together, they control how complex expressions are resolved.
- Equality operators (
==, !=) have the same precedence and are evaluated left to right. - Relational operators (
<, <=, >, >=) also share the same precedence and are evaluated left to right. - Relational operators have higher precedence than equality operators. This means that in mixed expressions, comparisons like <, >, <=, >= are evaluated before equality checks (==, !=).
Why Is This Important?
Let’s walk through a couple of examples:
Example 1:
int c = 0 == 5 > 7;
Step 1: Evaluate 5 > 7 (precedence high among mentioned operator).
int c = 0 == 0;
Step 2: Evaluate 0 == 0 (precedence higher than =).
int c = 1;
Step 3: Evaluate c = 1
Now c contains 1.
Example 2:
int c = 0 < 15 > 7(precedence same so associate from left to right).
Step 1: Evaluate 0 < 15
int c = 1 > 7
Step 2: Evaluate 1 > 7 (precedence higher than =)
int c = 0
Step 3: Evaluate c = 0
Now c contains 0.
⚠️ Best Practice: Always use parentheses () to make expressions clear. This avoids confusion and prevents unexpected results due to operator precedence.
Real-World Applications of Relational and Equality Operators in Embedded Systems:
Relational and equality operators are heavily used in microcontroller programming where decisions are made based on sensor inputs, status flags, and hardware registers. Let’s see some practical embedded use cases:
1. Checking Sensor Thresholds:
In embedded applications, sensors often provide analog or digital readings. Relational operators help in decision-making based on threshold values. It used in industrial controllers, home appliances, automotive systems.
#include <stdio.h>
int temperature = 70; // Suppose sensor reading in °C
int main()
{
if (temperature > 65)
{
// Activate cooling fan
printf("Fan ON: Temperature too high!\n");
}
else
{
printf("Fan OFF: Temperature normal.\n");
}
return 0;
}
2. Monitoring Status Flags:
In microcontroller peripherals, status flags are often set or cleared in hardware registers. Using equality and relational operators, we can check these flags to decide whether data needs to be transmitted or not
#define UART_SR (*(volatile unsigned int*)0x40011000) // Dummy status register
#define UART_TXE (1 << 7) // Transmit data register empty flag
int main()
{
if ((UART_SR & UART_TXE) != 0)
{
// Transmit buffer empty, safe to send data
printf("UART ready to send data.\n");
}
return 0;
}
3. In an input button:
Equality operators are useful to check if a button state has changed. This helps prevent multiple triggers due to noise or bouncing.
#include <stdio.h>
int main()
{
int prevState = 0;
int currState = 1; // Assume we read the GPIO pin
if (currState != prevState)
{
printf("Button state changed!\n");
prevState = currState;
}
return 0;
}
There are many practical use cases for equality operators.
I believe now, you should have a solid understanding of how relational and equality operators work in C/C++ programming.
These examples show how these operators are key to real-time decisions in embedded systems, helping firmware respond correctly to sensors, user inputs, and system conditions.
Common Mistakes and Pitfalls with Relational and Equality Operators:
You should be careful when using these operators. Even experienced programmers can make subtle mistakes with them. Here are some key points to watch out for:
1. Using Assignment = Instead of Equality ==
A very common mistake in C programming is using the assignment operator = inside a condition when you actually mean to check for equality using ==.
Example of the mistake:
int a = 5;
if (a = 10) // ❌ Wrong! This assigns 10 to a
{
printf("Condition true\n");
}
Why it’s wrong:
- a = 10 assigns the value 10 to a instead of comparing it.
- The assignment expression itself evaluates to the assigned value (10 in this case).
- In C, any non-zero value is treated as true in a condition.
- As a result, the if condition always passes, even though the logical intent was to check if a equals 10.
Correct way:
if (a == 10)
{
printf("Condition true\n");
}
Tip: Some programmers use Yoda conditions to avoid this mistake:
// safer: compiler error if '=' is used by mistake
if (10 == a)
{
printf("Condition true\n");
}
2. Ignoring Operator Precedence
Sometimes, complex expressions without parentheses can produce unexpected results due to operator precedence rules in C.
Confusing example:
int c = 0 == 5 > 7; // ❌ Hard to read and error-prone
Here, the expression is evaluated according to C’s operator precedence:
>has higher precedence than ==, so 5 > 7 is evaluated first → 0 (false).- Then 0 == 0 → 1 (true), so c becomes 1.
- This may not match your intended logic.
Clear and correct approach:
int c = (0 == (5 > 7)); // âś… Explicit and readable
Tip:
- Always use parentheses to make your intent clear, especially in expressions with multiple operators.
- This improves readability and reduces subtle bugs.
3. Comparing Floating-Point Numbers Directly
Directly checking equality between floating-point numbers can lead to unexpected results due to precision errors in their representation.
Example of the problem:
#include <stdio.h>
int main()
{
float a = 0.1f * 10;
float b = 1.0f;
if (a == b)
{
printf("Equal\n");
}
else
{
printf("Not equal\n");
}
return 0;
}
Even though mathematically 0.1 * 10 equals 1.0, the condition may fail because floating-point numbers cannot always represent decimals exactly in memory.
Safer approach: Use a tolerance value (epsilon) to check if two floats are “close enough”:
#include <stdio.h>
#include <math.h>
#define EPSILON 0.0001f
int main()
{
float a = 0.1f * 10;
float b = 1.0f;
if (fabs(a - b) < EPSILON)
{
printf("Equal within tolerance\n");
}
else
{
printf("Not equal\n");
}
return 0;
}
Note: Never compare floating-point numbers directly with ==. Always account for a small tolerance to handle precision errors
4. Misreading Hardware Flags in Embedded Systems
In embedded systems, status registers often use bit flags to indicate hardware states. A common mistake is checking a flag using == 1 or == FLAG, which can fail if other bits are also set.
Example of the mistake:
if (UART_SR == UART_TXE) // Wrong, other bits may be set
{
// Might not work correctly
}
- UART_SR may have multiple bits set.
- Using
==UART_TXE checks all bits, so the condition fails if any other bit is high.
Correct way: Use bitwise AND to check only the relevant bit:
if ((UART_SR & UART_TXE) != 0) //Checks only the relevant bit
{
// Safe to send data
}
Explanation:
- UART_SR & UART_TXE isolates the specific flag bit.
- The condition is true if the flag is set, regardless of other bits.
Tip:
This technique is essential for safe and reliable hardware flag checking in embedded programming.
Key Takeaways from This Post:
- Relational and equality operators return an int (1 for true, 0 for false).
- Precedence matters: Relational operators (<, <=, >, >=) have higher precedence than equality operators (==, !=).
- Use parentheses: It make expressions safer, clearer, and easier to read.
- These operators are widely used in if-else conditions, loops, and logical checks in C programs.