# “Modern C”: Notes on chapter 4 “Expressing computations”

By **Dmitry Kabanov**

These are my notes taken while reading chapter 4 “Expressing computations” from the book “Modern C” by Jens Gustedt.

This chapter discusses expressions, that is, computations based on some values, such as variables and literals.

The table of contents for all notes for this book are available in that post.

Values used in this chapter are based on type `size_t`

which is
C representation of non-negative integers (natural numbers and
zero), although on computer this is a finite set of numbers.

*Takeaway 4.1*. The type `size_t`

represents values in the range
`[0, SIZE_MAX]`

.

Constant `SIZE_MAX`

comes from the header file `stdint.h`

.
Previously, computers had 32-bit processors and the value of
`SIZE_MAX`

was about 4 billions (precisely, \(2^{32} - 1\), where
“minus 1” is to accomodate zero).
Nowadays, most processors are 64-bit and `SIZE_MAX`

is much larger
(exact value is \(2^{64} - 1\), which is a number with 20 digits).

## 4.1 Arithmetic

Arithmetic operators `+`

, `-`

, `*`

, `/`

work in general
as we expect from mathematics.
For unsigned values such as variables of type `size_t`

the result
is always well-defined.

When performing arithmetic, division `/`

and modulus `%`

are
well-defined only if the second operand is not 0.

Sometimes the result of an arithmetic operation is such that
it is not within range [0, `SIZE_MAX~], for example, it can become negative or larger than ~SIZE_MAX`

(overflow).
In such cases, arithmetic on `size_t`

values “wraps around”,
that is, the result is replace with the remainder of modulus
operation `% (SIZE_MAX + 1)`

.
For example, -1 becomes `SIZE_MAX`

, while `SIZE_MAX + 1`

becomes 0.

## 4.2 Operators that modify objects

The first example is the assignment operator `=`

.
In C terminology, the right side is called **rvalue** and the left
side is called **lvalue**.

C has compact assignment operators for such expressions:

```
var = var O expression
```

which can be replaced with

```
var O= expression
```

where `O`

is `+`

, `-`

, `*`

, `/`

.

Also, often used operators are increment `i++`

and `++i`

and
decrement `i--`

and `--i`

. Postfix forms first return the value of
`i`

and then modify it, while prefix forms first modify `i`

and
then return the new value.
It is not recommended to use these operators in more complex
expressions directly but always as separate statements to improve
code readability.

## 4.3 Boolean context

Boolean expressions use comparison and logic operators
and always return values `false`

or `true`

.
Note that `false`

and `true`

in C are the same as 0 and 1,
respectively, so they can be used in arithmetic expressions.

Comparison operators are: equal to `==`

, not equal to `!=`

, less than `<`

,
less or equal to `<=`

, greater than `>`

, greater or equal to `>=`

.

Logic operators are: not `!`

, logical and `&&`

, logical or `||`

.

Logical and and or use “short-curcuit evaluation”, so that if the value of a logical expression can be determined from one of the subexpressions, other subexpressions are not evaluated:

```
if ((b != 0) && ((a/b) > 1)) {
// Subexpressions (a/b) > 1 is not evaluated at all
// if b equals to zero.
}
```

## 4.4 The ternary or conditional operator

The ternary operator is a compact form from an `if-else`

statement
with assignment. For example, this is how a minimum of two numbers
can be computed:

```
min_a_b = (a < b) ? a : b;
```

## 4.5 Evaluation order

C has comma operator, such that expression `f(a), f(b)`

first
evaluates `f(a)`

and then evaluates `f(b)`

and returns the value
of `f(b)`

.
The comma operator is rarely useful and is confusing.
For example, in `A[i, j]`

the result is `A[j]`

.

*Takeaway 4.16*. Do not use comma operator.

Most operators do not have a predefined order, so that the result
can be different depending on the order: for example, if
function `f`

changes some global state, the result of `f(a) + f(b)`

probably depends on the order in which they are evaluated.

*Takeaway 4.19*. Functions that are called inside expressions
should not have side effects.

This is the only way to preserve sanity while programming in C.