C Programming/Simple math

From Wikibooks, the open-content textbooks collection

Jump to: navigation, search
Previous: Simple Input and Output Index Next: Further math

Contents

[edit] Operators and Assignments

C has a wide range of operators that make simple math easy to handle. The list of operators grouped into precedence levels is as follows:

[edit] Primary expressions

An identifier is a primary expression, provided that it has been declared as designating an object (in which case it is an lvalue [a value that can be used as the left side of an assignment expression]) or a function (in which case it is a function designator).

A constant is a primary expression. Its type depends on its form and value.

A string literal is a primary expression.

A parenthesized expression is a primary expression. Its type and value are those of the unparenthesized expression.

[edit] Postfix operators

First, a primary expression is also a postfix expression. The following expressions are also postfix expressions:

A postfix expression followed by a left square bracket ([), an expression, and a right square bracket (]) constitutes an invocation of the array subscript operator. One of the expressions shall have type "pointer to object type" and the other shall have an integer type; the result type is type. Successive array subscript operators designate an element of a multidimensional array.

A postfix expression followed by an optional parenthesized argument list indicates an invocation of the function call operator.

A postfix expression followed by a dot (.) followed by an identifier selects a member from a structure or union; a postfix expression followed by an arrow (->) followed by an identifier selects a member from a structure or union who is pointed to by the pointer on the left-hand side of the expression.

[edit] Multiplicative and additive operators

In C, simple math is very easy to handle. The following operators exist: + (addition), - (subtraction), * (multiplication), / (division), and % (modulus); You likely know all of them from your math classes - except, perhaps, modulus. It returns the remainder of a division (e.g. 5 % 2 = 1).

Care must be taken with the modulus, because it's not the equivalent of the mathematical modulus: (-5) % 2 is not 1, but -1. Division of integers will return an integer, and the division of a negative integer by a positive integer will round towards zero instead of rounding down (e.g. (-5) / 3 = -1 instead of -2).

There is no inline operator to do the power (e.g. 5 ^ 2 is not 25, and 5 ** 2 is an error), but there is a power function.

The mathematical order of operations does apply. For example (2 + 3) * 2 = 10 while 2 + 3 * 2 = 8. The order of precedence in C is BFDMAS: Brackets (or parentheses), Functions, Division or Multiplication (from left to right, whichever comes first), Addition or Subtraction (also from left to right, whichever comes first).

Actually, there are more operators than the above in C.

Assignment in C is simple. You declare the type of variable, the name of the variable and what it's equal to. For example, int x = 0; double y = 0.0; char z = 'a';

#include <stdio.h>
 
int main()
{
    int i = 0, j = 0;
 
    /* while i is less than 5 AND j is less than 5, loop */
    while( (i < 5) && (j < 5) )
    {
        /* postfix increment, i++
         *     the value of i is read and then incremented
         */
        printf("i: %d\t", i++);
 
        /*
         * prefix increment, ++j 
         *     the value of j is incremented and then read
         */
        printf("j: %d\n", ++j);
    }
 
    printf("At the end they have both equal values:\ni: %d\tj: %d\n", i, j);
 
    return 0;
}

will display the following:

i: 0    j: 1
i: 1    j: 2
i: 2    j: 3
i: 3    j: 4
i: 4    j: 5
At the end they have both equal values:
i: 5    j: 5

[edit] shift and rotate

Shift functions are often used in low-level I/O hardware interfacing. Shift and rotate functions are heavily used in cryptography and software floating point emulation. Other than that, shifts can be used in place of division or multiplication by a power of two. Many processors have dedicated function blocks to make these operations fast -- see Microprocessor Design/Shift and Rotate Blocks. On processors which have such blocks, most C compilers compile shift and rotate operators to a single assembly-language instruction -- see X86 Assembly/Shift and Rotate.

[edit] shift left

The << operator shifts the binary representation to the left, dropping the most significant bits and appending it with zero bits. The result is equivalent to multiplying the integer by a power of two.

[edit] unsigned shift right

The unsigned shift right operator, also sometimes called the logical right shift operator. It shift the binary representation to the right, dropping the least significant bits and prepending it with zeros. The >> operator is equivalent to division by a power of two for unsigned integers.

[edit] signed shift right

The signed shift right operator, also sometimes called the arithmetic right shift operator. It shifts the binary representation to the right, dropping the least significant bit, but prepending it with copies of the original sign bit. The >> operator is not equivalent to division for signed integers.

In C, the behavior of the >> operator depends on the data type it acts on. Therefore, a signed and an unsigned right shift looks exactly the same, but produces a different result in some cases.

[edit] rotate right

Contrary to popular belief, it is possible to write C code that compiles down to the "rotate" assembly language instruction (on CPUs that have such an instruction).

Most compilers recognize this idiom:

  unsigned int x;
  unsigned int y;
  /* ... */
  y = (x >> shift) | (x << (32 - shift));

and compile it to a single 32 bit rotate instruction. [1] [2]

On some systems, this may be "#define"ed as a macro or defined as an inline function called something like "rightrotate32" or "rotr32" or "ror32" in a standard header file like "bitops.h". [3]

[edit] rotate left

Most compilers recognize this idiom:

  unsigned int x;
  unsigned int y;
  /* ... */
  y = (x << shift) | (x >> (32 - shift));

and compile it to a single 32 bit rotate instruction.

On some systems, this may be "#define"ed as a macro or defined as an inline function called something like "leftrotate32" or "rotl32" in a standard header file like "bitops.h".

  1. GCC: "Optimize common rotate constructs"
  2. "Cleanups in ROTL/ROTR DAG combiner code" mentions that this code supports the "rotate" instruction in the CellSPU
  3. "replace private copy of bit rotation routines" -- recommends includeing "bitops.h" and using its rol32 and ror32 rather than copy-and-paste into a new program.
Previous: Simple Input and Output Index Next: Further math
In other languages