NEW C PRIMER PLUS SECOND EDITION
CHAPTER 5 NOTES
Copyright (C) 1993 by The Waite Group
Copyright (C) 1997 by Linda Buck


 1. Fundamental Operators
    ---------------------
    Table of Operators
    ------------------
    Assignment Operator:
       =   Assigns the value at its right to the variable at its left.
           Note that C allows multiple assignment.
    Arithmetic Operators:
       +   Adds the value at its right to the value at its left.
       -   Subtracts the value at its right from the value at its left.
       -   As a unary operator, changes the sign of the value at its
           right.
       *   Multiplies the value at its left by the value at its right.
       /   Divides the value at its left by the value at its right.
           Answer is truncated if both operands are integers.  Note that
           dividing by zero gives a run-time error.
       %   Yields the remainder when the value at its left is divided by
           the value at its right (integers only).

    Note:
    C does not have an exponent operator.

 2. Example 5.1
    -----------
    Program:
    /* assign1.c -- increments a variable */
    #include <stdio.h>
    int main(void)
    {
      int i = 3;

      printf("i = %d\n", i);
      i = i + 1;
      printf("i = %d\n", i);
      return 0;
    }

    Output:
    i = 3
    i = 4

 3. Example 5.2
    -----------
    Problem:
    Switch the contents of two variables.

    Program #1:
    /* assign2.c -- tries to swap two variables */
    #include <stdio.h>
    int main(void)
    {
      int a = 3, b = 5;

      printf("a = %d, b = %d\n", a, b);
      a = b;
      b = a;
      printf("a = %d, b = %d\n", a, b);
      return 0;
    }

    Output #1:
    a = 3, b = 5
    a = 5, b = 5

    Program #2:
    /* assign3.c -- swaps two variables */
    #include <stdio.h>
    int main(void)
    {
      int a = 3, b = 5;
      int temp;

      printf("a = %d, b = %d\n", a, b);
      temp = a;
      a = b;
      b = temp;
      printf("a = %d, b = %d\n", a, b);
      return 0;
    }

    Output #2:
    a = 3, b = 5
    a = 5, b = 3

 4. Example 5.3
    -----------
    Program:
    /* assign4.c -- multiple assignment */
    #include <stdio.h>
    int main(void)
    {
      int a, b;

      /* C allows multiple assignment */
      a = b = 0;
      printf("a = %d, b = %d\n", a, b);
      return 0;
    }

    Output:
    a = 0, b = 0
 
 5. Example 5.4
    -----------
    Program:
    /* arith1.c -- arithmetic operators */
    #include <stdio.h>
    int main(void)
    {
      printf("7+4 = %d\n", 7+4);
      printf("7-4 = %d\n", 7-4);
      printf("7*4 = %d\n", 7*4);

      /* /: answer is truncated if both operands are integers */
      printf("7/4 = %d\n", 7/4);
      printf("7.0/4.0 = %.2lf\n", 7.0/4.0);

      /* %: remainder when integer at left is divided by integer at
            right */
      printf("7%%4 = %d\n", 7%4);
      return 0;
    }

    Output:
    7+4 = 11
    7-4 = 3
    7*4 = 28
    7/4 = 1
    7.0/4.0 = 1.75
    7%4 = 3

 6. Example 5.5
    -----------
    Program:
    /* arith2.c -- arithmetic operators */
    #include <stdio.h>
    int main(void)
    {
      double a = 3.5, b = 0.0;

      /*** error ***/
      /* dividing by zero gives a run-time error */
      printf("a/b = %.2lf\n", a/b);
      return 0;
    }

    Output:
    run-time error M6103: MATH
    - floating-point error: divide by 0

 7. Precedence and the Order of Evaluation
    --------------------------------------
    Table of Operators in Order of Decreasing Precedence
    ----------------------------------------------------
        Operator             Associativity
    (1) ()                   left to right
    (2) +(unary) -(unary)    right to left
    (3) * / %                left to right
    (4) +(binary) -(binary)  left to right
    (5) =                    right to left

    Note:
    (1) If two operators share an operand, precedence and associativity
        rules tell us the order of evaluation.
        (a) Evaluate the higher precedence operator first.
        (b) If the two operators have the same precedence, use the
            associativity rule.
    (2) If two operators do not share an operand, the order is left up
        to the compiler.  This allows the compiler to optimize code.

 8. Example 5.6
    -----------
    Program:
    /* prec1.c -- precedence */
    #include <stdio.h>
    int main(void)
    {
      double ans1, ans2;

      /* if two operators share an operand, precedence and associativity
         rules tell us the order of evaluation:
         (1) evaluate the higher precedence operator first
         (2) if the two operators have the same precedence, use the
             associativity rule */
      ans1 = 25.0 + 60.0 * 6.0 / 2.0;
      ans2 = (25.0 + 60.0 * 6.) / 2.0;
      printf("ans1 = %.2lf, ans2 = %.2lf\n", ans1, ans2);
      return 0;
    }

    Trace:
    1) ans1 = 25.0 + 60.0 * 6.0 / 2.0
            = 25.0 + 360.0 / 2.0
            = 25.0 + 180.0
            = 205.0
    2) ans2 = (25.0 + 60.0 * 6.0) / 2.0
            = (25.0 + 360.0) / 2.0
            = 385.0 / 2.0
            = 192.5

    Output:
    ans1 = 205.00, ans2 = 192.50

 9. Example 5.7
    -----------
    Program:
    /* prec2.c -- precedence */
    #include <stdio.h>
    int main(void)
    {
      int ans;

      /* if two operators do not share an operand, the order is left up
         to the compiler */
      ans = 6 * 12 + 5 * 20;
      printf("ans = %d\n", ans);
      return 0;
    }

    Trace:
    1) Doing leftmost multiplication first:
       ans = 6 * 12 + 5 * 20
           = 72 + 5 * 20
           = 72 + 100
           = 172
    2) Doing rightmost multiplication first:
       ans = 6 * 12 + 5 * 20
           = 6 * 12 + 100
           = 72 + 100
           = 172

    Output:
    ans = 172

