Tuesday, 1 October 2013

C Programming Operators

The Simple Assignment Operator

  • The equals sign, =, is known as the assignment operator in C
  • The purpose of the assignment operator is to take the value from the right hand side of the operator ( the RHS value ), and store it in the variable on the left hand side ( the LHS ).
  • Note the following examples:
    • X = Y + 7; - Valid: The sum of Y plus 7 will be stored in the variable X.
    • X - Y = 7; - Invalid: Although this looks like a simple rearrangement of the above, the LHS is no longer a valid storage location.
    • 7 = X - Y; - Invalid: The LHS is now a single entity, but it is a constant whose value cannot be changed.
    • X = X + 7; - Valid: First the original value of X will be added to 7. Then this new total will be stored back into X, replacing the previous value.

Arithmetic Operators, +, -, *, /, %

  • + is used for binary addition. Adds two operands and yields their sum.
    • Ex: X = Y + 7;
  • - is used for binary subtraction. Subtracts the second operand from the first and yields the difference.
    • Ex: X = Y - 7;
  • - may also be used for unary negation. Generates the negative of a single operand.
    • Ex: X = - Y;
    • ( + can also be used as a unary operator, but there is no good reason to do so. )
  • * is used for binary multiplication. Multiplies two operands and yields their product.
    • Ex: X = Y * 7;
  • / is used for binary division. Divides the first operand by the second and yields their quotient.
    • Ex: X = Y / 7;
    • WARNING: INTEGER DIVISION TRUNCATES
      • 9 / 10 yields zero, not 0.9 or 1.
      • 17 / 5 yields 3.
      • 9.0 / 10 yields 0.9, because there are two different types involved, and so the "smaller" int of 10 is promoted to a double precision 10.0 before the division takes place.
      • int num = 9.0 / 10; stores 0. The division yields 0.9 as in the above example, but then it is truncated to the integer 0 by the assignment operator that stores the result in the int variable "num".
  • % is used for modulus, which means the REMAINDER when one integer is divided by another.
    • Ex: K = N % 7;
    • 17 % 5 yields 2.
    • 3 % 5 yields 3.
    • Mod only works with integers in C.
    • If N % M is equal to zero, then it means N is evenly divisible by M. ( E.g. if N % 2 is 0, then N is even. )
    • N % M is always an integer in the range from 0 to M - 1 inclusive, regardless of N or M.
      • Therefore mod is often used to map a number into a given range.
      • For example, rand( ) % 52 always yields a number in the range 0 to 51 inclusive, suitable for randomly selecting a card from a deck of 52 cards.

Precedence and Associativity

  • Some operators have higher precedence than other operators, meaning that they are performed first. For example, multiplication and division have a higher precedence than addition or subtraction, so in a string of multiple operations, all the multiplications and divisions would be performed first, before any of the additions or subtractions.
    • Ex: what is the value of the expression 3 + 5 / 2 ?
    • Assignment statements have the lowest precedence of all, so all other operations are performed before the result is assigned.
  • Parentheses have the highest precedence, and can be used to override the natural precedence of other operators.
    • Ex: In the expression 3 * ( 4 + 2 ), the addition is performed first, and then the multiplication.
  • For operators of equal precedence, most operators are evaluated from left to right.
    • Ex: What is the value of the expression 5 / 3 * 2.0 ?
  • However there are a few that are evaluated from right to left.
    • Most notable is the assignment operator, so in the following statement, zero is first assigned to C by the rightmost assignment operator, and then the result of that operation ( zero ) is assigned to B by the middle operator, and then finally that result ( 0 ) is assigned to A by the leftmost assignment operator:
      • A = B = C = 0;
  • A full table of precedence and associativity is included in any good book on C Programming. There are also many versions of this information on the web.

Abbreviated Assignment Operators

  • A very common operation in computer programming is to change a variable in some way and store the new result back into the same variable.
    • E.g. X = X + 7;
  • Because this is so common, there are a number of operators that combine assignment with some other ( binary ) operator.
Operator Example Equivalent
X += 7;
X = X + 7
X -= 7;
X = X - 7;
X *= 7;
X = X * 7;
X /= 7;
X = X / 7;
X %= 7;
X = X % 7;
  • Note that in these combined operators, that there is no space between the = and the other character, e.g. no space between the + and the = in +=.
  • These operators are still assignment operators, and thus still have the lowest precedence. So in the following statement the addition will be performed first, and then the sum will be multiplied by X with the result stored in X:
    • X *= 3 + 4;
    • The above is equivalent to X = X * ( 3 + 4 );, not X = X * 3 + 4;

Auto Increment and Auto Decrement

  • Another operation that is very common in programming is to either increase or decrease an integer by exactly 1, e.g. when counting up or counting down.
  • The ++ operator is the auto-increment operator, which increases its argument by 1
    • N++; is equivalent to N += 1; which is equivalent to N = N + 1;
  • The -- operator is the auto-decrement operator, which decreases its argument by 1
    • N--; is equivalent to N -= 1; which is equivalent to N = N - 1;
  • Postfix versus Prefix
    • There are actually two versions of the auto increment/decrement operators, depending on whether the operator appears after the operand ( postfix, e.g. N++ ) or before the operand ( prefix, e.g. ++N ).
    • For stand-alone statement that consist of nothing but the auto increment/decrement there is no difference between the two. Common convention is to use the postfix form, but prefix would work equivalently.
    • Things get more interesting when the auto increment / decrement operators are used as part of a larger expression:
      • The postfix versions will use the original value of the variable to evaluate the expression, and then change the variable after the expression is evaluated.
        • If N is originally equal to 3, then the statement X = 2 * N++ * 3; will store 18 in X and then increment N to 4.
      • The prefix version will increment the variable first, and then use the new value of the variable to evaluate the expression.
        • If N is originally equal to 3, then the statement X = 2 * ++N * 3; will increment N to 4 first, and then store 24 in X.
  • DANGER: If a variable is affected by an auto increment / decrement operator, never use that same variable more than once in the same statement. For example, the result of X = N++ * 3 + N; is undefined, because it is undetermined what value will be used for the second instance of N.
  • Note that proper spacing can be very important when using auto increment and decrement operators.
    • ( Compare N++   +J to N+   ++J )