C Basics
Operators
Master Types of Operators (with tables & examples), Operator Precedence, and Type Conversion using LEARNCODEGURU’s 6-level learning model.
Level 1 Basics Content
C Operators Overview
An operator is a symbol that tells the compiler to perform a specific operation — arithmetic, comparison, logic, assignment, bit manipulation, and more. Operands are the values the operator works on. Mastering operators is essential before control statements and functions.
This level introduces every major operator category with reference tables, then covers a simple precedence overview, type conversion basics, and one complete sample program.
Overview of operators in C
Expressions combine operands and operators to produce a value. For example, in
a + b * c, * and + are operators; a,
b, and c are operands. Operators may be:
- Unary — one operand (
-x,!flag,++i) - Binary — two operands (
a + b,x == y) - Ternary — three operands (
cond ? a : b)
Types of operators in C
C groups operators into these major categories (covered one by one below):
- Arithmetic:
+-*/% - Relational:
==!=><>=<= - Logical:
&&||! - Assignment:
=+=-=*=/=%= - Increment / Decrement:
++--(pre and post) - Bitwise:
&|^~<<>> - Conditional (ternary):
? : - Special:
sizeof, cast(type), comma,
Arithmetic operators
Arithmetic operators perform basic math on numeric operands. With two int operands,
/ truncates toward zero and % yields the remainder.
| Operator | Meaning | Example | Result |
|---|---|---|---|
+ | Addition | 5 + 3 | 8 |
- | Subtraction | 5 - 3 | 2 |
* | Multiplication | 5 * 3 | 15 |
/ | Division | 7 / 2 | 3 (integer) |
% | Modulus (remainder) | 7 % 2 | 1 |
Tiny example: int q = 7 / 2; stores 3; int r = 7 % 2; stores 1.
Relational operators
Relational operators compare two values and produce 1 (true) or 0 (false).
They are the building blocks of if, loops, and the ternary operator.
| Operator | Meaning | Example | Result |
|---|---|---|---|
== | Equal to | 5 == 5 | 1 |
!= | Not equal to | 5 != 3 | 1 |
> | Greater than | 5 > 3 | 1 |
< | Less than | 5 < 3 | 0 |
>= | Greater or equal | 5 >= 5 | 1 |
<= | Less or equal | 3 <= 5 | 1 |
Tiny example: if (marks >= 40) checks pass/fail using a relational test.
== for comparison. A single = is assignment —
if (x = 5) assigns 5 and is always true (non-zero).
Logical operators
Logical operators combine or negate boolean conditions. They short-circuit: the right operand of
&& / || may be skipped (details in Level 2).
| Operator | Meaning | Example | Result |
|---|---|---|---|
&& | Logical AND | (5 > 3) && (2 < 4) | 1 |
|| | Logical OR | (5 < 3) || (2 < 4) | 1 |
! | Logical NOT | !(5 == 3) | 1 |
Tiny example: if (age >= 18 && age <= 60) checks a closed range.
Assignment operators
Assignment stores a value in a variable. Compound forms update a variable using its current value
in one step (x += 2 means x = x + 2).
| Operator | Meaning | Example | Result (if x was 10) |
|---|---|---|---|
= | Simple assign | x = 5 | x is 5 |
+= | Add and assign | x += 3 | 13 |
-= | Subtract and assign | x -= 3 | 7 |
*= | Multiply and assign | x *= 2 | 20 |
/= | Divide and assign | x /= 2 | 5 |
%= | Modulus and assign | x %= 3 | 1 |
Tiny example: sum += marks; accumulates marks into sum.
Increment and decrement (unary)
++ adds 1; -- subtracts 1. Prefix changes the value first,
then uses it. Postfix uses the old value first, then changes it.
| Operator | Meaning | Example | Result |
|---|---|---|---|
++x | Pre-increment | x = 5; y = ++x; | x=6, y=6 |
x++ | Post-increment | x = 5; y = x++; | y=5, then x=6 |
--x | Pre-decrement | x = 5; y = --x; | x=4, y=4 |
x-- | Post-decrement | x = 5; y = x--; | y=5, then x=4 |
Tiny example: Loop counters often use i++ in for loops.
Bitwise operators (basic)
Bitwise operators work on the binary representation of integers. They do not short-circuit. Useful for flags, masks, and low-level work.
| Operator | Meaning | Example | Result (bits) |
|---|---|---|---|
& | Bitwise AND | 5 & 3 | 1 (101 & 011) |
| | Bitwise OR | 5 | 3 | 7 |
^ | Bitwise XOR | 5 ^ 3 | 6 |
~ | Bitwise NOT (ones’ complement) | ~5 | depends on width (flips all bits) |
<< | Left shift | 5 << 1 | 10 |
>> | Right shift | 5 >> 1 | 2 |
Tiny example: flags & MASK tests whether selected bits are set.
Conditional (ternary) operator
The ternary operator chooses one of two values based on a condition:
condition ? value_if_true : value_if_false.
| Operator | Meaning | Example | Result |
|---|---|---|---|
? : | Conditional | (a > b) ? a : b | the larger of a and b |
Tiny example: char *msg = (n % 2 == 0) ? "even" : "odd";
Special operators — sizeof, cast, comma
These operators do not fit the arithmetic/relational groups but appear constantly in real C code.
| Operator | Meaning | Example | Result / role |
|---|---|---|---|
sizeof | Size in bytes | sizeof(int) | typically 4 (platform-dependent) |
(type) | Explicit cast | (float)7 / 2 | 3.5 |
, | Comma (sequence) | (a = 1, b = 2) | evaluates left→right; value is rightmost |
Tiny example: avg = (float)sum / count; forces floating-point division.
Operator precedence overview
When an expression mixes operators, precedence decides which binds first. Higher rows bind before lower rows. Full detail is in Level 2.
| Level (high → low) | Operators (intro) | Associativity |
|---|---|---|
| 1 (highest) | () [] -> . | Left → right |
| 2 | ++ -- (postfix), then unary + - ! ~ * & sizeof cast | Right → left (unary) |
| 3 | * / % | Left → right |
| 4 | + - | Left → right |
| 5 | Relational < <= > >=, then == != | Left → right |
| 6 | Bitwise / logical & ^ | && || | Left → right |
| 7 | Conditional ? : | Right → left |
| 8 (lowest here) | Assignment = += … | Right → left |
Rule of thumb: a + b * c is a + (b * c) because * outranks +.
Type conversion intro — implicit vs explicit
When operands have different types, C may convert them automatically (implicit), or you force a conversion with a cast (explicit).
- Implicit:
int x = 3.9;→ stores3(fraction dropped) - Implicit promotion:
char/shortoften becomeintin expressions - Explicit cast:
(float)a / bmakes floating-point division - Narrowing: assigning a larger type to a smaller type can lose data
Sample program — arithmetic + relational
This program reads two integers, computes arithmetic results, and uses a relational check to report which value is larger:
/* Operators demo — arithmetic + relational */
#include <stdio.h>
int main(void) {
int a, b;
printf("Enter two integers: ");
scanf("%d %d", &a, &b);
printf("Sum = %d\n", a + b);
printf("Product = %d\n", a * b);
printf("Quotient = %d, Remainder = %d\n", a / b, a % b);
if (a > b)
printf("%d is larger\n", a);
else if (a < b)
printf("%d is larger\n", b);
else
printf("Both are equal\n");
return 0;
}
+ * / % for arithmetic,
and > < for comparisons. Avoid dividing by zero in real programs.
Level 2 Advanced Content
Going deeper into operators
Level 1 named the operators. Level 2 explains how expressions are really evaluated: full precedence and associativity, pre vs post traps, short-circuit logic, integer division rules, and type conversion in depth — the material that shows up in exams and interviews.
Operator precedence & associativity (full table)
Precedence chooses which operator binds first. When two operators share the same precedence, associativity decides left-to-right or right-to-left grouping.
| Precedence | Operators | Associativity |
|---|---|---|
| 1 (highest) | () [] -> . postfix ++ -- | Left → right |
| 2 | Unary ++ -- + - ! ~ (type) * & sizeof | Right → left |
| 3 | * / % | Left → right |
| 4 | + - | Left → right |
| 5 | << >> | Left → right |
| 6 | < <= > >= | Left → right |
| 7 | == != | Left → right |
| 8 | & | Left → right |
| 9 | ^ | Left → right |
| 10 | | | Left → right |
| 11 | && | Left → right |
| 12 | || | Left → right |
| 13 | ? : | Right → left |
| 14 | = += -= *= /= %= … | Right → left |
| 15 (lowest) | Comma , | Left → right |
Left-to-right vs right-to-left associativity
Same-precedence operators still need a grouping rule:
- Left → right:
a - b - cmeans(a - b) - c - Left → right:
a / b * cmeans(a / b) * c - Right → left:
a = b = c = 0meansa = (b = (c = 0)) - Right → left: unary chains like
*p++follow unary associativity rules — parentheses help
int a = 20, b = 10, c = 5;
printf("%d\n", a - b - c); /* (20-10)-5 = 5 */
a = b = c = 0; /* all become 0 */
Pre vs post increment traps
Prefix and postfix differ in the value of the expression, not only in “when” the variable changes. Mixing multiple increments on the same variable in one expression is undefined behavior.
int x = 5; printf("%d", ++x);→ prints6,xis 6int x = 5; printf("%d", x++);→ prints5, thenxis 6a = a++;→ undefined — do not write thisi++ + ++i→ undefined — modify once per expression
++/-- alone on a line, or use them only
as the third clause of a for loop, until you are confident about sequencing.
Short-circuit evaluation of && and ||
Logical operators evaluate left-to-right and may skip the right operand:
false && anything→ right side not evaluatedtrue || anything→ right side not evaluated- Bitwise
&and|always evaluate both sides
int x = 0;
if (x != 0 && 10 / x > 1) /* safe: division skipped when x==0 */
printf("ok\n");
Integer division and modulus rules
When both operands of / or % are integers:
- Division truncates toward zero:
7/2 → 3,(-7)/2 → -3(C99+) - Modulus satisfies:
(a/b)*b + (a%b) == a(when defined) 7 % 2 → 1; sign of remainder follows dividend in modern C- Division or modulus by zero is undefined behavior
- Need decimals? Cast:
(double)a / b
Type conversion deep dive
C converts operands so both sides of an operator share a common type before computing:
- Integer promotions:
char/short→int(orunsigned int) - Usual arithmetic conversions: if one operand is
double, the other becomesdouble; elsefloat; else rank among integer types - Implicit assignment conversion: right-hand side converted to left-hand type
- Explicit cast:
(type)exprforces conversion at that point - Narrowing: larger → smaller may truncate or wrap; check ranges
int a = 7, b = 2;
double d = (double)a / b; /* 3.5 */
char c = (char)300; /* narrowing — lower bits kept */
How a + b * c is evaluated
Follow precedence first, then associativity. For a + b * c with
a=2, b=3, c=4:
Contrast: (a + b) * c forces addition first → (2+3)*4 = 20.
Parentheses always win over default precedence.
Level 3 C Tricky Interview Points
Advanced tricky interview points on operators, precedence, increment/decrement, short-circuit evaluation, and type conversion.
Tricky Interview Point-1:
a = a++ does not reliably increment a
Writing a = a++ (or a = ++a) modifies a twice without a sequence point between the side effects — undefined behavior. Use a++ alone, or a = a + 1. Interviewers love this trap.
Tricky Interview Point-2:
i++ + ++i is undefined behavior
Modifying the same scalar object more than once between sequence points (pre-C11) or without sequenced-before rules is UB. Never combine multiple ++/-- on the same variable in one expression.
Tricky Interview Point-3:
7 / 2 is 3, not 3.5 — integer division
When both operands are integers, / truncates toward zero. 7/2 → 3 and 7%2 → 1. Cast one operand: (float)7 / 2 → 3.5.
Tricky Interview Point-4:
Short-circuit: right side of && / || may never run
If the left of && is false, the right is not evaluated. If the left of || is true, the right is skipped. Side effects (function calls, ++, assignments) on the right may never happen.
Tricky Interview Point-5:
x = y = z = 0 assigns right-to-left
Assignment associativity is right-to-left: x = y = z = 0 means y = (z = 0), then x = that result. All three become 0. Confusion with left-associative operators is a common interview question.
Tricky Interview Point-6:
sizeof is an operator, not a function
sizeof does not need parentheses for variables (sizeof x), though sizeof(type) does. It usually yields a compile-time size_t and does not evaluate its operand (except VLAs).
Tricky Interview Point-7:
Bitwise & vs logical && are different
& is bitwise AND (operates on bits, no short-circuit). && is logical AND (yields 0 or 1, short-circuits). Mixing them up in conditions is a classic bug: if (flags & MASK) vs if (a && b).
Tricky Interview Point-8:
Post-increment returns old value, then increments
int x = 5; printf("%d", x++); prints 5, then x becomes 6. printf("%d", ++x) with x=5 prints 6. Knowing when the side effect is applied is essential for exam output questions.
Tricky Interview Point-9:
Char and short promote to int in expressions
Usual arithmetic conversions / integer promotions: char and short become int (or unsigned int) before most arithmetic. That is why sizeof('A' + 'B') may not equal sizeof(char).
Tricky Interview Point-10:
Ternary ?: has lower precedence than most operators
a + b ? c : d is (a + b) ? c : d, not a + (b ? c : d). Assignment has even lower precedence: x = cond ? a : b is fine, but watch parentheses with complex conditions.
Tricky Interview Point-11:
Comma operator evaluates left, yields right
In (a = 1, b = 2, a + b), each expression runs left-to-right; the whole expression value is a + b (3). Comma in function arguments is not the comma operator — it only separates arguments.
Tricky Interview Point-12:
Narrowing cast can silently lose data
int n = 300; char c = (char)n; keeps only the lower bits. Explicit casts document intent but do not magically preserve range. Prefer checking bounds before narrowing.
Level 4 Simple Programs
Short programs demonstrating arithmetic, relational, logical, ternary, increment, and casts.
Program 1 — Arithmetic + assignment operators
/* Arithmetic and compound assignment demo */
#include <stdio.h>
int main(void) {
int x = 10, y = 3;
printf("x + y = %d\n", x + y);
printf("x - y = %d\n", x - y);
printf("x * y = %d\n", x * y);
printf("x / y = %d\n", x / y);
printf("x %% y = %d\n", x % y);
x += 5;
y *= 2;
printf("After += and *= : x=%d y=%d\n", x, y);
return 0;
}
Program 2 — Relational + logical + ternary
/* Relational, logical, and ternary operators */
#include <stdio.h>
int main(void) {
int age, marks;
printf("Enter age and marks: ");
scanf("%d %d", &age, &marks);
if (age >= 18 && marks >= 40)
printf("Eligible\n");
else
printf("Not eligible\n");
printf("%s\n", (marks >= 40) ? "Pass" : "Fail");
return 0;
}
Program 3 — Increment and type cast demo
/* Pre/post increment and explicit cast */
#include <stdio.h>
int main(void) {
int n = 5;
int a = 7, b = 2;
float avg;
printf("n++ = %d, n now = %d\n", n++, n);
printf("++n = %d, n now = %d\n", ++n, n);
avg = (float)a / b;
printf("int div = %d, float div = %.2f\n", a / b, avg);
printf("sizeof(int) = %zu\n", sizeof(int));
return 0;
}
Level 5 Problem Solving Tricks
How to master operators while solving problems
Most operator bugs come from forgotten parentheses, undefined a = a++ patterns,
integer division when floats are needed, and mixing bitwise with logical operators.
Use these colorful habits every time you write or debug an expression.
Parenthesize until precedence is obvious
When in doubt, add parentheses. Writing (a + b) * c or a + (b * c) documents intent and avoids precedence mistakes. Prefer clarity over clever one-liners in exams and interviews.
Never write a = a++ or i = ++i
These forms modify a twice without defined sequencing. Use a++; or a = a + 1; or ++a; alone. If a compiler “works,” the behavior is still not portable.
Match operand types before dividing
If you need a fractional result, ensure at least one operand is float/double: (double)a / b or a * 1.0 / b. Leaving both as int silently truncates.
Use && / || when you mean logic; & / | for bits
Conditions and boolean logic → && || !. Masks and bit flags → & | ^ ~ << >>. Mixing them changes both meaning and evaluation (no short-circuit for bitwise).
Rely on short-circuit for safe checks
Write if (ptr != NULL && *ptr == 0) so the dereference only runs when the pointer is valid. Same pattern: if (n != 0 && sum / n > limit).
Trace ++/-- on paper before coding
For output questions, draw a column for each variable. Apply pre-increment before using the value; apply post-increment after using the old value. Never guess under time pressure.
Cast explicitly when narrowing or changing meaning
Document intent with (int)x, (float)sum / count, or (unsigned)flags. Explicit casts make type conversion visible during code review and reduce accidental promotion surprises.
Remember assignment is an expression
if ((ch = getchar()) != EOF) is idiomatic: assignment yields the assigned value. Always wrap assignment-in-condition in parentheses to avoid = vs == mistakes and to clarify precedence.
Quick success checklist
- Before run: parentheses clear? == not =? types matched for / ? no a=a++?
- Debug order: fix compile errors → trace precedence on paper → check ++/-- → verify casts
- Trace on paper: rewrite mixed expressions with full parentheses before predicting output
Level 6 Practice Programs List
Programming questions only — focused on operators, precedence, and type conversion.
- 1. Write a C program that reads two integers and prints their sum, difference, product, quotient, and remainder using arithmetic operators.
- 2. Write a C program that reads three numbers and uses relational and logical operators to print whether they are in strictly ascending order.
- 3. Write a C program that demonstrates pre-increment and post-increment on the same starting value and prints results at each step.
- 4. Write a C program that uses the ternary operator to find the larger of two integers without using if.
- 5. Write a C program that shows integer division vs floating-point division for the same pair of integers (use a cast).
- 6. Write a C program that evaluates a + b * c and (a + b) * c for user-entered a, b, c to illustrate precedence.
- 7. Write a C program that demonstrates short-circuit evaluation: print messages from the left and right sides of && and ||.
- 8. Write a C program that uses sizeof, a cast, and compound assignment (+=, *=) in one small demo with clear printf output.