A Comprehensive Guide to Operators and Their Usage
In C programming, operators are symbols that tell the compiler to perform specific mathematical, relational, or logical operations. C provides a rich set of operators that can be classified based on their functionality.
Definition: An operator is a symbol that operates on a value or a variable to perform specific operations.
Operators work on operands. Based on the number of operands, operators can be:
++, --, !)+, -, *, /)?:)Arithmetic operators are used to perform mathematical operations like addition, subtraction, multiplication, division, etc.
| Operator | Description | Example | Result |
|---|---|---|---|
+ |
Addition | a + b |
Sum of a and b |
- |
Subtraction | a - b |
Difference of a and b |
* |
Multiplication | a * b |
Product of a and b |
/ |
Division | a / b |
Quotient of a divided by b |
% |
Modulus | a % b |
Remainder of a divided by b |
#include <stdio.h>
int main() {
int a = 10, b = 3;
printf("a + b = %d\n", a + b); // Output: 13
printf("a - b = %d\n", a - b); // Output: 7
printf("a * b = %d\n", a * b); // Output: 30
printf("a / b = %d\n", a / b); // Output: 3
printf("a %% b = %d\n", a % b); // Output: 1
return 0;
}
Note: The modulus operator (%) can only be used with integer operands. For floating-point numbers, use the fmod() function from the math library.
Relational operators are used to compare two values. They return 1 (true) or 0 (false) based on the comparison result.
| Operator | Description | Example | Result |
|---|---|---|---|
== |
Equal to | a == b |
1 if a equals b, else 0 |
!= |
Not equal to | a != b |
1 if a not equals b, else 0 |
> |
Greater than | a > b |
1 if a greater than b, else 0 |
< |
Less than | a < b |
1 if a less than b, else 0 |
>= |
Greater than or equal to | a >= b |
1 if a greater than or equal to b, else 0 |
<= |
Less than or equal to | a <= b |
1 if a less than or equal to b, else 0 |
#include <stdio.h>
int main() {
int a = 10, b = 5, c = 10;
printf("a == b: %d\n", a == b); // Output: 0
printf("a != b: %d\n", a != b); // Output: 1
printf("a > b: %d\n", a > b); // Output: 1
printf("a < b: %d\n", a < b); // Output: 0
printf("a >= c: %d\n", a >= c); // Output: 1
printf("a <= c: %d\n", a <= c); // Output: 1
return 0;
}
Common Mistake: Don't confuse the assignment operator (=) with the equality operator (==). Using = instead of == in conditions is a common error.
Logical operators are used to combine multiple conditions. They return 1 (true) or 0 (false) based on the logical operation.
| Operator | Description | Example | Result |
|---|---|---|---|
&& |
Logical AND | a && b |
1 if both a and b are true, else 0 |
|| |
Logical OR | a || b |
1 if either a or b is true, else 0 |
! |
Logical NOT | !a |
1 if a is false, else 0 |
#include <stdio.h>
int main() {
int a = 1, b = 0;
printf("a && b: %d\n", a && b); // Output: 0
printf("a || b: %d\n", a || b); // Output: 1
printf("!a: %d\n", !a); // Output: 0
printf("!b: %d\n", !b); // Output: 1
// Combining multiple conditions
int x = 5, y = 10, z = 15;
printf("(x < y) && (y < z): %d\n", (x < y) && (y < z)); // Output: 1
printf("(x > y) || (y < z): %d\n", (x > y) || (y < z)); // Output: 1
return 0;
}
Short-Circuit Evaluation: In logical expressions, C uses short-circuit evaluation. For &&, if the first operand is false, the second operand is not evaluated. For ||, if the first operand is true, the second operand is not evaluated.
Bitwise operators perform operations on individual bits of integer values. They are used for low-level programming.
| Operator | Description | Example | Result (for a=5, b=3) |
|---|---|---|---|
& |
Bitwise AND | a & b |
1 (0101 & 0011 = 0001) |
| |
Bitwise OR | a | b |
7 (0101 | 0011 = 0111) |
^ |
Bitwise XOR | a ^ b |
6 (0101 ^ 0011 = 0110) |
~ |
Bitwise NOT | ~a |
-6 (in two's complement) |
<< |
Left shift | a << 1 |
10 (0101 << 1 = 1010) |
>> |
Right shift | a >> 1 |
2 (0101 >> 1 = 0010) |
#include <stdio.h>
int main() {
unsigned int a = 5; // Binary: 0101
unsigned int b = 3; // Binary: 0011
printf("a & b = %u\n", a & b); // Output: 1 (0001)
printf("a | b = %u\n", a | b); // Output: 7 (0111)
printf("a ^ b = %u\n", a ^ b); // Output: 6 (0110)
printf("~a = %u\n", ~a); // Output: large number (depends on system)
printf("a << 1 = %u\n", a << 1); // Output: 10 (1010)
printf("a >> 1 = %u\n", a >> 1); // Output: 2 (0010)
return 0;
}
Note: Bitwise operators work on the binary representation of numbers. They are commonly used in systems programming, device drivers, and cryptography.
Assignment operators are used to assign values to variables. C provides simple assignment and compound assignment operators.
| Operator | Description | Example | Equivalent to |
|---|---|---|---|
= |
Simple assignment | a = b |
a = b |
+= |
Add and assign | a += b |
a = a + b |
-= |
Subtract and assign | a -= b |
a = a - b |
*= |
Multiply and assign | a *= b |
a = a * b |
/= |
Divide and assign | a /= b |
a = a / b |
%= |
Modulus and assign | a %= b |
a = a % b |
&= |
Bitwise AND and assign | a &= b |
a = a & b |
|= |
Bitwise OR and assign | a |= b |
a = a | b |
^= |
Bitwise XOR and assign | a ^= b |
a = a ^ b |
<<= |
Left shift and assign | a <<= b |
a = a << b |
>>= |
Right shift and assign | a >>= b |
a = a >> b |
#include <stdio.h>
int main() {
int a = 10;
a += 5; // a = a + 5 = 15
printf("After += 5: %d\n", a);
a -= 3; // a = a - 3 = 12
printf("After -= 3: %d\n", a);
a *= 2; // a = a * 2 = 24
printf("After *= 2: %d\n", a);
a /= 4; // a = a / 4 = 6
printf("After /= 4: %d\n", a);
a %= 4; // a = a % 4 = 2
printf("After %%= 4: %d\n", a);
return 0;
}
Note: Compound assignment operators are more efficient than their expanded equivalents because the variable is evaluated only once.
The conditional operator (?:) is a ternary operator that works like a compact if-else statement.
condition ? expression1 : expression2
If the condition is true, expression1 is evaluated and becomes the result. If the condition is false, expression2 is evaluated and becomes the result.
#include <stdio.h>
int main() {
int a = 10, b = 20;
int max;
// Using conditional operator to find maximum
max = (a > b) ? a : b;
printf("Maximum of %d and %d is %d\n", a, b, max);
// Using conditional operator in printf
printf("The larger number is %d\n", (a > b) ? a : b);
// Nested conditional operator
int c = 30;
int largest = (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
printf("Largest of %d, %d, and %d is %d\n", a, b, c, largest);
return 0;
}
Caution: While the conditional operator can make code more concise, overusing it or creating complex nested conditional expressions can reduce code readability.
The increment (++) and decrement (--) operators are used to increase or decrease the value of a variable by 1.
| Operator | Description | Example | Result |
|---|---|---|---|
++a |
Prefix increment | b = ++a; |
a is incremented first, then assigned to b |
a++ |
Postfix increment | b = a++; |
a is assigned to b first, then a is incremented |
--a |
Prefix decrement | b = --a; |
a is decremented first, then assigned to b |
a-- |
Postfix decrement | b = a--; |
a is assigned to b first, then a is decremented |
#include <stdio.h>
int main() {
int a = 5, b;
// Prefix increment
b = ++a;
printf("After b = ++a: a = %d, b = %d\n", a, b); // Output: a = 6, b = 6
// Reset a
a = 5;
// Postfix increment
b = a++;
printf("After b = a++: a = %d, b = %d\n", a, b); // Output: a = 6, b = 5
// Prefix decrement
a = 5;
b = --a;
printf("After b = --a: a = %d, b = %d\n", a, b); // Output: a = 4, b = 4
// Postfix decrement
a = 5;
b = a--;
printf("After b = a--: a = %d, b = %d\n", a, b); // Output: a = 4, b = 5
return 0;
}
Undefined Behavior: Avoid using increment or decrement operators multiple times on the same variable in the same expression (e.g., a = ++a + a++;). This leads to undefined behavior.
C provides some special operators that don't fit into the other categories.
,)The comma operator evaluates multiple expressions and returns the value of the last expression.
#include <stdio.h>
int main() {
int a, b, c;
// Comma operator in assignment
c = (a = 5, b = 10, a + b);
printf("a = %d, b = %d, c = %d\n", a, b, c); // Output: a=5, b=10, c=15
// Comma operator in for loop
for (a = 0, b = 10; a < b; a++, b--) {
printf("a = %d, b = %d\n", a, b);
}
return 0;
}
The sizeof operator returns the size in bytes of a data type or variable.
#include <stdio.h>
int main() {
printf("Size of int: %zu bytes\n", sizeof(int));
printf("Size of float: %zu bytes\n", sizeof(float));
printf("Size of double: %zu bytes\n", sizeof(double));
printf("Size of char: %zu bytes\n", sizeof(char));
int arr[10];
printf("Size of array: %zu bytes\n", sizeof(arr));
printf("Number of elements: %zu\n", sizeof(arr) / sizeof(arr[0]));
return 0;
}
& and *)The address-of operator (&) returns the memory address of a variable. The dereference operator (*) accesses the value at a memory address.
#include <stdio.h>
int main() {
int a = 10;
int *ptr = &a; // & gets the address of a
printf("Value of a: %d\n", a); // Output: 10
printf("Address of a: %p\n", &a); // Output: memory address
printf("Value via pointer: %d\n", *ptr); // Output: 10 (* dereferences the pointer)
*ptr = 20; // Change value through pointer
printf("New value of a: %d\n", a); // Output: 20
return 0;
}
Operator precedence determines the order in which operators are evaluated in an expression. Associativity determines the order when operators have the same precedence.
| Category | Operators | Associativity |
|---|---|---|
| Postfix | () [] -> . ++ -- |
Left to Right |
| Unary | + - ! ~ ++ -- & * (type) sizeof |
Right to Left |
| Multiplicative | * / % |
Left to Right |
| Additive | + - |
Left to Right |
| Shift | << >> |
Left to Right |
| Relational | < <= > >= |
Left to Right |
| Equality | == != |
Left to Right |
| Bitwise AND | & |
Left to Right |
| Bitwise XOR | ^ |
Left to Right |
| Bitwise OR | | |
Left to Right |
| Logical AND | && |
Left to Right |
| Logical OR | || |
Left to Right |
| Conditional | ?: |
Right to Left |
| Assignment | = += -= *= /= %= <<= >>= &= ^= |= |
Right to Left |
| Comma | , |
Left to Right |
#include <stdio.h>
int main() {
int a = 10, b = 5, c = 2;
int result;
// Multiplication has higher precedence than addition
result = a + b * c; // Equivalent to: a + (b * c) = 10 + 10 = 20
printf("a + b * c = %d\n", result);
// Parentheses change the order of evaluation
result = (a + b) * c; // Equivalent to: (a + b) * c = 15 * 2 = 30
printf("(a + b) * c = %d\n", result);
// Logical AND has higher precedence than logical OR
int x = 1, y = 0, z = 1;
int logical_result = x || y && z; // Equivalent to: x || (y && z) = 1 || 0 = 1
printf("x || y && z = %d\n", logical_result);
return 0;
}
Best Practice: When in doubt about operator precedence, use parentheses to make your intentions clear. This improves code readability and prevents errors.
#include <stdio.h>
int main() {
char operator;
double num1, num2, result;
printf("Enter an operator (+, -, *, /): ");
scanf("%c", &operator);
printf("Enter two numbers: ");
scanf("%lf %lf", &num1, &num2);
switch(operator) {
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
case '*':
result = num1 * num2;
break;
case '/':
if (num2 != 0) {
result = num1 / num2;
} else {
printf("Error: Division by zero\n");
return 1;
}
break;
default:
printf("Error: Invalid operator\n");
return 1;
}
printf("Result: %.2lf %c %.2lf = %.2lf\n", num1, operator, num2, result);
return 0;
}
#include <stdio.h>
// Function to print binary representation
void printBinary(unsigned int num) {
for (int i = 31; i >= 0; i--) {
printf("%d", (num >> i) & 1);
if (i % 8 == 0) printf(" ");
}
printf("\n");
}
int main() {
unsigned int a = 0b11001100; // Binary literal (C99+)
unsigned int b = 0b10101010;
printf("a: ");
printBinary(a);
printf("b: ");
printBinary(b);
printf("a & b: ");
printBinary(a & b);
printf("a | b: ");
printBinary(a | b);
printf("a ^ b: ");
printBinary(a ^ b);
printf("~a: ");
printBinary(~a);
printf("a << 2: ");
printBinary(a << 2);
printf("a >> 2: ");
printBinary(a >> 2);
return 0;
}
Programming Tip: Understanding operators is fundamental to writing effective C code. Practice using different operators and understand their precedence to write efficient and correct programs.