C Programming/Operators and type casting

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:

Primary expressions
Identifiers are names of things in C, and consist of either a letter or an underscore ( _ ) optionally followed by letters, digits, or underscores. An identifier (or variable name) 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. The types of constants are character constants (e.g.  is a space), integer constants (e.g.  ), floating-point constants (e.g.  ), and enumerated constants that have been previously defined via.

A string literal is a primary expression. It consists of a string of characters within double quotes ( " ).

A parenthesized expression is a primary expression. It consists of an expression within parentheses ( ( ) ). Its type and value are those of the non-parenthesized expression within the parentheses.

In C11, an expression that starts with _Generic followed by an initial expression, a list of values of the form type: expression where type is either a named type or the keyword default, and constitutes a primary expression. The value is the expression that follows the type of the initial expression or the default if not found.

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 in sequence 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 parentheses or an optional parenthesized argument list indicates an invocation of the function call operator. The value of the function call operator is the return value of the function called with the provided arguments. The parameters to the function are copied on the stack by value (or at least the compiler acts as if that is what happens; if the programmer wanted the parameter to be copied by reference, then it is easier to pass the address of the area to be modified by value, then the called function can access the area through the respective pointer). The trend for compilers is to pass the parameters from right to left onto the stack, but this is not universal.

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.

A postfix expression followed by the increment or decrement operators ( or   respectively) indicates that the variable is to be incremented or decremented as a side effect. The value of the expression is the value of the postfix expression before the increment or decrement. These operators only work on integers and pointers.

Unary expressions
First, a postfix expression is a unary expression. The following expressions are all unary expressions:

The increment or decrement operators followed by a unary expression is a unary expression. The value of the expression is the value of the unary expression after the increment or decrement. These operators only work on integers and pointers.

The following operators followed by a cast expression are unary expressions:

Operator    Meaning ========    =======    &         Address-of; value is the location of the operand *        Contents-of; value is what is stored at the location -        Negation +        Value-of operator !        Logical negation ( (!E) is equivalent to (0==E) ) ~        Bit-wise complement

The keyword  followed by a unary expression is a unary expression. The value is the size of the type of the expression in bytes. The expression is not evaluated.

The keyword  followed by a parenthesized type name is a unary expression. The value is the size of the type in bytes.

Cast operators
A unary expression is also a cast expression.

A parenthesized type name followed by any expression, including literals, is a cast expression. The parenthesized type name has the effect of forcing the cast expression into the type specified by the type name in parentheses. For arithmetic types, this either does not change the value of the expression, or truncates the value of the expression if the expression is an integer and the new type is smaller than the previous type.

An example of casting an int as a float:

Multiplicative and additive operators
First, a multiplicative expression is also a cast expression, and an additive expression is also a multiplicative expression. This follows the precedence that multiplication happens before addition.

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). (Modulus is not defined for floating-point numbers, but the math.h library has an fmod function.)

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). However, it is always true that for all integer a and nonzero integer b, ((a / b) * b) + (a % b) == a.

There is no inline operator to do exponentiation (e.g. 5 ^ 2 is not 25 [it is 7; ^ is the exclusive-or operator], 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. Multiplicative operators have precedence over additive operators.

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

The shift operators (which may be used to rotate bits)
A shift expression is also an additive expression (meaning that the shift operators have a precedence just below addition and subtraction).

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.

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.

unsigned shift right
The unsigned shift right operator, also sometimes called the logical right shift operator. It shifts 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.

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.

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:

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 "rightrotate32" or "rotr32" or "ror32" in a standard header file like "bitops.h".

rotate left
Most compilers recognize this idiom:

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 header file like "bitops.h".

Relational and equality operators
A relational expression is also a shift expression; an equality expression is also a relational expression.

The relational binary operators  (less than),   (greater than),   (less than or equal), and   (greater than or equal) operators return a value of 1 if the result of the operation is true, 0 if false. The result of these operators is type.

The equality binary operators  (equals) and   (not equals) operators are similar to the relational operators except that their precedence is lower. They also return a value of 1 if the result of the operation is true and 0 if it is false.

One thing with floating-point numbers and equality operators: Because floating-point operations can produce approximations (e.g. 0.1 is a repeating decimal in binary, so 0.1 * 10.0 is hardly ever 1.0), it is unwise to use the  operator with floating-point numbers. Instead, if a and b are the numbers to compare, compare  to a fudge factor.

Bitwise operators
The bitwise operators are  (and),   (exclusive or) and   (inclusive or). The  operator has higher precedence than , which has higher precedence than.

The values being operated upon must be integral; the result is integral.

One use for the bitwise operators is to emulate bit flags. These flags can be set with OR, tested with AND, flipped with XOR, and cleared with AND NOT. For example:

Logical operators
The logical operators are  (and), and   (or). Both of these operators produce 1 if the relationship is true and 0 for false. Both of these operators short-circuit; if the result of the expression can be determined from the first operand, the second is ignored. The  operator has higher precedence than the   operator.

is used to evaluate expressions left to right, and returns a 1 if both statements are true, 0 if either of them are false. If the first expression is false, the second is not evaluated. Here, the  operator checks the left-most expression, then the expression to its right. If there were more than two expressions chained (e.g. ), the operator would check x first, then y (if x is nonzero), then continue rightwards to z if neither x or y is zero. Since both statements return true, the  operator returns true, and the code block is executed.

The && operator checks in the same way as before, and finds that the first expression is false. The && operator stops evaluating as soon as it finds a statement to be false, and returns a false.

is used to evaluate expressions left to right, and returns a 1 if either of the expressions are true, 0 if both are false. If the first expression is true, the second expression is not evaluated. The  operator here checks the left-most expression, finds it false, but continues to evaluate the next expression. It finds that the next expression returns true, stops, and returns a 1. Much how the  operator ceases when it finds an expression that returns false, the   operator ceases when it finds an expression that returns true.

It is worth noting that C does not have Boolean values (true and false) commonly found in other languages. It instead interprets a 0 as false, and any nonzero value as true.

Conditional operators
The ternary  operator is the conditional operator. The expression  has the value of   if   is nonzero,   otherwise.

Example: The expression  evaluates to 0. The ternary operator then looks for the "if-false" value, which in this case, is 6. It returns that, so  is equal to six. Had  been a non-zero, then the expression would have returned a 10.

Assignment operators
The assignment operators are,  ,  ,  ,  ,  ,  ,  ,  ,  , and. The  operator stores the value of the right operand into the location determined by the left operand, which must be an lvalue (a value that has an address, and therefore can be assigned to).

For the others,  is shorthand for. Hence, the following expressions are the same: 1. x += y    -     x = x+y 2. x -= y    -     x = x-y 3. x *= y    -     x = x*y 4. x /= y    -     x = x/y 5. x %= y    -     x = x%y

The value of the assignment expression is the value of the left operand after the assignment. Thus, assignments can be chained; e.g. the expression  would assign the value zero to all three variables.

Comma operator
The operator with the least precedence is the comma operator. The value of the expression  will evaluate both   and , but provides the value of.

This operator is useful for including multiple actions in one statement (e.g. within a for loop conditional).

Here is a small example of the comma operator: