5.1.4 · D1C Programming

Foundations — Operators — arithmetic, relational, logical, bitwise, assignment, comma

3,909 words18 min readBack to topic

Before you can trust a single line of C, you need a small toolbox of ideas that the parent note quietly assumes. This page builds each one from nothing — plain words, then a picture, then why the topic needs it. Every symbol is defined before it is used: we start with the two plainest words, then the atoms (bits), then earn each operator symbol one at a time.


0. The two words underneath everything: "value" and "operator"

Before any symbol, pin down the two plainest words the core idea leans on.

Everything below is the machinery that decides which new value comes out. Keep those two words in hand; the whole page is about the values that flow into operators and the values that flow back out.


1. The four plain arithmetic operators + - * /

The most familiar operators are the ones from grade-school arithmetic. They are all binary (two operands) and mean exactly what you expect.

Now that these four symbols are earned, the rest of the page can safely use them in examples.


2. What is a "bit"? (the atoms)

Everything a computer does is built from a bit: a single tiny switch that is either off (0) or on (1). That's the whole vocabulary — two states.

A number like 12 is not stored as the shape "12"; it is stored as a row of switches. Look at the figure: the number is written in base 2, meaning each switch is worth double the one to its right.

Figure — Operators — arithmetic, relational, logical, bitwise, assignment, comma

Why base 2 and not base 10? Because a wire is easiest to build as "voltage or no voltage" — two states. The whole machine is cheapest when its alphabet has exactly two letters.


3. Powers of two — the place values

The place values 1, 2, 4, 8, 16, ... are the powers of two. We write to mean "multiply 2 by itself times", where is a whole number (we never need negative here — a negative exponent like would mean the fraction , and switch-columns only ever go up in whole steps). By convention (multiplying zero twos leaves you with 1, the starting point).

Figure — Operators — arithmetic, relational, logical, bitwise, assignment, comma

(The right shift also lives here, but reasoning about it needs the "floor" idea and the sign switch — we build both in the next two sections, then state the shift rule cleanly once we have the tools.)


4. Truncation, floor, and "toward zero"

The parent says integer / truncates toward zero. Three words, three meanings — let's earn them on a number line.

Figure — Operators — arithmetic, relational, logical, bitwise, assignment, comma

For positive numbers truncate and floor agree (3.53 either way). They only differ for negatives — which is exactly why the parent's -7/2 = -3 example needs this distinction.


5. Sign: how a switch-row holds a negative number

The parent writes -7 / 2 and -7 % 2. But if a byte is just switches worth , how is anything negative? The trick is called two's complement: the leftmost switch is given a negative place value.

How do you actually build from ? The recipe is invert every bit, then add 1 (here "invert" means flip every switch, the ~ operation earned in section 9):

  • Start with 0000 0111.
  • Invert every switch: 1111 1000.
  • Add 1: 1111 1001.

Check that this really is using the negative top-bit: . ✓

Why invert-and-add-1 works, in one sentence: inverting turns into "(all-ones) ", and all-ones is in this scheme, so inverting gives ; adding 1 lands you on . The full story lives in Two's Complement Representation; here you only need the picture: the top switch is a "sign switch", and negatives are made by invert-and-add-1.


6. Now the shift rule (needs powers of two + floor + sign)

The two shift operators slide a switch-row sideways.

With powers of two, floor, and the sign switch in hand, we can state what those slides compute.


7. Types: int vs double

A type is a label on a value saying what kind of thing it is and how it's stored.

The deep story of how one becomes the other is Data Types and Type Promotion; for the parent you only need one rule, shown below.


8. The two integer operators / and %

Now we can define what / does for whole numbers and introduce its partner %.


9. The four bitwise combiners & | ^ ~

Section 2 showed a number is a row of switches. These four operators work column by column on those switches. (~ is the "invert" tool we borrowed early in section 5 — here is its full definition.)

Figure — Operators — arithmetic, relational, logical, bitwise, assignment, comma

