Operators and Expressions
Operators are like kitchen tools — you use a knife for chopping and a pan for frying. Different ingredients need different tools, and different calculations need different operators.
Arithmetic Operators
C provides 7 basic arithmetic operators for the most common mathematical calculations.
| Operator | Meaning | Example | Result |
|---|---|---|---|
+ |
Addition | 5 + 3 |
8 |
- |
Subtraction | 5 - 3 |
2 |
* |
Multiplication | 5 * 3 |
15 |
/ |
Division | 7 / 2 |
3 |
% |
Modulo | 7 % 2 |
1 |
+ |
Unary plus | +5 |
5 |
- |
Unary minus | -5 |
-5 |
The Integer Division Trap
When two integers are divided, the result is also an integer — the fractional part is simply discarded, not rounded.
#include <stdio.h>
int main(void) {
int a = 7;
int b = 2;
printf("%d / %d = %d\n", a, b, a / b);
printf("%d %% %d = %d\n", a, b, a % b);
return 0;
}
7 / 2 = 3
7 % 2 = 1
7.0 / 2 gives 3.5.
Uses of the Modulo Operator
The modulo operator % only works with integers. It has several very practical use cases:
- Checking even/odd:
n % 2equals 0 means even - Getting the last digit:
n % 10gives the ones place - Circular indexing:
i % sizekeeps the index cycling between 0 and size-1
#include <stdio.h>
int main(void) {
int n = 12345;
printf("Last digit: %d\n", n % 10);
printf("Is even: %s\n", n % 2 == 0 ? "Yes" : "No");
return 0;
}
Last digit: 5
Is even: No
Increment and Decrement Operators
The increment operator ++ adds 1 to a variable, and -- subtracts 1. Each comes in two forms: prefix and postfix, which differ in what the expression returns.
Prefix vs. Postfix
| Form | Name | Effect | Expression Value |
|---|---|---|---|
++i |
Prefix increment | i increases by 1 | The new (increased) value |
i++ |
Postfix increment | i increases by 1 | The old (original) value |
--i |
Prefix decrement | i decreases by 1 | The new (decreased) value |
i-- |
Postfix decrement | i decreases by 1 | The old (original) value |
#include <stdio.h>
int main(void) {
int a = 5;
int b = ++a;
printf("Prefix: a=%d, b=%d\n", a, b);
int c = 5;
int d = c++;
printf("Postfix: c=%d, d=%d\n", c, d);
return 0;
}
Prefix: a=6, b=6
Postfix: c=6, d=5
a = ++a + a++. The behavior is undefined, and different compilers will give different results.
Relational Operators
Relational operators compare two values, returning "true" (1) or "false" (0).
| Operator | Meaning | Example | Result |
|---|---|---|---|
== |
Equal to | 5 == 5 |
1 |
!= |
Not equal to | 5 != 3 |
1 |
< |
Less than | 3 < 5 |
1 |
> |
Greater than | 3 > 5 |
0 |
<= |
Less than or equal | 5 <= 5 |
1 |
>= |
Greater than or equal | 3 >= 5 |
0 |
#include <stdio.h>
int main(void) {
int a = 10;
int b = 20;
printf("a == b: %d\n", a == b);
printf("a != b: %d\n", a != b);
printf("a < b: %d\n", a < b);
return 0;
}
a == b: 0
a != b: 1
a < b: 1
== is comparison, = is assignment. Mixing them up turns the comparison into an assignment that won't produce an error. A good habit is to put the constant on the left: 5 == a — if you accidentally write 5 = a, the compiler will catch it.
Logical Operators
Logical operators combine multiple conditions, also returning 1 (true) or 0 (false).
| Operator | Meaning | Example | Result |
|---|---|---|---|
&& |
Logical AND | 1 && 0 |
0 |
| ` | ` | Logical OR | |
! |
Logical NOT | !0 |
1 |
Truth Table
| A | B | A && B | A || B | !A | |---|---|--------|--------|----| | 0 | 0 | 0 | 0 | 1 | | 0 | 1 | 0 | 1 | 1 | | 1 | 0 | 0 | 1 | 0 | | 1 | 1 | 1 | 1 | 0 |
Short-Circuit Evaluation
With &&, if the left side is false, the right side is never evaluated. With ||, if the left side is true, the right side is skipped. This feature can be used to avoid illegal operations:
#include <stdio.h>
int main(void) {
int divisor = 0;
int value = 10;
if (divisor != 0 && value / divisor > 5) {
printf("Condition met\n");
} else {
printf("Condition not met, and no division by zero\n");
}
return 0;
}
Condition not met, and no division by zero
-5 is "true" in a logical context.
Assignment Operators
The basic assignment operator = stores the right-hand value into the left-hand variable. C also provides compound assignment operators that combine an operation with assignment.
| Compound | Equivalent |
|---|---|
a += b |
a = a + b |
a -= b |
a = a - b |
a *= b |
a = a * b |
a /= b |
a = a / b |
a %= b |
a = a % b |
#include <stdio.h>
int main(void) {
int score = 80;
score += 10;
printf("After bonus: %d\n", score);
score -= 25;
printf("After penalty: %d\n", score);
score *= 2;
printf("After doubling: %d\n", score);
return 0;
}
After bonus: 90
After penalty: 65
After doubling: 130
The Conditional Operator (Ternary Operator)
The conditional operator ?: is C's only ternary operator. Its syntax is:
condition ? expression1 : expression2
If the condition is true, expression1 is evaluated; otherwise, expression2 is evaluated. It's a shorthand for if-else.
#include <stdio.h>
int main(void) {
int age = 20;
char *status = age >= 18 ? "Adult" : "Minor";
printf("Age %d, %s\n", age, status);
int a = 15, b = 28;
int max = a > b ? a : b;
printf("Larger value: %d\n", max);
return 0;
}
Age 20, Adult
Larger value: 28
The Comma Operator
The comma operator , evaluates each expression from left to right, and the value of the entire comma expression is the value of the last expression.
#include <stdio.h>
int main(void) {
int a, b, c;
c = (a = 1, b = 2, a + b);
printf("a=%d, b=%d, c=%d\n", a, b, c);
return 0;
}
a=1, b=2, c=3
The sizeof Operator
sizeof returns the number of bytes a data type or variable occupies in memory. It's evaluated at compile time, not runtime.
#include <stdio.h>
int main(void) {
printf("char: %zu bytes\n", sizeof(char));
printf("int: %zu bytes\n", sizeof(int));
printf("float: %zu bytes\n", sizeof(float));
printf("double: %zu bytes\n", sizeof(double));
int arr[5] = {1, 2, 3, 4, 5};
printf("Array total size: %zu bytes\n", sizeof(arr));
printf("Array element count: %zu\n", sizeof(arr) / sizeof(arr[0]));
return 0;
}
char: 1 bytes
int: 4 bytes
float: 4 bytes
double: 8 bytes
Array total size: 20 bytes
Array element count: 5
sizeof requires parentheses for type names (sizeof(int)) but not for variables (sizeof a). However, for consistency, it's best to always use parentheses.
Operator Precedence
When an expression contains multiple operators, the one with higher precedence is evaluated first. The table below lists them from highest to lowest:
| Precedence | Operators | Associativity |
|---|---|---|
| 1 (highest) | () [] -> . |
Left to right |
| 2 | ! ~ ++ -- +(unary) -(unary) *(dereference) &(address-of) sizeof |
Right 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 | ^ |
Left to right |
| 10 | ` | ` |
| 11 | && |
Left to right |
| 12 | ` | |
| 13 | ?: |
Right to left |
| 14 | = += -= *= /= %= etc. |
Right to left |
| 15 (lowest) | , |
Left to right |
Example
Combine various operators to calculate the sum of each digit in a three-digit number:
#include <stdio.h>
int main(void) {
int num = 952;
int hundreds = num / 100;
int tens = (num / 10) % 10;
int ones = num % 10;
int sum = hundreds + tens + ones;
printf("Number: %d\n", num);
printf("Hundreds: %d, Tens: %d, Ones: %d\n", hundreds, tens, ones);
printf("Sum of digits: %d\n", sum);
return 0;
}
Number: 952
Hundreds: 9, Tens: 5, Ones: 2
Sum of digits: 16
Example
Use logical and relational operators to determine whether a year is a leap year:
#include <stdio.h>
int main(void) {
int year = 2024;
int is_leap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
printf("%d is %sa leap year\n", year, is_leap ? "" : "not ");
return 0;
}
2024 is a leap year
Type Conversion
Implicit Conversion
When different types are mixed in an expression, the compiler automatically converts the lower-precision type to the higher-precision type:
#include <stdio.h>
int main(void) {
int a = 5;
double b = 2.0;
double c = a / b;
printf("5 / 2.0 = %f\n", c);
char ch = 'A';
int code = ch + 1;
printf("'A' + 1 = %c (ASCII %d)\n", code, code);
return 0;
}
5 / 2.0 = 2.500000
'A' + 1 = B (ASCII 66)
Conversion direction: char → int → long → double, int → unsigned → long → double.
Explicit Casting
Use (type_name) to force a value to a specific type:
#include <stdio.h>
int main(void) {
int a = 7, b = 2;
double result = (double)a / b;
printf("With cast: %f\n", result);
return 0;
}
With cast: 3.500000
❓ FAQ
a++ and ++a when used on their own line?= and == straight?= is assignment ("becomes"), == is comparison ("equals?"). Writing if (a = 0) by mistake won't cause an error but completely changes the logic. A good habit: put the constant on the left — if (0 == a) — so a typo like if (0 = a) will be caught by the compiler.% operator be used with floating-point numbers?% only works with integer types. For floating-point modulo, use the fmod() function from #include <math.h>.📖 Summary
- In arithmetic, integer division truncates the decimal part; modulo only works with integers
++/--prefix returns the new value, postfix returns the old; avoid using them multiple times on the same variable in one expression- Relational operators return 0 or 1; watch out for confusing
=with== - Logical operators
&&and||short-circuit, which can protect the right-hand expression - Don't memorize precedence — when uncertain, add parentheses
📝 Exercises
- Write a program that takes a number of seconds (e.g. 3661) and uses
/and%to calculate the corresponding hours, minutes, and seconds, then outputs the result. - Write a program that takes two integers and uses the ternary operator to find and output the larger and smaller values.
- Write a program that uses
sizeofto print the sizes ofshort,int,long, andlong longon your computer and observe the results.



