Friday, November 28, 2014

Programming in C Chapter IV - Precedence

Precedence is how we answer the question: What operations should we perform first? Whether in solving mathematical equations or writing source code, strict procedural rules of precedence allow the same operations to produce the same results every time.

The first rule of precedence in the C programming language (and many others) is that we always work from the inner-most parentheses out-ward. This is particularly important to remember during bug-testing. Adding parentheses can be a good debugging tactic, but it is bad form to litter your code with un-needed parentheses.

The second rule is that when operators have equal priority, we simply solve from left to right.

With simple arithmetic, precedence or order of operations conforms to PEMDAS - from first to last, in pairs: parentheses and  exponents, multiplication and division, and finally addition and subtraction. Multiplication and division share the same precedence in this scenario because, functionally, they are the same operation. After all, division is merely multiplying by the inverse of the denominator. Similarly subtraction can be seen as merely adding a negative value.

example.
3 + 10 / 2 * (9 - 1) - 1
| --> we start with exponents
|
3 + 10 / 2 * 8 - 1           --> * and / are equal, so we do
  |         both but from left to right
  |       starting with /
3 +    5   * 8 - 1
  |
  |
3 +  40 - 1
|
|
   43 -  1
   | --> last we subtract the two
   | remaining digits
42


In C, there are two types of increment/decrement operators:

*Prefix Form*: ++i or --i
*Suffix Form*: i++ or i--

The *Suffix Form* is commonly used in "For" loops. It represents the idea that the current value is used first, and then that value is incremented. The value will only be different the NEXT time the variable is used.

By contrast, using the *Prefix Form* the variable is incremented FIRST, and then it is used in the expression.

Let us consider an example using the integer `x`, which for the purposes of this example we will set to `5`.

example.

int x = 5;

x++; /* x on this line is still 5
if we were to print it immediately
we would get the value 5 */
x; // here, on this line, x = 6
++x; /* using the prefix increment, the value is
incremented first - so on this line the
value would be 7 */

POINTER NOTATION

The last precedence issue that we will consider deals with pointer notation. The Dereference Operator - * - has priority over basic math operators, but not over the suffix increment and decrement operators. This leads us to our final example.

example.

int x = 7;    // we create an integer, x and set it to 7
int *y = &x;  /* we create a pointer, y, and assign in
to the address of x. When we dereference
y we should get the number assigned to x
which in this case is 7 */
*y++;  /* this situation appears to be ambiguous.
do we dereference the pointer to 7, and
then increment? Or do we increment first
and then derefence? In reality, because
the dereference operator does not have
precedence over suffix increments, the
pointer address itself is incremented -
leading to *y being pointed away from x
and into a completely different segment
of memory entirely! */
(*y)++;  /* this is the solution to the connundrum
presented by *y++. (*y) dereferences
first to the address of x, which is 7
ONLY THEN does it increment, to 8 */

To recap, our Precedence can take list form as follows:

1. Follow Inner Parentheses Outward
2. i++, i-- Suffix operators
3. *x, &x   Dereferences and Address operators
  also 3. ++i, --i Prefix operators
4. *, /, %  Simple math operations mult, div, percent
5. +, - Simple math operations add, subtract

No comments:

Post a Comment