upgrade
upgrade

🧑🏽‍💻Intro to C Programming

Operators in C

Study smarter with Fiveable

Get study guides, practice questions, and cheatsheets for all your subjects. Join 500,000+ students with a 96% pass rate.

Get Started

Why This Matters

Operators are the verbs of C programming—they're how you actually do things with your data. Every calculation, every comparison, every decision your program makes relies on operators. You're being tested not just on recognizing operator symbols, but on understanding operator precedence, type behavior (like integer division truncation), and side effects (how increment operators change values mid-expression). These concepts appear constantly in exam questions that ask you to trace code or predict output.

Mastering operators means understanding evaluation order, type conversion, and memory manipulation. The difference between = and == has crashed countless programs, and knowing when to use && versus & separates competent programmers from confused ones. Don't just memorize symbols—know what each operator returns, how it affects its operands, and where precedence might trip you up.


Arithmetic and Mathematical Operations

These operators handle the fundamental math your programs need. The key insight: C treats integer and floating-point arithmetic differently, and this catches many students off guard.

Arithmetic Operators (+, -, *, /, %)

  • Five core operations—addition +, subtraction -, multiplication *, division /, and modulus % form the foundation of all calculations
  • Integer division truncates7/27 / 2 evaluates to 33, not 3.53.5; use floating-point types or casting to preserve decimals
  • Modulus returns remainders7%27 \% 2 evaluates to 11; only works with integer operands and is essential for cycling, wrapping, and divisibility checks

Increment and Decrement Operators (++, --)

  • Shorthand for ±1\pm 1 operations++x and x++ both add 1, but timing differs based on prefix vs. postfix form
  • Prefix evaluates before use—in y = ++x, x increments first, then y gets the new value; postfix (x++) assigns first, then increments
  • Loop workhorses—nearly every for loop uses these operators; understanding prefix vs. postfix prevents off-by-one errors

Compare: ++x vs. x++—both increment x by 1, but prefix returns the new value while postfix returns the original value. If asked to trace y = x++ where x starts at 5, y becomes 5 and x becomes 6.


Assignment and Compound Assignment

Assignment operators store values in variables. The critical distinction: assignment is an operation that returns a value, not just a statement.

Assignment Operator (=)

  • Right-to-left evaluation—the expression on the right is fully evaluated before being stored in the left-hand variable
  • Returns the assigned value—this enables chaining like a = b = c = 0, which assigns 0 to all three variables
  • Common error source—confusing = (assignment) with == (comparison) compiles without error but produces bugs; if (x = 5) always evaluates true

Compound Assignment Operators (+=, -=, *=, /=, %=)

  • Shorthand combinationsx += 5 is equivalent to x = x + 5, reducing repetition and potential typos
  • Works with all arithmetic operators—includes +=, -=, *=, /=, %=, and even bitwise versions like &= and |=
  • Evaluates left side once—important when the left side has side effects; arr[i++] += 1 only increments i once

Compare: x = x + 1 vs. x += 1 vs. x++—all increment x by 1, but compound assignment and increment operators are more concise and, in some contexts, can be more efficient. Use ++ for simple increments, += when adding values other than 1.


Comparison and Decision-Making

Relational and logical operators power every if statement and loop condition. These operators always return either 0 (false) or 1 (true) in C.

Relational Operators (==, !=, <, >, <=, >=)

  • Return boolean integers—comparisons yield 11 for true and 00 for false; C has no dedicated boolean type in C89
  • Six comparison types—equal ==, not equal !=, less than <, greater than >, less than or equal <=, greater than or equal >=
  • Lower precedence than arithmeticx + 1 < y evaluates the addition before the comparison; parentheses clarify intent

Logical Operators (&&, ||, !)

  • Combine boolean expressions—AND && requires both operands true; OR || requires at least one true; NOT ! inverts the value
  • Short-circuit evaluation&& stops if the left operand is false; || stops if the left operand is true; this prevents unnecessary computation and potential errors
  • NOT has high precedence!x && y applies NOT to x only; use parentheses !(x && y) to invert the entire expression

Compare: && vs. &—logical AND (&&) works on truth values and short-circuits; bitwise AND (&) operates on individual bits and always evaluates both sides. Using & when you mean && is a common bug that sometimes works by accident.