10. Type Conversions
    ----------------
    (1) Ranking of types from highest to lowest:
        long double
        double
        float
        unsigned long
        long
        unsigned int
        int
        char, short
    (2) In any operation involving two types, the lower ranking value
        is converted to the higher ranking type.
    (3) In an assignment statement, the final result of the calculations
        is converted to the type of variable that is being assigned a
        value.

    Note:
    Converting to a lower ranking type can lead to trouble because the
    lower ranking type may not be large enough to hold the result.

11. Example 5.8
    -----------
    Program #1:
    /* type1.c -- type conversions */
    #include <stdio.h>
    int main(void)
    {
      /* in any operation involving two types, the lower ranking value
         is converted to the higher ranking type */
      printf("24/5/3 = %d\n", 24/5/3);
      printf("24/5/3. = %.2lf\n", 24/5/3.);
      printf("24/5./3 = %.2lf\n", 24/5./3);
      return 0;
    }

    Trace #1:
    1) 24/5/3 = 4/3 = 1
    2) 24/5/3. = 4/3. = 4./3. = 1.333333
    3) 24/5./3 = 24./5./3 = 4.8/3 = 4.8/3. = 1.6

    Output #1:
    24/5/3 = 1
    24/5/3. = 1.33
    24/5./3 = 1.60

    Program #2:
    /* type2.c -- type conversions */
    #include <stdio.h>
    int main(void)
    {
      int ans1;
      double ans2;

     /* in an assignment statement, the final result of the calculations
        is converted to the type of variable that is being assigned a
        value */
      ans1 = 2.6;
      printf("ans1 = %d\n", ans1);
      ans2 = 24/5;
      printf("ans2 = %.2lf\n", ans2);
      return 0;
    }

    Trace #2:
    1) ans1 = 2.6 = 2
    3) ans2 = 24/5 = 4 = 4.0

    Output #2:
    ans1 = 2
    ans2 = 4.00

