- Home
- Blog
- Computer Science & IT
- C Operators: All 7 Types with Examples and Precedence
C Operators: All 7 Types with Examples and Precedence

On this page
- Types of operators in C at a glance
- 1. Arithmetic operators
- 2. Relational operators
- 3. Logical operators
- 4. Bitwise operators
- 5. Assignment operators, including *= and -=
- 6. Increment and decrement operators
- 7. The conditional (ternary) operator ?
- Special operators in C
- Operator precedence and associativity in C
- Common bugs with C operators
- Example program using C operators
- FAQs
- Related Topics on EngineeringHulk
An operator in C is a symbol that tells the compiler to perform an operation on one or more operands, such as + for addition or == for comparison. Textbooks usually group C operators into seven types: arithmetic, relational, logical, bitwise, assignment, increment/decrement and conditional (?:), with a set of special operators (sizeof, comma, address-of &, dereference *, member access . and ->, and cast) listed alongside. The C standard itself does not number the groups; “seven types” is a teaching convention, and different books split them slightly differently.
Every example below has been checked by compiling it as C99. If you are new to the language, start with what C programming is, then come back here.
Types of operators in C at a glance
| Type | Operators | Result |
|---|---|---|
| Arithmetic | + – * / % | A number |
| Relational | == != > < >= <= | int 1 (true) or 0 (false) |
| Logical | && || ! | int 1 or 0 |
| Bitwise | & | ^ ~ << >> | An integer, worked bit by bit |
| Assignment | = += -= *= /= %= <<= >>= &= ^= |= | The value stored |
| Increment / decrement | ++ — | The old or new value |
| Conditional | ? : | One of two values |
| Special | sizeof , & * . -> (type) | Varies |
1. Arithmetic operators
With int a = 17 and int b = 5:
| Operator | Meaning | Example | Result |
|---|---|---|---|
| + | Addition | a + b | 22 |
| – | Subtraction | a – b | 12 |
| * | Multiplication | a * b | 85 |
| / | Division | a / b | 3 (integer division drops the fraction) |
| % | Remainder (modulus) | a % b | 2 |
Integer division and % with negative numbers
When both operands are integers, / gives an integer. Since C99, the result is truncated toward zero, and % is defined so that (a / b) * b + a % b == a always holds. So:
- 17 / 5 = 3 and 17 % 5 = 2
- -17 / 5 = -3 and -17 % 5 = -2 (not -4 and 3, as floor division in some other languages gives)
- 17 / -5 = -3 and 17 % -5 = 2
The sign of a % result follows the left operand. % works only on integers; for floating point use fmod() from math.h. To get a decimal answer, make one operand a double: 17.0 / 5 gives 3.4. Dividing an integer by zero is undefined behaviour, so check the divisor first.
2. Relational operators
| Operator | Meaning | Example (a = 17, b = 5) | Result |
|---|---|---|---|
| == | Equal to | a == b | 0 |
| != | Not equal to | a != b | 1 |
| > | Greater than | a > b | 1 |
| < | Less than | a < b | 0 |
| >= | Greater than or equal to | a >= 17 | 1 |
| <= | Less than or equal to | b <= 4 | 0 |
C has no separate true/false type in older code: a comparison gives the int 1 or 0. C99 added _Bool and the header stdbool.h, which defines bool, true and false. Any non-zero value counts as true in a condition; see Boolean values for background.
3. Logical operators
| Operator | Meaning | Example | Result |
|---|---|---|---|
| && | Logical AND: true if both are true | (a > 10) && (b > 10) | 0 |
| || | Logical OR: true if either is true | (a > 10) || (b > 10) | 1 |
| ! | Logical NOT | !0 and !5 | 1 and 0 |
Short-circuit evaluation
&& and || evaluate the left operand first and stop as soon as the answer is known. In x && y, if x is 0 then y is never evaluated; in x || y, if x is non-zero then y is skipped. This is guaranteed by the standard and is used on purpose for safety checks:
if (p != NULL && p->count > 0) /* p->count is read only when p is not NULL */
if (b != 0 && a / b > 2) /* no division by zero */
The flip side: a function call or ++ on the right side may not run at all, so do not put side effects there if you need them every time.
4. Bitwise operators
These work on the individual bits of integer operands. With 12 (binary 1100) and 10 (binary 1010):
| Operator | Meaning | Example | Result |
|---|---|---|---|
| & | AND: 1 where both bits are 1 | 12 & 10 | 8 (1000) |
| | | OR: 1 where either bit is 1 | 12 | 10 | 14 (1110) |
| ^ | XOR: 1 where the bits differ | 12 ^ 10 | 6 (0110) |
| ~ | NOT: flips every bit | ~5 | -6 on two’s complement machines |
| << | Left shift (multiply by 2 per place) | 1 << 4 | 16 |
| >> | Right shift (divide by 2 per place) | 12 >> 2 | 3 |
Shifting by a negative amount or by at least the width of the type is undefined, and right-shifting a negative number is implementation-defined, so use unsigned types for bit work. Typical uses are flags in embedded code, masks (x & 1 tests for odd) and fast multiplication by powers of two.
5. Assignment operators, including *= and -=
The simple assignment = stores the right-hand value in the left-hand variable. A compound assignment such as x op= y means x = x op (y): it applies the operator to the variable and stores the result back. With x = 12 before each line:
| Operator | Same as | Example | x becomes |
|---|---|---|---|
| += | x = x + y | x += 3 | 15 |
| -= | x = x – y | x -= 3 | 9 |
| *= | x = x * y | x *= 3 | 36 |
| /= | x = x / y | x /= 5 | 2 |
| %= | x = x % y | x %= 5 | 2 |
| <<= | x = x << y | x <<= 1 | 24 |
| >>= | x = x >> y | x >>= 2 | 3 |
| &= | x = x & y | x &= 10 | 8 |
| |= | x = x | y | x |= 3 | 15 |
| ^= | x = x ^ y | x ^= 10 | 6 |
The *= operator in C
x *= y multiplies x by y and stores the product in x. It is shorthand for x = x * (y), and x is evaluated only once.
int x = 10;
x *= 3; /* x is now 30 */
x *= 2 + 1; /* x = x * (2 + 1), so x is now 90, not 61 */
The brackets matter: assignment has the lowest precedence apart from the comma, so the whole right side is worked out first. A common use is a running product, such as fact *= i inside a factorial loop.
The -= operator in C
x -= y subtracts y from x and stores the result in x, the same as x = x – (y).
int balance = 500;
balance -= 120; /* balance is now 380 */
balance -= 50 + 30; /* balance = balance - 80, so 300 */
Watch the spacing: x -= 5 subtracts 5, but x =- 5 is read as x = -5 and simply assigns minus five. The earliest versions of C spelled compound assignment as =-, which is why compilers such as Clang still warn when they see it.
6. Increment and decrement operators
| Form | Name | Example (i = 5 before each) | j gets | i becomes |
|---|---|---|---|---|
| ++i | Pre-increment: add 1, then use | j = ++i | 6 | 6 |
| i++ | Post-increment: use, then add 1 | j = i++ | 5 | 6 |
| –i | Pre-decrement | j = –i | 4 | 4 |
| i– | Post-decrement | j = i– | 5 | 4 |
On a line by itself (i++; or ++i;) the two forms do the same thing. The difference only shows when the value is used in a larger expression.
7. The conditional (ternary) operator ?
The ? operator in C
The conditional operator is C’s only operator with three operands: condition ? value_if_true : value_if_false. The condition is evaluated first; if it is non-zero the result is the second operand, otherwise the third. Only one of the two is evaluated.
int a = 17, b = 5;
int big = (a > b) ? a : b; /* big = 17 */
printf("%s\n", (a % 2 == 0) ? "even" : "odd"); /* prints odd */
Unlike an if-else statement, ?: is an expression, so it can sit inside printf, an initialiser or a return statement.
Nesting caution: ?: groups right to left, so a ? b : c ? d : e means a ? b : (c ? d : e). One level of nesting is readable when laid out on separate lines; beyond that, use if-else. Also keep both result operands the same type, because C converts them to a common type (mixing int and double gives a double).
Special operators in C
| Operator | Meaning | Example | Result |
|---|---|---|---|
| sizeof | Size of a type or object in bytes, evaluated at compile time for ordinary types | sizeof(int) | 4 on most current compilers (not fixed by the standard) |
| , | Comma: evaluate left, discard it, then evaluate right | x = (a = 2, a + 3) | x = 5 |
| & | Address-of | int *p = &a; | p holds the address of a |
| * | Dereference (indirection) | *p | The value of a |
| . | Member of a structure or union | pt.x | Field x of pt |
| -> | Member through a pointer | ptr->x | Same as (*ptr).x |
| (type) | Cast: convert to another type | (double)17 / 5 | 3.4 |
Structures and the -> operator are the basis of the data-hiding style described in encapsulation in C.
Operator precedence and associativity in C
Precedence decides which operator binds first; associativity decides the order when operators of the same level meet. Highest first, following cppreference:
| Level | Operators | Associativity |
|---|---|---|
| 1 | Postfix ++ –, function call (), subscript [], . and ->, compound literal | Left to right |
| 2 | Prefix ++ –, unary + -, ! ~, cast (type), dereference *, address-of &, sizeof, _Alignof | Right to left |
| 3 | * / % | Left to right |
| 4 | + – | Left to right |
| 5 | << >> | Left to right |
| 6 | < <= > >= | Left to right |
| 7 | == != | Left to right |
| 8 | & (bitwise AND) | Left to right |
| 9 | ^ | Left to right |
| 10 | | | Left to right |
| 11 | && | Left to right |
| 12 | || | Left to right |
| 13 | ?: | Right to left |
| 14 | = += -= *= /= %= <<= >>= &= ^= |= | Right to left |
| 15 | , (comma) | Left to right |
Two quick readings: 2 + 3 * 4 is 14 because * is level 3 and + level 4. a = b = 0 sets both to 0 because assignment groups right to left. When in doubt, add brackets; they cost nothing.
Common bugs with C operators
- = instead of ==. if (x = 5) assigns 5 and is always true. Compile with warnings on (-Wall) and the compiler will flag it.
- Modifying a variable twice in one expression. i++ + ++i, or i = i++, is undefined behaviour: the standard gives no answer, and different compilers print different numbers. Exam questions that ask for its “output” have no correct answer.
- Bitwise instead of logical. & and | evaluate both sides and work bit by bit; && and || short-circuit and give 0 or 1. 2 & 1 is 0 but 2 && 1 is 1.
- Precedence of & below ==. x & 1 == 0 is parsed as x & (1 == 0), which is always 0. Write (x & 1) == 0.
- Integer division surprise. 1 / 2 * 10 is 0, because 1 / 2 is already 0. Write 1.0 / 2 * 10 or reorder.
- Chained comparisons. 1 < x < 5 does not test a range: it compares (1 < x), which is 0 or 1, with 5, so it is always true. Use x > 1 && x < 5. Recent Clang versions flag the chained form with a warning or an error.
Example program using C operators
This program uses most of the operators above. It was compiled with -std=c99 -Wall -Wextra and produced no warnings.
#include <stdio.h>
int main(void)
{
int a = 17, b = 5;
/* arithmetic */
printf("a / b = %d, a %% b = %d\n", a / b, a % b);
printf("-17 / 5 = %d, -17 %% 5 = %d\n", -17 / 5, -17 % 5);
printf("17.0 / 5 = %.1f\n", 17.0 / 5);
/* relational and logical */
printf("a > b = %d, a == b = %d\n", a > b, a == b);
printf("(a > 10 && b > 10) = %d\n", a > 10 && b > 10);
/* bitwise: 12 = 1100, 10 = 1010 */
printf("12 & 10 = %d, 12 | 10 = %d, 12 ^ 10 = %d, 1 << 4 = %d\n",
12 & 10, 12 | 10, 12 ^ 10, 1 << 4);
/* compound assignment */
int x = 10;
x *= 3; /* x = x * 3 */
printf("after x *= 3: %d\n", x);
x -= 4; /* x = x - 4 */
printf("after x -= 4: %d\n", x);
x *= 2 + 1; /* x = x * (2 + 1) */
printf("after x *= 2 + 1: %d\n", x);
/* pre and post increment */
int i = 5;
int p = i++; /* p gets 5, then i becomes 6 */
int q = ++i; /* i becomes 7, then q gets 7 */
printf("p = %d, q = %d, i = %d\n", p, q, i);
/* conditional operator */
int big = (a > b) ? a : b;
printf("larger of a and b = %d\n", big);
/* sizeof and cast */
printf("sizeof(int) = %zu\n", sizeof(int));
printf("(double)a / b = %.2f\n", (double)a / b);
return 0;
}
Output:
a / b = 3, a % b = 2
-17 / 5 = -3, -17 % 5 = -2
17.0 / 5 = 3.4
a > b = 1, a == b = 0
(a > 10 && b > 10) = 0
12 & 10 = 8, 12 | 10 = 14, 12 ^ 10 = 6, 1 << 4 = 16
after x *= 3: 30
after x -= 4: 26
after x *= 2 + 1: 78
p = 5, q = 7, i = 7
larger of a and b = 17
sizeof(int) = 4
(double)a / b = 3.40
Note the -17 / 5 line: truncation toward zero gives -3 and -2, and 78 comes from 26 * (2 + 1). The sizeof line prints 4 on common desktop compilers; a 16-bit embedded compiler may print 2. For more practice with loops and %, try the prime number program in C, and GeeksforGeeks has further operator exercises.
FAQs
What are the 7 types of operators in C?
The usual textbook grouping is arithmetic, relational, logical, bitwise, assignment, increment/decrement and conditional (?:). Special operators such as sizeof, comma, &, *, ., -> and cast are listed separately or as an eighth group. The C standard does not fix the number.
What does *= mean in C?
x *= y multiplies x by y and stores the result in x, the same as x = x * (y). If x is 10, x *= 3 makes it 30, and x *= 2 + 1 multiplies by 3, not by 2.
What does -= mean in C?
x -= y subtracts y from x and stores the result back in x, the same as x = x – (y). If x is 500, x -= 120 leaves 380. Do not write x =- 120, which assigns minus 120.
What is the ? operator in C?
It is the conditional (ternary) operator: condition ? a : b gives a if the condition is non-zero and b otherwise. For example, (17 > 5) ? 17 : 5 gives 17. It groups right to left, so avoid deep nesting.
What is the difference between i++ and ++i?
Both add 1 to i. ++i adds first and gives the new value; i++ gives the old value and then adds. With i = 5, j = i++ makes j 5, while j = ++i makes j 6; either way i ends at 6.
Related Topics on EngineeringHulk
Keep reading

Classification of DBMS: Types of Database Management Systems with Examples
Types of DBMS by data model (hierarchical, network, relational, object, NoSQL), by users, by distribution and by use (OLTP, OLAP), with examples, tables.

Types of Metal: Ferrous and Non-Ferrous Classification with Examples
Types of metal explained: ferrous (carbon, alloy and stainless steel, cast iron) and non-ferrous (aluminium, copper, brass, zinc, titanium) with a table.

Boiler Classification: Types of Boilers With Examples
Types of boilers classified by tube contents, axis, firing, circulation, pressure, tubes, use, fuel and heat source, with a master table of named boilers.

Classification of Computers: Types by Size, Data Handled and Purpose
Classification of computers by size (supercomputer to embedded), by data (analog, digital, hybrid) and by purpose, with a comparison table and examples.

Lattice and Recurrence Relation: Posets, Hasse Diagrams and Solved Examples
Lattices explained with posets, Hasse diagrams, join and meet, bounded, distributive and complemented types, plus a solved linear recurrence relation.

Intrusion Prevention System (IPS): How It Works, Types, and IDS vs IPS
An intrusion prevention system (IPS) sits inline and blocks attacks in real time. Network-based IPS types, detection methods, IDS vs IPS, tools and a rule.