# More on Expressions

Expressions do most of the work of a C program. Expressions handle arithmetic operations as well as other things like calling functions.

## Operators

Operators are the connections between elements of an expression, for instance, + for addition. As in algebra, every operator has a precedence, a priority among the other operators as to which gets evaluated first. For example, in the expression a + b * c, the multiplication of b and c comes first even though a comes first from left to right because multiplication has a higher precedence than addition. Precedence can be overridden, again as in algebra, with parentheses, e.g. (a + b) * c.

In addition to precedence, there is also another property of operators: their associativity. Some operators associate from left to right, for example, the following divisions: a / b / c are performed like this:(a / b) / c. Other operators associate from right to left. For some operators like +, it doesn't really matter since addition has the associative property, i.e., (a + b) + c is the same as a + (b + c).

Here is a list of C operators, in order from highest to lowest precedence, giving their associativities. Some operators seem to be listed more than once, like -; these are instances where the same symbol is used to represent two different operators, like unary minus (the minus sign) and binary minus (subtraction). Many of these operators have special purposes beyond the scope of this lecture; we will go into these in more detail later.
```1               () [] -> .                              lr
2               ! ~ ++ -- + - * & (type) sizeof         rl
3               * / %                                   lr
4               + -                                     lr
5               << >>                                   lr
6               < <= > >=                               lr
7               == !=                                   lr
8               &                                       lr
9               ^                                       lr
10              |                                       lr
11              &&                                      lr
12              ||                                      lr
13              ?:                                      rl
14              = += -= *= /= %= &= ^= |= <<= >>=       rl
15              ,                                       lr
```

## Integer, Floating Point, and Mixed Arithmetic

When all of the objects involved in an expression are integers, the resulting values are also integers. For instance, consider the following program:
```#include <stdio.h>

int main () {
int	a;

a = 2 * (100 / 5);
}
```
The computation involves only integer constants and variables, so all the arithmetic is integer arithmetic. This is usually what we want, but there are some cases when this can lead to confusion:
• Integer division results in an integer. In C, 21 / 5 is 5, not 5.25 or 5 and 1/4. You can find the remainder with the modulus operator, %. For example, 21 / 5 is 5 remainder 1, so 21 % 5 is 1.
• C integers have limits on the numbers they can hold. This is normally not a problem, but when working with large integers, intermediate results represented as integers can overflow the number of bits needed. For example, consider the following C program:
```#include <stdio.h>

int main () {
int     a, b, c;

a = 1000000;
b = 1000000;
c = (a * b) / 1000000;
printf ("%d\n", c);
}
```
The output is clearly supposed to be 1,000,000, but when I run it on my computer I get -727. Although 1,000,000 is well within the 32-bit limit of my computer, the intermediate result the computer gets when multiplying 1,000,000 by 1,000,000 overflows 32 bits and the result is garbage.

## Floating Point Arithmetic

floats and doubles overflow less frequently because they can represent much larger numbers at the expense of precision. All floating point arithmetic in C is done in the double format; if a float is involved in an expression, its value is converted to double before it is used. If an assignment to a float is being made, the result is automatically changed from double to float at the end of the execution of the expression. It is important when working with floating point arithmetic that you specify constants as floating point even when they are integers, e.g., 5.0 instead of just 5. This makes it clear to both the reader and the compiler that the math is being done in a floating point context.

## Mixed Arithmetic

When an expression involving both integer and floating point objects is evaluated, the integer values are changed into doubles right before they are used in a floating point operation. So in the expression
```(30 / 20) + (10.0 / 20)
```
the 10 / 20 part is done as integer arithmetic, so that result is 1 (remainder 10). Since the second division involves a floating point constant 10.0, the integer constant 20 is changed to double and then the division is peformed in floating point, yielding 0.5. So the entire sum is 1 + 0.5 = 1.5.

## Errors in Arithmetic

There are several kinds of errors one can make when writing a program with arithmetic expressions. Some of them are caught during compile-time, for example, trying to put a floating point value into an integer. Others can only be found at run-time, like division by zero, taking the square root or logarithm of a negative number, or evaluating the tangent function at its asymptotes. C is special in that some arithmetic errors can occur without generating any error messages at all, like overflowing integer arithmetic.