12. Miscellaneous Operators
    -----------------------
    Table of Operators
    ------------------
    Miscellaneous Operators:
    sizeof(type) or sizeof(variable): Yields the size, in bytes, of the
           operand to its right.
    (type) Cast operator: converts the following value to the type
           specified by the enclosed keyword(s).

    Table of Operators in Order of Decreasing Precedence
    ----------------------------------------------------
        Operator                                    Associativity
    (1) ()                                          left to right
    (2) +(unary) -(unary) sizeof (type)(all unary)  right to left
    (3) * / %                                       left to right
    (4) +(binary) -(binary)                         left to right
    (5) =                                           right to left

13. Example 5.9
    -----------
    Program:
    /* sizeof.c -- sizeof operator */
    #include <stdio.h>
    int main(void)
    {
      int i_num;
      double d_num;
      char str[11];

      /* sizeof: yields the size, in bytes, of the following operand */
      printf("sizeof(int) = %d, sizeof(i_num) = %d\n", sizeof(int),
        sizeof(i_num));
      printf("sizeof(double) = %d, sizeof(d_num) = %d\n",
        sizeof(double), sizeof(d_num));
      printf("sizeof(str) = %d\n", sizeof(str));
      return 0;
    }

    Output:
    sizeof(int) = 2, sizeof(i_num) = 2
    sizeof(double) = 8, sizeof(d_num) = 8
    sizeof(str) = 11

14. Example 5.10
    ------------
    Program:
    /* cast.c -- type cast operator */
    #include <stdio.h>
    int main(void)
    {
      int a = 3, b = 5;
      double ans1, ans2;

      /* (type): converts the following value to the given type */
      ans1 = a/b;
      ans2 = (double)a/(double)b;
      printf("ans1 = %.2lf, ans2 = %.2lf\n", ans1, ans2);
      return 0;
    }

    Trace:
    1) ans1 = a/b = 3/5 = 0 = 0.0
    2) ans2 = (double)a/(double)b = (double)3/(double)5 = 3./5. = 0.6

    Output:
    ans1 = 0.00, ans2 = 0.60

15. Increment/Decrement Operators
    -----------------------------
    Table of Operators
    ------------------
    Increment/Decrement Operators:
      ++   Adds 1 to the value of the variable to its right (prefix
           mode) or adds 1 to the value of the variable to its left
           (postfix mode).
           (1) When ++a is part of an expression:
               step 1: increment a
               step 2: use the new value of a
           (2) When a++ is part of an expression:
               step 1: use the current value of a
               step 2: increment a
      --   Subtracts 1 from the value of the variable to its right
           (prefix mode) or subtracts 1 from the value of the variable
           to its left (postfix mode).
           (1) When --a is part of an expression:
               step 1: decrement a
               step 2: use the new value of a
           (2) When a-- is part of an expression:
               step 1: use the current value of a
               step 2: decrement a

    Table of Operators in Order of Decreasing Precedence
    ----------------------------------------------------
        Operator                                 Associativity
    (1) ++(postfix) --(postfix) ()               left to right
    (2) ++(prefix) --(prefix) +(unary) -(unary)  right to left
        sizeof (type)(all unary)
    (3) * / %                                    left to right
    (4) +(binary) -(binary)                      left to right
    (5) =                                        right to left

    Increment and Decrement Operator Problems
    -----------------------------------------
    (1) Don't use increment or decrement operators on a variable that is
        part of more than one argument of a function.  This can cause
        problems because the direction of argument evaluation is left up
        to the compiler.
        Note:  Most systems evaluate arguments right-to-left.
    (2) Don't use increment or decrement operators on a variable that
        appears more than once in an expression.  This can cause
        problems because:
        (a) Prefix
            The compiler can increment/decrement the variable at any
            point in an expression before it uses the new value.
        (b) Postfix
            The compiler can increment/decrement the variable at any
            point in an expression after it uses the current value.

