Operators
| Contents |

Way back when, computers were used primarily as calculators.
Some whiz-bang programmer would code up some formula and
run the program on a bunch of data. In fact, the very first
high-level programming language was called Fortran, for *for*mula
*tran*slation.
Fortran, and most every language that came after it, supplied
a full complement of mathmatical operators.
C is no exception.
For example, suppose you have forgotten your times table
and aren't quite sure whether 8 times 7 is 54 or 56. We can write
a C program to tell us the answer:

//test printf("%d\n",8 * 7); //should print: 56

Of course, we can multiply variables as well as numbers:

//test int x = 8; int y = 7; printf("%d\n",x * y); //should print: 56

We can also intermix variables and numbers:

//test int x = 8; printf("%d\n",x * 7); //should print: 56

Time for some terminology. The
multiplication sign `*`

is known as an *operator*, as it *operates* on the numbers
or variables on either side of it,
producing an equivalent literal value. The items preceding and following
the multiplication sign are
known as *operands*. It seems that the actual names of various operands are
not being taught anymore, so for nostalgia's sake, here they are. The
operand to the left of the multiplication sign is
known as the *multiplicand*. The operand to the right
is known as the *multiplier*. The result is known as the *product*.

The operands of the other basic operators
have special names too. For addition, the left operand is known as the
*augend* and the right operand is known as the *addend*.
The result is known as the *sum*.
For subtraction,
the left operand is the *minuend*, the right the *subtrahend*, and
the result as the *difference*.
For division (and I think this is still taught), the left operand is
the *dividend*, the right operand is the *divisor*, and the
result is the *quotient*.

In general, we will separate
operators from their operands by
spaces, tabs,
or newlines, collectively known as *whitespace*.^{14}
It's not necessary to do so, but it makes your code
easier to read.

C always takes an expression and computes an equivalent literal expression (e.g., integer or real). Most of the C operators are binary, meaning they operate on exactly two operands. We first look at the numeric operators.

If it makes sense to add two numbers together, you can probably do it in C using the + operator. For example:

//test printf("%d\n",2 + 3); //should print: 5 printf("%f\n",1.9 + 3.1); //should print: 5.000000

One can see that if one adds two integers, the result is an integer. If one does the same with two reals, the result is a real.

Things get more interesting when you add things having different types. Adding an integer and a real (in any order) always yields a real.

//test printf("%f\n",2 + 3.3); //should print: 5.300000 printf("%f\n",3.3 + 2); //should print: 5.300000

Adding a string to a real number yields an error; the types are not "close" enough, like they are with integers and reals. This statment:

printf("%f\n",2.2 + "123");

generates the following error when compiled:

error: invalid operands to binary + (have 'double' and 'char *')

In general, when adding two things, the types must match or nearly match.

Subtraction, multiplication, and division of numbers follow the same rules as addition. Of special note is the division operator with respect to integer operands. Consider evaluating the following expression:

15 / 2

If one asked the C compiler to compute the result, the value
7, not 7.5, would be produced.
This is because, when given an integer dividend and an integer
divisor, the quotient will be an integer. Since 7.5 is not an
integer, the fractional part is lopped off to make it an integer.
If we wish to compute a real result, we need to *cast* the operands:

//test int x = 15, y = 2; int i_quotient; double r_quotient; //calculate! i_quotient = x / y; r_quotient = (double) x / (double) y; //(double) is a cast printf("%d and %f\n",i_quotient,r_quotient); //should print: 7 and 7.500000

For division, dividing an integer dividend by a real divisor or vice
versa, a real number results. Therefore,
we could have used any of the following
ways to compute *r_quotient*.

r_quotient = (double) x / (double) y; r_quotient = (double) x / y; r_quotient = x / (double) y;

The complement to integer division is the modulus operator %. While the result of integer division is the quotient, the result of the modulus operator is the remainder. Thus

14 % 5

evaluates to 4 since 4 is left over when 5 is divided into 14. To check if this is true, one can ask C to compute this expression:

(14 / 5) * 5 + (14 % 5) == 14

This complicated expression asks the question "is it true that the quotient times the divisor plus the remainder is equal to the original dividend?". Running the following code will show that, indeed, it is true as a 1 is printed.

$ quickc > printf("%d\n",(14 / 5) * 5 + (14 % 5) == 14); + compiling the program... running the program... 1 >

The first set of parentheses in the expression surrounds the quotient while the second pair surrounds the remainder.

We can also use the modulus operator to check whether a value is even or odd. The expression

x % 2 == 0

evaluates to true if the value of *x* is even, false otherwise.

Precedence (partially) describes the order in which operators, in an expression involving different operators, are evaluated. In C, the expression

3 + 4 < 10 - 2

evaluates to true. In particular, `3 + 4` and `10 - 2`
are evaluated before the `<`, yielding `7 < 8`,
which is indeed true. This implies that `+` and
`-` have higher precedence than `<`. If
`<` had higher precedence, then `4 < 10`
would be evaluated first, yielding `3 + True - 2`, which
is nonsensical.

Note that precedence is only a partial ordering. We cannot tell, for
example whether `3 + 4` is evaluated before the `10 - 2`,
or vice versa. Upon close examination, we see that it does not
matter which is performed first as long as both are performed before
the expression involving `<` is evaluated.

