Skip to content
VLSI Mentor

C Part I · Module 3 · Expressions and Operators

Arithmetic Operators

The arithmetic operators are the least surprising thing in C — addition adds, multiplication multiplies, and nobody needs a tutorial to guess that. What is worth a chapter is the property Chapter 3.1 asked you to start noticing: the type of the result. Two int operands produce an int result, and that single sentence turns out to explain both the behaviour that catches every beginner in the next chapter and the reason a calculation can silently leave the range its type can hold. So this chapter introduces the operators quickly and then spends its time on the two questions that actually matter: what type comes out, and what happens when the answer will not fit.

Foundation10 min readCPart IFundamentalsExpressions

Part I · Module 3 · Chapter 3.2 · Arithmetic Operators

1. The Operators

C has five arithmetic operators. Four of them behave exactly as you would expect:

Azvya Education Pvt. Ltd.VLSI Mentor
the unsurprising ones
#include <stdio.h>

int main(void)
{
    int a = 7;
    int b = 3;

    printf("a + b = %d\n", a + b);
    printf("a - b = %d\n", a - b);
    printf("a * b = %d\n", a * b);
    printf("-a    = %d\n", -a);
    return 0;
}

Output:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
a + b = 10
a - b = 4
a * b = 21
-a    = -7

+, - and * each take two operands. - also has a one-operand form, as in -a, which produces the negative of its operand without changing it — a still holds 7 afterwards, for the reason Chapter 3.1 gave: computing with an object reads it.

The fifth and sixth are / and %, for division and remainder. They are not covered here. Division in C produces a result that is completely correct and surprises nearly everyone the first time, and it deserves the whole of Chapter 3.3 rather than a paragraph at the end of this one.

2. The Result Has a Type, and the Operands Choose It

Chapter 3.1 asked you to get into the habit of asking two questions about every expression. Here is the answer to the second one for arithmetic:

When both operands are int, the result is an int.

That sentence looks like it says nothing. It is in fact the most consequential rule in this module, because it means the result has to be representable as an int — and an int can only hold whole numbers, within a range.

Two things follow, and each gets its own chapter:

  • A result that is not a whole number has nowhere to go. That is Chapter 3.3.
  • A result outside the type's range has nowhere to go either. That is the rest of this chapter.

More generally, the type of an arithmetic result is decided by the types of the operands, not by the size of the answer. C works out the result type from the expression before the program runs; it does not look at the values and pick something roomy.

3. When the Answer Does Not Fit

Chapter 2.5 established that every integer type has a limited range, and Chapter 2.6 established what happens at the edges. Arithmetic is where you actually arrive at them.

Multiply two large int values and the mathematical answer may be far outside what an int can hold. C does not notice this on your behalf, widen the type, or produce an error. The behaviour depends on the operands' type, and the two cases are genuinely different:

  • Unsigned operands: the result wraps, and C defines this. Chapter 2.6 showed it.
  • Signed operands: the result is undefined. C promises nothing.

That asymmetry is Chapter 2.6's and is not re-argued here. What this chapter adds is where it bites: an ordinary-looking multiplication is one of the commonest ways to reach it, because products grow much faster than the operands do. Two values well inside the range can easily have a product well outside it.

This chapter does not demonstrate signed overflow, for the reason Chapter 2.6 gave: any output would be a fact about one run and would teach you that the result is worth knowing. Module 13.4 returns to it with the tools for avoiding it. For now:

Arithmetic can leave the range, C will not warn you at run time, and for signed types there is no defined result to fall back on.

4. What Does Not Happen

Three things beginners expect that C does not do. Each is worth stating because expecting them produces bugs that look inexplicable.

The type does not grow to fit the answer. int * int is int, whatever the values. There is no automatic promotion to a wider type because the product got large.

Operands are not modified. Every expression in §1 read its operands and produced a new value. a + b leaves both alone. This is Chapter 3.1's point and it holds for every operator in this chapter.

There is no rounding. Nothing in §1 produced a fractional result, so nothing had to be rounded — but this expectation is the one that catches people in the next chapter, so it is worth flagging now. C does not round a division result to the nearest whole number. What it does instead is Chapter 3.3's subject.

5. What You Should Be Able to Say Now

  1. C's arithmetic operators are +, -, *, / and %. This chapter covers the first three; - also has a one-operand negation form.
  2. Arithmetic operators read their operands and produce a new value. Nothing is modified.
  3. The result has a type, decided by the operands — int with int gives int.
  4. C determines the result type from the expression, not from how large the answer turns out to be.
  5. A result outside the type's range has nowhere to go: unsigned wraps (defined), signed overflow is undefined.
  6. Multiplication is the commonest way to reach that edge, because products grow fast.
  7. C does not widen the type to fit, does not warn at run time, and does not round.

6. Exercise

Exercise 1 — predict, then run. Give the exact output:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
int x = 10;
int y = 4;

printf("%d\n", x - y);
printf("%d\n", x * y);
printf("%d\n", -y);
printf("%d\n", x);

Exercise 2 — name the type. For each expression, where a and b are both int, give the value and the type: a + b, -a, a * a, 3 + 4.

Exercise 3 — spot the risk. Both are int on a machine where an int holds up to about two billion. Say which line is risky and why the other is not:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
int a = 50000;
int b = 50000;
int sum = a + b;
int product = a * b;

Exercise 4 — classify the edge. Using Chapter 2.6, say what C guarantees for each: an unsigned int multiplication whose answer exceeds the range; an int multiplication whose answer exceeds the range.

Exercise 5 — reject the expectation. A colleague says: "If the answer gets too big, C will just use a bigger type." Give two reasons this is wrong, using §2 and §4.

7. Summary

  • +, -, * behave as expected, and - also negates a single operand. / and % are Chapter 3.3's.
  • Operands are read, never modified.
  • The result's type comes from the operands, decided before the program runs and regardless of how large the answer is.
  • int with int gives int — a sentence that sounds empty and explains the whole of the next chapter.
  • Leaving the range is a real risk, reached most often through multiplication: unsigned wraps by definition, signed overflow is undefined.
  • C does not widen, warn at run time, or round.

Two operators were deliberately left out of this chapter. One of them produces, for 7 / 2, the answer 3 — which is not a bug, not a rounding choice, and follows directly from the one rule this chapter has been building. That is the next chapter.

Standards & specifications

Governing standard
ISO/IEC 9899 (the C language standard)(opens ISO/IEC (JTC 1/SC 22/WG 14) in a new tab)

Defines the C language itself — the type system, expression semantics, object model, storage duration and the behaviour categories a conforming implementation must honour. It is a FAMILY of editions (C89/C90, C99, C11, C17, C23) and this curriculum names the edition wherever a claim depends on one. It does not define any foreign-function interface to a hardware description language, and it does not define platform behaviour: what a memory-mapped access does on real silicon is the implementation's and the device's contract, not this standard's. Working drafts published by WG14 are freely available and are what most engineers read day to day; a draft is not the published standard.

This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.

Where this fits

Part of the C Programming curriculum.