16. Example 5.11
    ------------
    Program #1:
    /* inc_dec1.c -- increment and decrement operators */
    #include <stdio.h>
    int main(void)
    {
      int n;

      n = 3;
      ++n;  /* n = n+1; */
      printf("n = %d\n", n);

      n = 3;
      n++;  /* n = n+1; */
      printf("n = %d\n", n);

      n = 3;
      --n;  /* n = n-1; */
      printf("n = %d\n", n);

      n = 3;
      n--;  /* n = n-1; */
      printf("n = %d\n", n);
      return 0;
    }

    Output #1:
    n = 4
    n = 4
    n = 2
    n = 2

    Program #2:
    /* inc_dec2.c -- increment and decrement operators */
    #include <stdio.h>
    int main(void)
    {
      int n, ans;

      n = 3;
      ans = ++n;  /* n = n+1; ans = n; */
      printf("n = %d, ans = %d\n", n, ans);

      n = 3;
      ans = n++;  /* ans = n; n = n+1; */
      printf("n = %d, ans = %d\n", n, ans);
      return 0;
    }

    Output #2:
    n = 4, ans = 4
    n = 4, ans = 3

    Program #3:
    /* inc_dec3.c -- increment and decrement operators */
    #include <stdio.h>
    int main(void)
    {
      int n, ans;

      n = 3;
      ans = 2*++n;  /* n = n+1; ans = 2*n; */
      printf("n = %d, ans = %d\n", n, ans);

      n = 3;
      ans = 2*n++;  /* ans = 2*n; n = n+1; */
      printf("n = %d, ans = %d\n", n, ans);
      return 0;
    }

    Output #3:
    n = 4, ans = 8
    n = 4, ans = 6

17. Example 5.12
    ------------
    Program #1:
    /* inc_dec4.c -- increment/decrement operator problems */
    #include <stdio.h>
    int main(void)
    {
      int n = 3;

      /*** problem ***/
      /* don't use increment or decrement operators on a variable that
         is part of more than one argument of a function -- this can
         cause problems because the direction of argument evaluation is
         left up to the compiler */
      printf("n = %d, n+1 = %d\n", n, ++n);
      return 0;
    }

    Trace #1:
    1) Evaluating argument list left to right:
       n = 3
       ++n, n = n+1 = 3+1 = 4
       Output:
       n = 3, n+1 = 4
    2) Evaluating argument list right to left (most systems):
       ++n, n = n+1 = 3+1 = 4
       n = 4
       Output:
       n = 4, n+1 = 4

    Program #2:
    /* inc_dec5.c -- increment/decrement operator problems */
    #include <stdio.h>
    int main(void)
    {
      int n = 3, ans;

      /*** problem ***/
      /* don't use increment or decrement operators on a variable that
         appears more than once in an expression -- this can cause
         problems because:
         (1) prefix
             the compiler can increment/decrement the variable at any
             point in an expression before it uses the new value
         (2) postfix
             the compiler can increment/decrement the variable at any
             point in an expression after it uses the current value */
      ans = n + n++;
      printf("n = %d, ans = %d\n", n, ans);
      return 0;
    }

    Trace #2:
    1) Possibility #1:
       ans = n+n++
       ans = n+n, n = n+1
       ans = 3+3 = 6
       n = 3+1 = 4
       Output:
       n = 4, ans = 6
    2) Possiblity #2:
       ans = n+n++
       cur = n, n = n+1, ans = n+cur
       cur = n = 3
       n = n+1 = 3+1 = 4
       ans = n+cur = 4+3 = 7
       Output:
       n = 4, ans = 7

18. Assignment Operators
    --------------------
    Table of Operators
    ------------------
    Assignment Operators:
    Operator   Meaning
       +=      Adds the righthand quantity to the lefthand variable and
               stores the result in the lefthand variable.
       -=      Subtracts the righthand quantity from the lefthand
               variable and stores the result in the lefthand variable.
       *=      Multiplies the lefthand variable by the righthand
               quantity and stores the result in the lefthand variable.
       /=      Divides the lefthand variable by the righthand quantity
               and stores the result in the lefthand variable.
       %=      Gives the remainder from dividing the lefthand variable
               by the righthand quantity and stores the result in the
               lefthand variable.

    General Form:
        variable operator= expression

    General Meaning:
        variable = variable operator (expression)
            where variable is computed only once.
    
    Table of Operators in Order of Decreasing Precedence
    ----------------------------------------------------
        Operator                                 Associativity
    (1) ++(postfix) --(postfix) ()               left to right
    (2) ++(prefix) --(prefix) +(unary) -(unary)  right to left
        sizeof (type)(all unary)
    (3) * / %                                    left to right
    (4) +(binary) -(binary)                      left to right
    (5) = *= /= %= += -=                         right to left