It is common to assume that the left operand is evaluated before the right operand. For the BOOLEAN connectives And and Or, this is indeed true. But for other operators, such an assumption can lead you into trouble. You will learn why later. For now, remember never, never, never depend on the order in which operands are evaluated!

The C language has a complete precedence chart that illustrates operator precedence for all possible operators. This chart includes 15 levels of precedence. However, since it includes a number of operators that we have not yet discussed, we will simply provide you with a subset of this chart for now.

- The lowest precedence operator in C is the assignment operator (which is described later)
- Next, the BOOLEAN connectives And and Or
- At the next higher level are the BOOLEAN
comparatives,
`<`,`<=`,`>`,`>=`,`==`, and`!=` - After that come the additive arithmetic operators
`+`and`-` - Next comes the multiplicative operators
`*`,`/`and`%`. - Finally, at the highest level of precedence is the selection,
or
*dot*, operator (the dot operator is a period or full-stop).

Higher precedence operations are performed before lower precedence operations. Functions which are called with operator syntax have the same precedence level as the mathematical operators.

Parentheses can also be used to change the *precedence*
of operators; in a complicated expression composed of differing operators,
subexpressions with parentheses are done first,
then dot operations,
then division and mulitplication, then addition and subtraction, and so on.

General comment on precedence: unless you have the C Operator Precedence Chart memorized, it is always a good idea to use lots of parentheses whenever you are using multiple operators in an expression or statement. That way, you know exactly how things will be handled.

Finally, you are encouraged to find a complete C Operator Precedence Chart on the web and examine it. It contains lots of useful information.

Associativity describes how multiple expressions connected by operators at the same
precedence level are evaluated. All the operators, with the exception of
the assignment operator, are left associative.
For example, the expression
*5 - 4 - 3 - 2 - 1* is equivalent to *((((5 - 4) - 3) - 2) - 1)*. For
a left-associative structure, the equivalent, fully parenthesized,
structure has open parentheses piling up on the left. If the minus
operator was right associative, the equivalent expression would be
*(5 - (4 - (3 - (2 - 1))))*, with the close parentheses piling up on
the right. For a commutative operator, it does not matter whether it
is left associative or right associative. Subtraction, however, is not
commutative, so associativity does matter. For the given expression, the
left associative evaluation is -5. If minus were right associative, the
evaluation would be 3.

Like subtraction, division, which is non-commutative, exhibits left associativity. In the expression:

a / b / c / d

the divisions are done from left to right. The above expression is equivalent to:

(((a / b) / c) / d)

The assignement operator, covered in the next chapter, exhibits right associativity.

Remember the BOOLEAN interpretation of integers? We can use the BOOLEAN comparison operators to generate such values. For example, we can ask if 3 is less than 4:

//test int b = 3 < 4; printf("%d\n",b); //should print: 1

The output says that, indeed, 3 is less than 4, since 1 is considered
true.
If the expression had resolved to false,
the output would be 0, since 0 represents falsity.
Besides
`<`

(less than),
there are other BOOLEAN comparison operators:
`<=`

(less than or equal to),
`>}`

(greater than),
`>=`

(greater than or equal to),
`==`

(equal to), and
`!=`

(not equal to).

Note that two equal signs are used to see if to things are the same. A single equals sign is reserved for the assignment operator, which you will learn about in the next chapter.

Besides integers, we can compare reals with reals and integers and reals
using the comparison operators. We cannot compare strings with strings
using the BOOLEAN operators, however. We need a special operator to
do that. This operator, *strcmp*, is covered in the chapter on strings.

We can combine comparisons with the BOOLEAN logical connectives
`&&`

and `||`

, logical **AND** and logical **OR**,
respectively.

//test int b = 3 < 4 && 4 < 5; //true AND true printf("%d\n",b); //should print: true (which is 1) b = 3 < 4 || 5 < 4; //true OR false printf("%d\n",b); //should print: true (which is 1) b = 3 < 4 && 5 < 4; //true AND false printf("%d\n",b); //should print: false (which is 0)

The first bit of code asks if both the expression
`3 < 4`

and the expression
`4 < 5`

are true. Since both are,
*C* calculates a `1`

. The second bit of code
asks if at least one of the expressions is true. Again,
*C* calculates a `1`

. The difference between `&&`

and `||`

is illustrated by the last two interactions. Since
only one expression is true (the latter expression being
false) only the `||`

operator yields a true value.

There is one more BOOLEAN logic operation, called
*not*. It simply reverses the value of the expression
to which it is attached. The *not* operator is represented by
an exclamation point (Computer Scientists call it 'bang'):

int b = !(3 < 4 && 4 < 5); printf("%d\n",b); //should print false (which is 0) b = !(3 < 4 || 5 < 4); printf("%d\n",b); //should print false (which is 0) b = !(3 < 4 && 5 < 4); printf("%d\n",b); //should print true (which is 1)

Note that we attached *not* to each of the previous expressions involving
the logical connectives. Note also that the calculated result
is reversed from before in each case.

In terms of precedence, `&&`

and `||`

are lower
than the comparison operators,
which in turn are lower than the mathmatical operators.

Operators
| Contents |