C Programming Operators Reference
Essential Reference

C Operators - Complete Reference Guide

Master all C operators with detailed explanations, usage examples, and programming best practices for effective C programming.

7 Categories

Comprehensive coverage

Practical Examples

Real-world usage

Precedence Rules

Operator hierarchy

Introduction to C Operators

Operators are special symbols that perform operations on variables and values. C provides a rich set of operators to manipulate data, make decisions, and control program flow.

Key Characteristics
  • Operators work on operands (variables, constants, expressions)
  • Operators have precedence (order of evaluation)
  • Operators have associativity (left-to-right or right-to-left)
  • Some operators can be overloaded (used for different operations)
  • Operators can be unary, binary, or ternary
Operator Categories
  • Arithmetic Operators: Mathematical calculations
  • Relational Operators: Comparison operations
  • Logical Operators: Boolean logic operations
  • Bitwise Operators: Bit-level operations
  • Assignment Operators: Value assignment
  • Other Operators: Special purpose operators

Important Note About Operators

Operator precedence determines which operations are performed first in an expression. When in doubt, use parentheses () to explicitly define the order of operations.

C Operators Classification

Here is a comprehensive classification of all C operators organized by their operation type:

Operation Type Operators
Unary Operators
Operate on a single operand
++ --
++ (increment), -- (decrement)
Arithmetic Operators
Perform mathematical calculations
+ - * / %
+ (add), - (subtract), * (multiply), / (divide), % (modulus)
Logical Operators
Perform Boolean logic operations
&& || !
&& (AND), || (OR), ! (NOT)
Relational Operators
Compare values and return Boolean results
< <= > >= == !=
<, <=, >, >=, ==, !=
Bit-wise Operators
Perform operations at bit level
& | << >> ~ ^
& (AND), | (OR), << (left shift), >> (right shift), ~ (NOT), ^ (XOR)
Assignment Operators
Assign values to variables
= += -= *= /= %=
=, +=, -=, *=, /=, %=
Ternary or Conditional Operator
Compact if-else statement replacement
? :
? : (conditional operator)
Note: Understanding operator types helps in writing efficient C code. Unary operators work on single operands, binary operators on two operands, and the ternary operator is the only operator that works on three operands.

Complete C Operators Reference

Here is the complete list of C operators with their categories, descriptions, and examples:

Operator Category Description & Purpose Example
+ Arithmetic Addition - Adds two operands
int sum = a + b;
- Arithmetic Subtraction - Subtracts right operand from left
int diff = a - b;
* Arithmetic Multiplication - Multiplies two operands
int prod = a * b;
/ Arithmetic Division - Divides left operand by right
int quot = a / b;
% Arithmetic Modulus - Returns remainder of division
int rem = a % b;
++ Arithmetic Increment - Increases value by 1
a++; or ++a;
-- Arithmetic Decrement - Decreases value by 1
a--; or --a;
== Relational Equal to - Checks if two values are equal
if (a == b) { ... }
!= Relational Not equal to - Checks if two values are not equal
if (a != b) { ... }
> Relational Greater than - Checks if left is greater than right
if (a > b) { ... }
< Relational Less than - Checks if left is less than right
if (a < b) { ... }
>= Relational Greater than or equal to
if (a >= b) { ... }
<= Relational Less than or equal to
if (a <= b) { ... }
&& Logical Logical AND - True if both operands are true
if (a > 0 && b > 0)
|| Logical Logical OR - True if at least one operand is true
if (a > 0 || b > 0)
! Logical Logical NOT - Reverses logical state
if (!flag) { ... }
& Bitwise Bitwise AND - Performs AND on each bit
int result = a & b;
| Bitwise Bitwise OR - Performs OR on each bit
int result = a | b;
^ Bitwise Bitwise XOR - Performs XOR on each bit
int result = a ^ b;
~ Bitwise Bitwise NOT - Inverts all bits (one's complement)
int result = ~a;
<< Bitwise Left shift - Shifts bits to the left
int result = a << 2;
>> Bitwise Right shift - Shifts bits to the right
int result = a >> 2;
= Assignment Simple assignment - Assigns right value to left
int a = 10;
+= Assignment Add and assign - a += b is same as a = a + b
a += 5;
-= Assignment Subtract and assign - a -= b is same as a = a - b
a -= 3;
*= Assignment Multiply and assign - a *= b is same as a = a * b
a *= 2;
/= Assignment Divide and assign - a /= b is same as a = a / b
a /= 2;
%= Assignment Modulus and assign - a %= b is same as a = a % b
a %= 3;
?: Other Ternary/Conditional operator - Short form of if-else
max = (a > b) ? a : b;
sizeof() Other Returns size of variable or type in bytes
int size = sizeof(int);
& Other Address of operator - Returns memory address
int *ptr = &a;
* Other Pointer dereference - Accesses value at address
int value = *ptr;
-> Other Arrow operator - Accesses struct member via pointer
ptr->member = 10;
. Other Dot operator - Accesses struct/union member
obj.member = 10;
, Other Comma operator - Evaluates multiple expressions
a = (b=3, b+2); // a=5
Pro Tip: The most commonly used operators in everyday programming are: = (assignment), + - * / (arithmetic), == != < > (relational), && || ! (logical), and ++ -- (increment/decrement).

Detailed Operator Examples

Arithmetic Operators Example
Basic Arithmetic Operations
#include <stdio.h>

int main() {
    int a = 15, b = 4;
    
    printf("a = %d, b = %d\n", a, b);
    printf("Addition: a + b = %d\n", a + b);
    printf("Subtraction: a - b = %d\n", a - b);
    printf("Multiplication: a * b = %d\n", a * b);
    printf("Division: a / b = %d\n", a / b);
    printf("Modulus: a %% b = %d\n", a % b);
    
    // Increment/Decrement
    int x = 5;
    printf("Original x: %d\n", x);
    printf("Post-increment: x++ = %d\n", x++);
    printf("After post-increment: x = %d\n", x);
    printf("Pre-increment: ++x = %d\n", ++x);
    
    return 0;
}
Relational and Logical Operators Example
Comparison and Boolean Logic
#include <stdio.h>

int main() {
    int a = 10, b = 20, c = 10;
    
    // Relational operators
    printf("a == b: %d\n", a == b);  // 0 (false)
    printf("a != b: %d\n", a != b);  // 1 (true)
    printf("a < b: %d\n", a < b);    // 1 (true)
    printf("a > b: %d\n", a > b);    // 0 (false)
    printf("a <= c: %d\n", a <= c);  // 1 (true)
    printf("a >= c: %d\n", a >= c);  // 1 (true)
    
    // Logical operators
    int age = 25;
    int hasLicense = 1;
    
    printf("Can drive? %d\n", age >= 18 && hasLicense);
    printf("Is teenager? %d\n", age >= 13 && age <= 19);
    printf("Not a teenager? %d\n", !(age >= 13 && age <= 19));
    
    return 0;
}
Bitwise Operators — Quick Example (Positive Values)
Bit-level Manipulation
#include <stdio.h>

int main() {
    unsigned char a = 12, b = 5;
    printf("a & b  = %u\n", a & b);
    printf("a | b  = %u\n", a | b);
    printf("a ^ b  = %u\n", a ^ b);
    printf("a << 2 = %u\n", a << 2);
    printf("a >> 2 = %u\n", a >> 2);
    return 0;
}

How Bitwise Operators Work (Positive & Negative)

Bitwise operators (&, |, ^, ~, <<, >>) work on the binary representation of an integer, one bit at a time. For unsigned types, bits are plain binary. For signed int, negative values are stored in two's complement on virtually all modern systems (including C on typical platforms).

One's Complement and Two's Complement Explained

1. One's Complement

Definition: Invert all bits (change 01 and 10).

How it works: Positive numbers stay the same in one's complement. To get the negative of a value, flip every bit.

Example: 8-bit system, +5 to −5

Step 1: +5 = 0000 0101 Step 2: Flip all bits (0→1, 1→0) −5 in one's complement = 1111 1010

Example: 8-bit one's complement table (selected values)

DecimalOne's complement binaryDecimalOne's complement binary
+00000 0000−01111 1111
+10000 0001−11111 1110
+20000 0010−21111 1101
+30000 0011−31111 1100
+40000 0100−41111 1011
+50000 0101−51111 1010
+60000 0110−61111 1001
+70000 0111−71111 1000
+80000 1000−81111 0111
Problem with one's complement: two zeros!
+0 = 0000 0000 −0 = 1111 1111

This wastes one bit pattern and complicates arithmetic.

One's complement addition (end-around carry):

Adding +5 and −2 in one's complement: +5 = 0000 0101 −2 = 1111 1101 (flip 0000 0010) --------- 1 0000 0010 (carry out) Add the carry back (end-around carry): 0000 0010 + 1 = 0000 0011 = +3 ✓

2. Two's Complement

Definition: One's complement + 1 (flip all bits, then add 1).

  1. Write the positive number in binary.
  2. Flip all bits (one's complement).
  3. Add 1 to the result.

Example: +5 to −5 (8-bit)

Step 1: +5 = 0000 0101 Step 2: One's complement = 1111 1010 Step 3: Add 1 = 1111 1011 Therefore: −5 in two's complement = 1111 1011

Example: +12 to −12

Step 1: +12 = 0000 1100 Step 2: Flip bits = 1111 0011 Step 3: Add 1 = 1111 0100 Therefore: −12 = 1111 0100

Example: −5 back to +5

Step 1: −5 = 1111 1011 Step 2: Flip bits = 0000 0100 Step 3: Add 1 = 0000 0101 = +5 ✓

4-bit two's complement table

DecimalBinaryDecimalBinary
+00000−11111
+10001−21110
+20010−31101
+30011−41100
+40100−51011
+50101−61010
+60110−71001
+70111−81000

Notice: Only one zero. Range is −8 to +7 (asymmetric) in 4 bits.

3. Key Differences Between One's and Two's Complement

FeatureOne's complementTwo's complement
Number of zerosTwo (+0 and −0)One (0)
Range (4-bit)−7 to +7−8 to +7
Range (8-bit)−127 to +127−128 to +127
Negative representationFlip all bitsFlip bits + add 1
AdditionEnd-around carry neededNormal binary addition
Used inOld systems (UNIVAC, CDC)All modern computers & C

4. Why Two's Complement is Better

Benefit 1 — No negative zero:

One's complement: +0 = 0000, −0 = 1111 (wasted) Two's complement: 0 = 0000 only

Benefit 2 — Addition works naturally:

Add −5 and +3 in two's complement: −5 = 1111 1011 +3 = 0000 0011 --------- 1111 1110 = −2 ✓ No special end-around carry!

Benefit 3 — Subtraction becomes addition:

5 − 3 = 5 + (−3) +5 = 0000 0101 −3 = 1111 1101 --------- 0000 0010 = 2 ✓

5. Converting Between Systems

  • One's → two's: one's complement + 1. Example: −5 one's 1111 1010 + 1 = 1111 1011 (two's).
  • Two's → one's: two's complement − 1. Example: −5 two's 1111 1011 − 1 = 1111 1010 (one's).

6. Practical Examples

Method 1 — Flip and add 1 (−7 in 8-bit):

+7 = 0000 0111 Flip = 1111 1000 Add 1 = 1111 1001 ✓

Method 2 — From the rightmost 1:

+7 = 0000 0111 rightmost 1 ↑ Keep bits to the right of that 1; flip all bits to the left: Result = 1111 1001 ✓

Convert negative two's complement to decimal:

1111 1011 → flip → 0000 0100 → add 1 → 0000 0101 = 5 Therefore 1111 1011 = −5 ✓

7. Overflow Examples (4-bit two's complement)

+7 (0111) + 1 = 1000 = −8 (overflow!) +4 (0100) + 4 = 1000 = −8 (overflow!) −8 (1000) − 1 = 0111 = +7 (underflow!)

8. Summary Table (8-bit)

Decimal8-bit binaryOne's complementTwo's complement
+50000 01010000 01010000 0101
−51111 10101111 1011
00000 00000000 0000 or 1111 11110000 0000
−01111 1111does not exist

9. Quick Reference Formula

Two's complement of n (same as C bitwise NOT + 1 for signed types):

−n = (~n) + 1 Example: −5 = (~5) + 1 ~5 = 1111 1010 +1 = 1111 1011 = −5 ✓

Converting back:

n = ~((−n) − 1)

10. Memory Representation (32-bit example)

+5 (two's) = 00000000 00000000 00000000 00000101 −5 (one's) = 11111111 11111111 11111111 11111010 −5 (two's) = 11111111 11111111 11111111 11111011
Key takeaway: Modern C uses two's complement for signed integers on typical platforms. Understanding two's complement is essential for predicting results of ~, &, |, ^, and shifts on negative values.

Bitwise Operators Theory with Examples (Positive & Negative Numbers)

1. Binary Representation Fundamentals

Positive numbers

Use standard binary positional notation. Example: 5 in 8-bit = 0000 0101

0×128 + 0×64 + 0×32 + 0×16 + 0×8 + 1×4 + 0×2 + 1×1 = 5
Negative numbers (two's complement)

C uses two's complement for negative integers on typical platforms.

  1. Write positive binary.
  2. Invert all bits.
  3. Add 1.
Step 1: +5 = 0000 0101 Step 2: Invert bits = 1111 1010 Step 3: Add 1 = 1111 1011 Therefore: −5 = 1111 1011 Verify: 1111 1011 = −128 + 64 + 32 + 16 + 8 + 0 + 2 + 1 = −5

2. Bitwise AND (&)

Rule: Result is 1 only if both bits are 1.

ABA&B
000
010
100
111

Example 1 — positive & positive:

5 & 3 = ? 5 = 0000 0101 3 = 0000 0011 --------- & = 0000 0001 = 1 Answer: 1

Example 2 — negative & positive:

−5 & 3 = ? −5 = 1111 1011 3 = 0000 0011 --------- & = 0000 0011 = 3 Answer: 3

Example 3 — negative & negative:

−5 & −3 = ? −3: +3=0000 0011 → ~3=1111 1100 → +1=1111 1101 −5 = 1111 1011 −3 = 1111 1101 --------- & = 1111 1001 = −7 Answer: −7

3. Bitwise OR (|)

Rule: Result is 1 if at least one bit is 1.

ABA|B
000
011
101
111

Example 1 — positive | positive:

5 | 3 = ? 5 = 0000 0101 3 = 0000 0011 --------- | = 0000 0111 = 7 Answer: 7

Example 2 — negative | positive:

−5 | 3 = ? −5 = 1111 1011 3 = 0000 0011 --------- | = 1111 1011 = −5 Answer: −5

4. Bitwise XOR (^)

Rule: Result is 1 if bits differ.

ABA^B
000
011
101
110

Example 1 — positive ^ positive:

5 ^ 3 = ? 5 = 0000 0101 3 = 0000 0011 --------- ^ = 0000 0110 = 6 Answer: 6

Example 2 — negative ^ positive:

−5 ^ 3 = ? −5 = 1111 1011 3 = 0000 0011 --------- ^ = 1111 1000 = −8 Answer: −8

Example 3 — negative ^ negative:

−5 ^ −3 = ? −5 = 1111 1011 −3 = 1111 1101 --------- ^ = 0000 0110 = 6 Answer: 6

5. Bitwise NOT (~)

Rule: Flip every bit.

A~A
01
10

Example 1 — positive:

~5 = ? 5 = 0000 0101 ~5 = 1111 1010 = −6 Check: −128+64+32+16+8+0+2+0 = −6 Formula: ~n = −(n+1) → ~5 = −6 ✓

Example 2 — negative:

~(−5) = ? −5 = 1111 1011 ~(−5) = 0000 0100 = 4 ✓

6. Left Shift (<<)

Effect: x << n = x × 2n when valid.

Example — positive:

5 << 1: 0000 0101 → 0000 1010 = 10 (5×2¹=10 ✓) 5 << 2: 0001 0100 = 20 (5×2²=20 ✓)

Example — negative:

−5 << 1: 1111 1011 → 1111 0110 = −10 ✓ −5 << 4: 1011 0000 = −80 (−5×16) ✓ Note: sign bit can shift out.
Caution: Left shift of negative signed overflow is undefined behavior in C.

7. Right Shift (>>)

  • Positive: logical shift, fill with 0.
  • Negative: arithmetic shift on most compilers (fill with 1).

Example — positive (logical shift):

20 >> 2: 20 = 0001 0100 20 >> 2 = 0000 0101 = 5 (20÷4=5 ✓)

Example — negative (arithmetic shift):

−20 >> 2: −20 = 1110 1100 −20 >> 2 = 1111 1011 = −5 (−20÷4=−5 ✓)

Note: Signed >> is implementation-defined in C; most use arithmetic shift.

8. Complete Comparison Table (8-bit)

NumberBinary~Number<< 1>> 1
+50000 0101−6102
−51111 10114−10−3
+120000 1100−13246
−121111 010011−24−6
+10000 0001−220
−11111 11110−2−1

9. Quick Reference Formulas

OpPositive nNegative n
~n−(n+1)same rule
n<<kn×2kwatch UB
n>>kfloor ÷ 2kimpl-defined

10. Memory Representation (32-bit)

+5 = 00000000 00000000 00000000 00000101 −5 = 11111111 11111111 11111111 11111011 ~5 = 11111111 11111111 11111111 11111010 = −6 ~(−5)= 00000000 00000000 00000000 00000100 = 4
Key insight: Bitwise ops use the actual binary representation; two's complement explains negative results.

Try it in C

Positive vs negative (hex)
#include <stdio.h>

int main() {
    int pos = 12, neg = -5;
    printf("pos = %d (0x%08X)\n", pos, (unsigned int)pos);
    printf("neg = %d (0x%08X)\n", neg, (unsigned int)neg);
    printf("neg & 12 = %d\n", neg & 12);
    printf("~neg     = %d\n", ~neg);
    printf("neg >> 1 = %d\n", neg >> 1);
    return 0;
}

Operator Precedence and Associativity

Operator precedence determines the order in which operators are evaluated in an expression. When operators have the same precedence, associativity determines the order.

Precedence Category Operators Associativity
1 (Highest) Function call, Array subscript () [] . -> Left to Right
2 Unary ! ~ ++ -- + - * & sizeof Right to Left
3 Multiplicative * / % Left to Right
4 Additive + - Left to Right
5 Bitwise shift << >> Left to Right
6 Relational < <= > >= Left to Right
7 Equality == != Left to Right
8 Bitwise AND & Left to Right
9 Bitwise XOR ^ Left to Right
10 Bitwise OR | Left to Right
11 Logical AND && Left to Right
12 Logical OR || Left to Right
13 Conditional ?: Right to Left
14 Assignment = += -= *= /= %= &= ^= |= <<= >>= Right to Left
15 (Lowest) Comma , Left to Right
Precedence Examples
Understanding Operator Priority
#include <stdio.h>

int main() {
    int a = 10, b = 5, c = 2;
    int result;
    
    // Example 1: Multiplication before addition
    result = a + b * c;  // 10 + (5 * 2) = 20
    printf("a + b * c = %d\n", result);
    
    // Example 2: Using parentheses to change order
    result = (a + b) * c;  // (10 + 5) * 2 = 30
    printf("(a + b) * c = %d\n", result);
    
    // Example 3: Complex expression
    result = a * b + c / 2 - 1;  // (10 * 5) + (2 / 2) - 1 = 50 + 1 - 1 = 50
    printf("a * b + c / 2 - 1 = %d\n", result);
    
    // Example 4: Assignment vs comparison
    int x, y = 5;
    x = y == 5;  // First y == 5 evaluates to 1, then x = 1
    printf("x = y == 5: x = %d\n", x);
    
    return 0;
}
Best Practice: When writing complex expressions, use parentheses to make the intended order of operations explicit. This improves code readability and prevents bugs caused by incorrect assumptions about operator precedence.

Tricky Points (All Operator Types)

Interview-style pitfalls grouped by operator category. See bitwise positive & negative above for two's complement detail.

Arithmetic operators

Tricky 1: 5 / 2 == 2 with integers — use (float)5 / 2 for 2.5.
Tricky 2: % sign follows the dividend: -7 % 3 == -1, not 2.
Tricky 3: ++i increments before use; i++ after — matters in a[i++] = i;.

Relational operators

Tricky 4: if (x = 5) assigns; if (x == 5) compares.
if (x = 5) { ... } // wrong
if (x == 5) { ... } // correct
Tricky 5: Do not compare floats with ==; use an epsilon.

Logical operators

Tricky 6: && and || short-circuit — the right side may not execute.
Tricky 7: Logical operators return 0 or 1, not arbitrary non-zero values.

Bitwise operators

Tricky 8: & is bitwise AND; && is logical AND — not interchangeable in if.
Tricky 9: ~(-5) == 4; for signed n, ~n == -(n+1).
Tricky 10: >> on negative int is usually arithmetic shift (sign preserved); on unsigned, logical shift.
Tricky 11: Left shift of a negative signed value is undefined behavior if it overflows.

Assignment, ternary, comma, precedence

Tricky 12: a += b * c means a = a + (b * c), not (a + b) * c.
Tricky 13: Ternary ?: has low precedence — use (a > b) ? a : b.
Tricky 14: Comma operator returns the rightmost value: x = (a=1, a+2) sets x to 3.
Tricky 15: a + b * c is a + (b * c) — use parentheses when you mean (a + b) * c.
Rule of thumb: Parentheses when unsure; unsigned for bit masks; == and && for conditions.

Key Takeaways

  • C provides 7 categories of operators: Arithmetic, Relational, Logical, Bitwise, Assignment, and Others
  • Operator precedence determines evaluation order; use parentheses for clarity
  • == is for comparison, = is for assignment - don't confuse them!
  • Integer division truncates the fractional part; cast to float for precise division
  • ++ and -- can be prefix (++x) or postfix (x++) with different behaviors
  • Bitwise operators work on individual bits; logical operators work on boolean values
  • The ternary operator (?:) provides a compact if-else alternative
  • Assignment operators can be combined with arithmetic (+=, -=, *=, /=, %=)
  • sizeof() returns the size in bytes of a variable or type
Next Topics: We'll explore control flow statements (if-else, switch-case, loops) and how they work with operators to create logical program flow.