Increment and Decrement Operators



  • C provides two unusual operators for incrementing and decrementing variables. The increment operator "++" adds 1 to its operand, while the decrement operator "--" subtracts 1.


  • ++ and -- may be used either as prefix operators (before the variable, as in ++n), or postfix operators (after the variable: n++). In both cases, the effect is to increment n.


  • But the expression ++n increments n before its value is used, while n++ increments "n" after its value has been used.


  • Example : x = n++; sets x to 5, but x = ++n; sets x to 6. In both cases, n becomes 6.


  • The increment and decrement operators can only be applied to variables; an expression like (i+j)++ is illegal.



Write a function squeeze(s,c), which removes all occurrences of the character "c" from the string "s" [Hint : Use Increment and Decrement Operators].


  • /* squeeze:  delete all c from s */
       void squeeze(char s[], int c)
       {
          int i, j;
          for (i = j = 0; s[i] != '\0'; i++)
              if (s[i] != c)
                  s[j++] = s[i];
          s[j] = '\0';
       }


Write a function strcat(s,t), which concatenates the string t to the end of string s [Hint : Use Increment and Decrement Operators].


  • /* strcat:  concatenate t to end of s; s must be big enough */
       void strcat(char s[], char t[])
       {
           int i, j;
           i = j = 0;
           while (s[i] != '\0') /* find end of s */
               i++;
           while ((s[i++] = t[j++]) != '\0') /* copy t */
               ;
       }




Bitwise Operators



  • C provides six operators for bit manipulation; these may only be applied to integral operands, that is, char, short, int, and long, whether signed or unsigned.


    1. & : bitwise AND


    2. | : bitwise inclusive OR


    3. ^ : bitwise exclusive OR


    4. << : left shift


    5. >> : right shift


    6. ~ : one's complement (unary)


  • The bitwise AND operator & is often used to mask off some set of bits, for example " n = n & 0177; " sets to zero all but the low-order 7 bits of n as 177 is 1111111.


  • The bitwise exclusive OR operator ^ sets a one in each bit position where its operands have different bits, and zero where they are the same.


  • One must distinguish the bitwise operators & and | from the logical operators && and ||, which imply left-to-right evaluation of a truth value. For example, if x is 1 and y is 2, then x & y is zero while x && y is one.


  • The shift operators >> and << perform right and left shifts of their left operand by the number of bit positions given by the right operand, which must be non-negative.


  • Thus x << 2 shifts the value of x by two positions, filling vacated bits with zero; this is equivalent to multiplication by 4. Right shifting an unsigned quantity always fits the vacated bits with zero.


  • The unary operator ~ yields the one's complement of an integer; that is, it converts each 1-bit into a 0-bit and vice versa. For example x = x & ~ 077 sets the last six bits of x to zero.



Q. Write a program with function : getbits(x,4,3) that returns the three bits in positions 4, 3 and 2, right-adjusted.


  • /* getbits:  get n bits from position p */
       unsigned getbits(unsigned x, int p, int n)
       {
           return (x >> (p+1-n)) & ~(~0 << n);
       }

  • The expression x >> (p+1-n) moves the desired field to the right end of the word. ~0 is all 1 bits; shifting it left n positions with ~0 << n places zeros in the rightmost "n" bits; complementing that with "~" makes a mask with ones in the rightmost "n" bits.




Assignment Operators and Expressions



  • An expression such as i = i + 2 in which the variable on the left side is repeated immediately on the right, can be written in the compressed form i += 2 . The operator += is called an assignment operator.


  • Most binary operators (operators like + that have a left and right operand) have a corresponding assignment operator op=, where op is one of + - * / % << >> & ^ | For example : x *= y + 1 is same as x = x * (y + 1) rather than x = x * y + 1




Q. Write a function bitcount that counts the number of 1-bits in its integer argument.


  • /* bitcount:  count 1 bits in x */
       int bitcount(unsigned x)
       {
           int b;
           for (b = 0; x != 0; x >>= 1)
               if (x & 01)
                   b++;
           return b;
       }



Conditional Expressions



  • The statements 
       if (a > b)
           z = a;
       else
           z = b;
    compute in z the maximum of a and b. 

  • he conditional expression, written with the ternary operator ``?:'', provides an alternate way to write this and similar constructions.


  • Syntax : expr1 ? expr2 : expr3


  • The expression expr1 is evaluated first. If it is non-zero (true), then the expression expr2 is evaluated, and that is the value of the conditional expression. Otherwise expr3 is evaluated, and that is the value. Only one of expr2 and expr3 is evaluated.


  • If expr2 and expr3are of different types, the type of the result is determined by the conversion rules discussed earlier in this chapter. For example, if f is a float and n an int, then the expression (n > 0) ? f : n is of type float regardless of whether n is positive.


  • Parentheses are not necessary around the first expression of a conditional expression, since the precedence of ?: is very low, just above assignment.




Q. Write a loop that prints "n" elements of an array, 10 per line, with each column separated by one blank, and with each line (including the last) terminated by a newline.


  • for (i = 0; i < n; i++)
           printf("%6d%c", a[i], (i%10==9 || i==n-1) ? '\n' : ' ');

  • A newline is printed after every tenth element, and after the n-th. All other elements are followed by one blank.




Additional Notes :



  • C, like most languages, does not specify the order in which the operands of an operator are evaluated. (The exceptions are &&, ||, ?:, and `,'.) For example, in a statement like x = f() + g();


  • f may be evaluated before g or vice versa; thus if either f or g alters a variable on which the other depends, x can depend on the order of evaluation.


  • Similarly, the order in which function arguments are evaluated is not specified, so the statement printf("%d %d\n", ++n, power(2, n)); can produce different results with different compilers, depending on whether "n" is incremented before power() is called.


  • Function calls, nested assignment statements, and increment and decrement operators cause ``side effects'' - some variable is changed as a by-product of the evaluation of an expression. For a[i] = i++; Compilers can interpret this in different ways, and generate different answers depending on their interpretation.