19. Example 5.13
    ------------
    Program:
    /* assign5.c -- assignment operators */
    #include <stdio.h>
    int main(void)
    {
      int n, ans;

      n = 3;
      ans = 7;
      ans += n;  /* ans = ans + (n); */
      printf("n = %d, ans = %d\n", n, ans);

      n = 3;
      ans = 7;
      ans -= n;  /* ans = ans - (n); */
      printf("n = %d, ans = %d\n", n, ans);

      n = 3;
      ans = 7;
      ans *= n;  /* ans = ans * (n); */
      printf("n = %d, ans = %d\n", n, ans);

      n = 3;
      ans = 7;
      ans /= n;  /* ans = ans / (n); */
      printf("n = %d, ans = %d\n", n, ans);

      n = 3;
      ans = 7;
      ans %= n;  /* ans = ans % (n); */
      printf("n = %d, ans = %d\n", n, ans);

      n = 3;
      ans = 7;
      ans *= n + 1; /* ans = ans * (n+1); */
      printf("n = %d, ans = %d\n", n, ans);
      return 0;
    }

    Output:
    n = 3, ans = 10
    n = 3, ans = 4
    n = 3, ans = 21
    n = 3, ans = 2
    n = 3, ans = 1
    n = 3, ans = 28

20. Expressions and Statements
    --------------------------
    (1) An expression is a combination of operators and operands.
    (2) Every C expression has a value.
    (3) C allows you to embed an assignment in an expression.
        The value of the assignment is the value of its right-hand
        expression.
    (4) A statement is a command to the computer.
    (5) Simple statements terminate in a semicolon.
    (6) Compound statements consist of one or more statements enclosed
        in braces.

    Embedded Assignment Problems:
    (1) Don't use embedded assignment on a variable that is part of more
        than one argument of a function.  This can cause problems
        because the direction of argument evaluation is left up to the
        compiler.
    (2) Don't use embedded assignment on a variable that appears more
        than once in an expression.  This can cause problems when the
        order of expression evaluation is left up to the compiler.

21. Example 5.14
    ------------
    Program:
    /* embed.c -- embedded assignment */
    #include <stdio.h>
    int main(void)
    {
      int ans1, ans2;

      /* C allows you to embed an assignment in an expression -- the
         value of the assignment is the value of its right-hand
         expression */
      ans2 = 3 + (ans1 = 5+7);
      printf("ans1 = %d, ans2 = %d\n", ans1, ans2);
      return 0;
    }

    Output:
    ans1 = 12, ans2 = 15

22. Relational Operators
    --------------------
    Table of Operators
    ------------------
    Relational Operators:
    Operator   Meaning
       <       is less than
       <=      is less than or equal to
       ==      is equal to
       >=      is greater than or equal to
       >       is greater than
       !=      is not equal to
     
    True and False:
    (1) In C, a true expression has the value 1; a false expression has
        the value 0.
    (2) All nonzero values are regarded as true, and only 0 is
        recognized as false.

    Note:
    (1) Be sure to use = for assignment and == for equality.  Some care
        is needed, for a compiler will let you use the wrong form in
        many cases, yielding results other than what you expect.
    (2) Relational operators can be used with characters.  The machine
        code (which we have been assuming is ASCII) is used for the
        comparison.  However, you can't use relational operators to
        compare strings.
    (3) Relational operators can be used with floating-point numbers.
        However, you should limit yourself to using only < and > in
        floating-point comparisons because roundoff errors can prevent
        two numbers from being equal even though logically they should
        be.
       
    Table of Operators in Order of Decreasing Precedence
    ----------------------------------------------------
        Operator                                 Associativity
    (1) ++(postfix) --(postfix) ()               left to right
    (2) ++(prefix) --(prefix) +(unary) -(unary)  right to left
        sizeof (type)(all unary)
    (3) * / %                                    left to right
    (4) +(binary) -(binary)                      left to right
    (5) < > <= >=                                left to right
    (6) == !=                                    left to right
    (7) = *= /= %= += -=                         right to left

