Part of C in 100s

C in 100 Seconds: Arithmetic Operators | Episode 4

Celest KimCelest Kim

Video: C in 100 Seconds: Arithmetic Operators | Episode 4 by Taught by Celeste AI - AI Coding Coach

Take the quiz on the full lesson page
Test what you've read · interactive walkthrough

C Arithmetic Operators

+ - * / and % (modulo). The classic gotcha: 17 / 5 is 3, not 3.4. Integer division truncates. Use a float operand to get the decimal back.

C's arithmetic looks like math, mostly. Integer division is the one big surprise — and one of the most common bugs in early C code.

The five operators

#include <stdio.h>

int main() {
  int a = 17, b = 5;

  printf("%d + %d = %d\n", a, b, a + b);    // 22
  printf("%d - %d = %d\n", a, b, a - b);    // 12
  printf("%d * %d = %d\n", a, b, a * b);    // 85
  printf("%d / %d = %d\n", a, b, a / b);    // 3 (!)
  printf("%d %% %d = %d\n", a, b, a % b);   // 2

  return 0;
}

+, -, *, /, %. Standard for any C-family language. %% in the format string prints a literal % (because a single % would start a format specifier).

Integer division truncates

printf("17 / 5 = %d\n", 17 / 5);            // 3
printf("17.0 / 5 = %.1f\n", 17.0 / 5);      // 3.4

When both operands are integers, / truncates toward zero. 17 / 5 is 3 (not 3.4, not 4).

To get the decimal answer, at least one operand must be a float or double:

  • 17.0 / 53.4
  • 17 / 5.03.4
  • (double)17 / 53.4 (explicit cast)

If you accidentally use two ints, your decimal result becomes integer:

double avg = 17 / 5;   // 3.0 (because 17/5 is 3, then promoted to double)

To fix:

double avg = 17.0 / 5;   // 3.4

This is one of the top three bugs in beginner C code. Always check types before division.

Modulo: the remainder

printf("17 %% 5 = %d\n", 17 % 5);   // 2

a % b is the remainder of a / b. For 17/5: quotient is 3, remainder is 2 (because 5×3 + 2 = 17).

Useful for:

  • Even/odd: n % 2 is 0 if even, 1 if odd.
  • Loop step: "every Nth iteration": if (i % 10 == 0).
  • Wrapping: index % size always falls in [0, size).
  • Digit extraction: n % 10 is the last digit of n.

% only works on integers. 17.0 % 5 doesn't compile — for floats, use fmod from math.h:

#include <math.h>
double r = fmod(17.5, 5.0);    // 2.5

Negative modulo

printf("%d\n", -17 % 5);   // -2 (in C99+)
printf("%d\n", 17 % -5);   // 2

In C99 and later, % matches the dividend's sign. -17 % 5 is -2, not 3. Different from Python, which returns 3.

For "true" modulo (always non-negative):

int true_mod(int a, int b) {
  int r = a % b;
  return (r < 0) ? r + b : r;
}

Operator precedence

int x = 2 + 3 * 4;        // 14, not 20
int y = (2 + 3) * 4;      // 20

Standard math precedence:

  1. () — explicit
  2. unary -, +, !, ~
  3. *, /, %
  4. +, -

When in doubt, parenthesize. Code clarity beats character count.

Increment and decrement

int i = 5;
i++;        // i = 6
i--;        // i = 5
++i;        // i = 6 (prefix)

int x = 5;
int y = x++;     // y = 5, then x = 6 (post-increment)
int z = ++x;     // x = 7, then z = 7 (pre-increment)

i++ returns the old value, then increments. ++i increments first, then returns the new value. Inside expressions this matters; as a standalone statement it doesn't.

Avoid using ++/-- inside complex expressions — readability suffers and undefined behavior lurks (a[i++] = i; has undefined evaluation order).

Compound assignment

int x = 10;
x += 3;        // x = x + 3 = 13
x -= 2;        // x = 11
x *= 5;        // x = 55
x /= 4;        // x = 13 (integer division!)
x %= 5;        // x = 3

Shorthand for x = x op value. Same precedence rules.

Mixing types

int i = 5;
double d = 2.5;

double r = i + d;     // 7.5 — i promoted to double
int n = i + d;        // 7 — entire expression cast to int (truncate!)

C automatically promotes the smaller type to the larger one (intdouble). The result type is the larger.

When assigning to a smaller type, the value is converted (truncated for float-to-int). The compiler may warn (-Wconversion).

Common mistakes

Integer division by accident. int avg = total / count; when total/count is meant to be a decimal. Use (double)total / count.

Modulo with float. 17.5 % 5 doesn't compile. Use fmod(17.5, 5.0).

Off-by-one with %. i % size for index in array of size size is 0 to size-1 — correct for arrays. But i % size for "1-based" indexing breaks at size (gives 0, not size).

Operator precedence guesses. 1 << 2 + 3 is 1 << (2 + 3) = 32, not (1 << 2) + 3 = 7. Parenthesize bit-shifts.

Division by zero. 5 / 0 is undefined behavior. Compile-time constant: error. Runtime: usually a SIGFPE crash (Linux/macOS) or silent garbage. Always check.

Overflow. 2000000000 * 2 (fits in int?) overflows silently. Result is undefined. Use long or int64_t for large products.

What's next

Episode 5: if / else. Conditional branching, ternary operator, and a 14-line grade calculator.

Recap

+ - * / plus % (integer remainder). Integer division truncates: 17/5 = 3. Use a float operand for decimal: 17.0 / 5 = 3.4. % only works on ints; use fmod for floats. % matches dividend's sign in C99+. Compound assignment: +=, -=, etc. Increment: i++ (post) returns old then increments; ++i (pre) increments then returns new. Watch for division by zero (undefined) and integer overflow (undefined).

Next episode: if/else.

Ready? Take the quiz on the full lesson page →
Test what you've learned. Watch the lesson and try the interactive quiz on the same page.