Bitwise and Low-Level Operations

Bitwise operators manipulate individual bits within integers. These are essential for systems programming, embedded development, and optimization.

Bitwise Operators (&, |, ^, ~)

  • Operate on binary representations—AND & yields 1 only where both bits are 1; OR | yields 1 where either bit is 1; XOR ^ yields 1 where bits differ
  • NOT inverts all bits~ flips every bit; ~0 becomes all 1s (typically 1-1 in two's complement)
  • Masking and flags—use AND to extract specific bits, OR to set bits, XOR to toggle bits; essential for hardware control and compact data storage

Shift Operators (<<, >>)

  • Left shift multiplies by powers of 2x << n is equivalent to x×2nx \times 2^n; bits shift left, zeros fill from the right
  • Right shift divides by powers of 2x >> n is equivalent to x÷2nx \div 2^n for unsigned types; behavior varies for signed negatives
  • Faster than multiplication/division—compilers often optimize arithmetic to shifts automatically, but explicit shifts clarify intent in bit manipulation code

Compare: << vs. *—left-shifting by 1 (x << 1) doubles x just like x * 2, but shifting is a single CPU instruction. For powers of 2, shifting is idiomatic in systems code; for general multiplication, use * for clarity.


Special-Purpose Operators

These operators serve specific roles that don't fit neatly into other categories. Each solves a particular programming problem elegantly.

Conditional Operator (? :)

  • Ternary inline if-else—syntax is condition ? value_if_true : value_if_false; the only C operator taking three operands
  • Returns a value—unlike if-else statements, this is an expression: max = (a > b) ? a : b assigns directly
  • Keep it simple—nested ternary operators become unreadable quickly; use if-else for complex logic

Sizeof Operator

  • Returns size in bytessizeof(int) gives the byte count for an int on your system (commonly 4 bytes)
  • Works on types and variablessizeof(x) returns the size of variable x; parentheses optional for variables but required for type names
  • Essential for memory allocationmalloc(n * sizeof(int)) ensures portable, correct memory requests regardless of platform

Comma Operator (,)

  • Evaluates left-to-right, returns rightmost—in (a = 1, b = 2, a + b), all three execute but the expression yields 33
  • Common in for loopsfor (i = 0, j = 10; i < j; i++, j--) initializes and updates multiple variables
  • Lowest precedence—parentheses are usually needed to prevent the comma from being interpreted as a separator rather than an operator

Compare: Conditional ? : vs. if-else—both make decisions, but the ternary operator is an expression returning a value while if-else is a statement. Use ternary for simple value selection; use if-else for complex actions or multiple statements.


Memory and Pointer Operations

Pointer operators give you direct access to memory addresses. Understanding these is crucial for dynamic memory, arrays, and efficient function calls.

Pointer Operators (* and &)

  • Ampersand gets addresses&x returns the memory address where variable x is stored; this address can be stored in a pointer
  • Asterisk dereferences pointers—if p holds an address, *p accesses the value at that address; also used in pointer declarations (int *p)
  • Foundation for advanced C—pointers enable dynamic memory allocation, efficient array handling, and pass-by-reference function parameters

Compare: * in declarations vs. expressions—int *p declares p as a pointer to int; *p = 5 dereferences p to store 5 at the pointed-to location. Same symbol, different contexts—this trips up many beginners.


Quick Reference Table

ConceptBest Examples
Basic math operations+, -, *, /, %
Value modification=, +=, -=, ++, --
Comparisons==, !=, <, >, <=, >=
Boolean logic&&, `
Bit manipulation&, `
Conditional expressions? :
Memory and sizesizeof, *, &
Multiple expressions, (comma operator)

Self-Check Questions

  1. What is the output of int x = 5; int y = x++; for both x and y? How would the result differ with ++x?

  2. Why does 7 / 2 evaluate to 3 in C, and what are two ways to get the result 3.5 instead?

  3. Compare && and &: when would using the wrong one cause a bug, and when might it accidentally work correctly?

  4. If int a = 10; and int *p = &a;, what do p, *p, and &a each represent? How would you use these to change a's value to 20?

  5. Trace this expression: int result = (3 > 2) ? (4 + 1) : (4 - 1); What value does result hold, and how would you rewrite this using an if-else statement?