23. Example 5.15
    ------------
    Program:
    /* relat1.c -- relational operators */
    #include <stdio.h>
    int main(void)
    {
      /* a true expression has the value 1; a false expression has
         the value 0 */
      printf("10>2 is %d\n", 10>2);
      printf("10<2 is %d\n", 10<2);
      return 0;
    }

    Output:
    10>2 is 1
    10<2 is 0

24. Example 5.16
    ------------
    Program:
    /* relat2.c -- relational operators */
    #include <stdio.h>
    int main(void)
    {
      int a = 3, b = 5;

      /*** error ***/
      /* uses equality instead of assignment */
      a == b;
      printf("a = %d, b = %d\n", a, b);
      return 0;
    }

    Trace:
    (a==b) = (3==5) = 0 (false)

    Output:
    a = 3, b = 5

25. Example 5.17
    ------------
    Program #1:
    /* relat3.c -- relational operators */
    #include <stdio.h>
    int main(void)
    {
      char ch = 'D';

      /* relational operators can be used with characters -- the
         machine code (which we have been assuming is ASCII) is used for
         the comparison */
      printf("ch>='A' is %d\n", ch>='A');
      printf("ch<='Z' is %d\n", ch<='Z');
      printf("ch>='a' is %d\n", ch>='a');
      printf("ch<='z' is %d\n", ch<='z');
      return 0;
    }
 
    Trace #1:
    1) ch>='A' is 'D'>='A' is 68>=65 is 1
    2) ch<='Z' is 'D'<='Z' is 68<=90 is 1
    3) ch>='a' is 'D'>='a' is 68>=97 is 0
    4) ch<='z' is 'D'<='a' is 68<=122 is 1

    Output #1:
    ch>='A' is 1
    ch<='Z' is 1
    ch>='a' is 0
    ch<='z' is 1

    Program #2:
    /* relat4.c -- relational operators */
    #include <stdio.h>
    int main(void)
    {
      char str1[4] = "abc";
      char str2[4] = "abc";

      /*** error ***/
      /* you can't use relational operators to compare strings */
      printf("str1==str2 is %d\n", str1==str2);
      return 0;
    }

    Output #2:
    str1==str2 is 0

    Program #3:
    /* relat5.c -- relational operators */
    #include <stdio.h>
    int main(void)
    {
      double sum;

     /*** problem ***/
     /* relational operators can be used with floating-point
        numbers -- you should limit yourself to using only < and
        > in floating-point comparisons because roundoff errors can
        prevent two numbers from being equal even though logically they
        should be */
      sum = 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1;
      printf("sum==1.0 is %d\n", sum==1.0);
      return 0;
    }

    Output #3:
    sum==1.0 is 0
    
26. Example 5.18
    ------------
    Program:
    /* relat6.c -- relational operators */
    #include <stdio.h>
    int main(void)
    {
      int ans;

      /* arithmetic operators have higher precedence than relational
         operators */
      printf("2+8>2*4 is %d\n", 2+8>2*4);

      /* be careful -- doesn't do what you think */
      /* relational operators associate left-to-right */
      printf("7>5>3 is %d\n", 7>5>3);

      /* relational operators have higher precedence than assignment
         operators */
      printf("ans=5!=6 is %d\n", ans=5!=6);
      printf("ans = %d\n", ans);
      printf("(ans=5)!=6 is %d\n", (ans=5)!=6);
      printf("ans = %d\n", ans);
      return 0;
    }

    Trace:
    1) 2+8>2*4 is 10>8 is 1
    2) 7>5>3 is 1>3 is 0
    3) ans=5!=6
       5!=6 is 1, ans = 1
    4) (ans=5)!=6
       ans = 5, 5!=6 is 1
    
    Output:
    2+8>2*4 is 1
    7>5>3 is 0
    ans=5!=6 is 1
    ans = 1
    (ans=5)!=6 is 1
    ans = 5