10. Arity — how many operands


11. Comparing values: relational & equality operators

These six operators ask a yes/no question about two values and hand back a clean answer.


12. Combining yes/no answers: logical operators

Once you can produce true/false values, you combine them with three logical operators.


13. Truth in C: 0, nonzero, and "true"

Classic C has no dedicated Boolean type. Instead:


14. Precedence & associativity — the seating order

When several operators sit in one expression, precedence decides who fires first, and associativity breaks ties between equals.

Figure — Operators — arithmetic, relational, logical, bitwise, assignment, comma

The prerequisite map

The diagram below is a dependency chart: read an arrow X --> Y as "you need X before Y makes sense." Follow any path and you'll see the order this page built things in — bits at the top feed everything, and every strand eventually flows down into the Operators topic itself.

Add sub mul div

Divide and remainder

Bits and bytes

Powers of two

Two's complement sign bit

Shift rule

Truncate toward zero

Floor and rounding

Types int vs double

Real vs integer division

Bitwise combiners AND OR XOR NOT

Relational and equality

Nonzero equals true

Logical AND OR NOT

Arity unary binary ternary

Precedence and associativity

Operators topic 5.1.4


Equipment checklist

Self-test: cover the right side and answer out loud.

A value and an operator are
a piece of data the program holds; and a symbol that takes operands (values) and produces a new value.
What do +, - (binary), and * each do to two values?
+ sums them; binary - takes the right from the left; * multiplies (repeated addition).
A bit and a byte are
a single on/off switch (0 or 1); and a row of bits C treats as one chunk — 8 on almost every machine, guaranteed at least 8 (CHAR_BIT).
Why is a number stored in base 2?
because a wire is cheapest as two states (voltage or none), so each column is worth double the one right of it.
means, and its domain of
multiply 2 by itself times, with a whole number ; sliding switches columns left multiplies by .
The floor means
the greatest whole number not larger than (round down toward ); -3.5-4.
How do you form from in two's complement?
invert every bit then add 1: 0000 01111111 10001111 1001; the top bit carries weight .
Difference between truncate toward zero and floor
they agree for positives; for negatives truncate keeps the value closer to 0 (-3.5-3) while floor goes down (-3.5-4).
What do << and >> compute for a non-negative x?
x << n = x * 2**n; x >> n = floor(x / 2**n).
Is x >> n == floor(x / 2**n) always true?
only for x >= 0; for negative signed x right-shift is implementation-defined, so use unsigned for bit work.
Why does 5/2 differ from 5/2.0?
/ reads operand types; two ints give integer division, a double gives real division.
What are / and % for integers, and what sign does % keep?
/ = whole times divisor fits (truncated toward zero); % = the leftover remainder, keeping the sign of the dividend a (never the divisor b).
What is -7 % -2 and why?
-1; -7 / -2 truncates 3.53, so -7 - 3*(-2) = -7 + 6 = -1, keeping the sign of the dividend.
What do & | ^ ~ each do to a column of bits?
AND keeps common ONs; OR keeps any ON; XOR keeps disagreements; NOT (unary) flips every bit.
How do the six relational/equality operators behave, and what do they return?
< > <= >= == != ask a yes/no question about two values and return an int 1 (true) or 0 (false).
What do &&, ||, and ! do, and how do they read their operands?
they read 0 as false and any nonzero as true; && true if both, || true if either, ! flips one truth value; result is 1 or 0.
Difference between && and &
&& reduces two values to a single true/false; & works column by column and can return any number. 1 && 2 is 1, 1 & 2 is 0.
In C, true is
any nonzero value; false is exactly 0; relational/logical ops return a clean 1 or 0.
Arity of ?:, !, and + (as in a+b)
ternary (3), unary (1), binary (2).
Precedence vs associativity, and which operators are right-associative
precedence = who fires first; associativity = tie-breaker for equals; most operators group left→right, but assignment, ?:, and unary prefixes group right→left.