27. Logical Operators
    -----------------
    Table of Operators
    ------------------
    Logical Operators:
    (1) AND (&&)
        exp1   exp2   exp1 && exp2
        -----  -----  ------------
        false  false     false
        false  true      false
        true   false     false
        true   true      true
    (2) OR (||)
        exp1   exp2   exp1 || exp2
        -----  -----  ------------
        false  false     false
        false  true      true
        true   false     true
        true   true      true
    (3) NOT (!)
         exp   !exp
        -----  -----
        false  true
        true   false

    Table of Operators in Order of Decreasing Precedence
    ------------------------------------------------------
        Operator                                   Associativity
    (1) ++(postfix) --(postfix) ()                 left to right
    (2) ++(prefix) --(prefix) +(unary) -(unary) !  right to left
        sizeof (type)(all unary)
    (3) * / %                                      left to right
    (4) +(binary) -(binary)                        left to right
    (5) < > <= >=                                  left to right
    (6) == !=                                      left to right
    (7) &&                                         left to right
    (8) ||                                         left to right
    (9) = *= /= %= += -=                           right to left

    Operators                                Associativity
    ()                                       left to right
    +(unary) -(unary) ! ++ -- sizeof (type)  right to left
    * / %                                    left to right
    + -                                      left to right
    < > <= >=                                left to right
    == !=                                    left to right
    &&                                       left to right
    ||                                       left to right
    = *= /= %= += -=                         right to left
    ,                                        left to right

    Order of Evaluation:
    (1) Logical expressions are evaluated from left to right whether
        they share an operand or not.
    (2) Evaluation stops as soon as something is discovered that
        renders the expression true or false.
    (3) With the && and || operators, all side effects take place
        before a program moves from one operand to the next.

28. Example 5.19
    ------------
    Program:
    /* logical1.c -- logical operators */
    #include <stdio.h>
    int main(void)
    {
      /* relational operators have higher precedence than logical
         operators */
      printf("5>2&&4>7 is %d\n", 5>2&&4>7);
      printf("4>7||5>2 is %d\n", 4>7||5>2);

      /* ! has higher precedence than relational operators */
      printf("!4>7 is %d\n", !4>7);
      printf("!(4>7) is %d\n", !(4>7));

      /* (1) relational operators have higher precedence than logical
             operators
         (2) && has higher precedence than || */
      printf("4>7||5>2&&6>3 is %d\n", 4>7||5>2&&6>3);
      return 0;
    }

    Trace:
    1) 5>2&&4>7 is 1&&4>7 is 1&&0 is 0
    2) 4>7||5>2 is 0||5>2 is 0||1 is 1
    3) !4>7 = 0>7 = 0
    4) !(4>7) is !0 is 1
    5) 4>7||5>2&&6>3 is 0||5>2&&6>3 is 0||1&&6>3 is 0||1&&1 is 0||1 is 1

    Output:
    5>2&&4>7 is 0
    4>7||5>2 is 1
    !4>7 is 0
    !(4>7) is 1
    4>7||5>2&&6>3 is 1

29. Example 5.20
    ------------
    Program:
    /* logical2.c -- logical operators */
    #include <stdio.h>
    int main(void)
    {
      int num, ans;

      /* order of evaluation rules:
         (1) logical expressions are evaluated from left to right
             whether they share an operand or not
         (2) evaluation stops as soon as something is discovered that
             renders the expression true or false */

      /* order of evaluation rules guarantee that if scanf() fails to
         assign a value to num, the computer won't try to use num */
      printf("Please enter an integer.\n");
      ans = (scanf("%d", &num) == 1 && num != 0);
      printf("ans = %d\n", ans);

      /* order of evaluation rules guarantee that if num is zero, the
         computer won't try to divide by zero which gives a run-time
         error */
      num = 0;
      ans = (num != 0 && 12/num == 2);
      printf("num = %d, ans = %d\n", num, ans);
      return 0;
    }

    Screen:
    Output: Please enter an integer.
    Input:  q
    Output: ans = 0
    Output: num = 0, ans = 0
 



17



