Thread: Logical And

  1. #1
    Samuel shiju's Avatar
    Join Date
    Dec 2003
    Posts
    41

    Logical And

    Code:
    #include <stdio.h>
    
    int expr(char str[], int i){
    	printf("%s \n",str);
    	return  i;
    }
    
    int main()
    {
    	if(expr("1st",1) || expr("2nd",0) && expr("3rd",1));
    	return 0;
    }
    
    )


    output
    -------
    1st




    Logical and has Higher precedence then logical or

    Then why the above code evaluated expr("1st",1) first
    and not expr("2nd",0) && expr("3rd",1)
    Last edited by shiju; 01-11-2004 at 12:35 AM.

  2. #2
    Obsessed with C chrismiceli's Avatar
    Join Date
    Jan 2003
    Posts
    501
    don't even worry about presidence, use parenthisies.
    Help populate a c/c++ help irc channel
    server: irc://irc.efnet.net
    channel: #c

  3. #3
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    As it was explained to me the conditions are evaulted from left to right.

    Also it would make more since to evaulte the left side of the || first since if it is true that would be all it needed to enter into the condition.

    Code:
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    
    int main (void)
    {
      int x, y=100, z;
      const int range=20, cutoff=1;
      srand ( (unsigned) time(NULL));
    
      while ( ((x=rand()%range)!=0) && ( (z=(y/x)) > cutoff) )
      {
        printf("%d\t%d\n",x, z);
      }
      printf("%d\t%d\n", x, z);
      return 0;
    }
    As you can see the right side of the && isn't even evaulated when x is zero since the program is able that the condition is false and can leave the loop.

    And an example using your conditions while some modifications to the functions. (note: The added () around the && conditions do not change it, was just a warning the compiler gave)
    Code:
    #include <stdio.h>
    
    int fun1 (char str[], int i)
    {
      printf("Evaluating %s condition. ", str);
      if ( i == 1)
      {
        printf("Returning false.\n");
        return 0;
      }
      else
      {
        printf("Returning true.\n");
        return 1;
      }
    }
    
    int fun2 (char str[], int i)
    {
      printf("Evaluating %s condition. ", str);
      if ( i != 1)
      {
        printf("Returning false.\n");
        return 0;
      }
      else
      {
        printf("Returning true.\n");
        return 1;
      }
    }
    
    int main (void)
    {
      printf("First one: \n");
      if (fun1("1st",1) || (fun1("2nd",2) && fun1("3rd",3)) );
      printf("Second one: \n");
      if (fun2("1st",1) || (fun2("2nd",2) && fun2("3rd",3)) );
      return 0;
    }
    Last edited by Thantos; 01-11-2004 at 01:56 AM.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Any good C book should explain the left-to-right evaluation of && and ||

    In short
    if ( a && b )
    b is not evaluated if a is false. There would be no point to evaluating b because the expression would still be false

    if ( a || b )
    b is not evaluated if a is true. There would be no point to evaluating b because the expression would still be true

    One thing it allows you to do for example is test a pointer and dereference it in the same expression
    if ( p != NULL && *p != '\n' ) /* not the end of a valid string */
    You can be sure that if p is NULL, then it won't be dereferenced to check for a newline character.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Samuel shiju's Avatar
    Join Date
    Dec 2003
    Posts
    41
    I am not wondering why the right hand side is not evaluated when the left hand side determines the outcome

    I want to know why the AND is not evaluated first when it got higher precedence over OR as in a arithmetic operator * got higher precedence over +

    5 + 2 * 3

    2 * 3 is evaluated first not 5 + 2

    then why in expression

    expr("1st",1) || expr("2nd",0) && expr("3rd",1)

    OR side is evaluated first

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Where's the problem here?

    Given expr("1st",1) || expr("2nd",0) && expr("3rd",1), you get
    a is expr("1st",1)
    b is expr("2nd",0) && expr("3rd",1)

    So if a is true, b isn't evaluated

    The precedence only tells you that you have
    expr("1st",1) || ( expr("2nd",0) && expr("3rd",1) )
    and not
    ( expr("1st",1) || expr("2nd",0) ) && expr("3rd",1)
    http://www.eskimo.com/~scs/C-faq/q3.5.html

    > as in a arithmetic operator * got higher precedence over +
    Yeah, but you don't know which order the operands are evaluated in.
    Given
    f1() + f2() * f3()
    There is nothing stopping the compiler from calling f1() first, saving the result for later and then calling f3() followed by f2(). For sure precedence tells you how the results are combined, but it does nothing to tell you in which order the individual sub-expressions are evaluated in.
    If in some horrible code, the outcome of f2() depended on whether f1() was called first, then you'd be in for a lot of grief at some point.
    http://www.eskimo.com/~scs/C-faq/q3.4.html

    The important point for the boolean operators is that the left-to-right order is guaranteed.

    Consider again my
    if ( p != NULL && *p != '\n' )
    If the order were not always predictably left-to-right, then it would randomly crash with a segmentation fault at the whim of the implementation of the compiler, because it dereferenced a pointer before checking that it was NULL.

    Then you would be in the sorry mess that Pascal is in, where you have to implement && and || using if / else chains if one part of the expression guards the evaluation of another part of the expression.
    http://www.lysator.liu.se/c/bwk-on-pascal.html
    Yes Pascal has 'and' and 'or', but they don't have useful left-to-right properties.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Salem I respect you but you are wrong on the Pascal point. The paper you linked is from 1981. The standard for Pascal has had some improvements done. As such modern compilers (such as Free Pascal) use the C style method of left to right evaluation and stopping as soon as it has enough to determine if it should go into the condition or not.

    I read BWK's paper and I am sure its 100% accurate for 1981 but it is not for 2004.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Codeblocks and logical operators
    By fhbwghads in forum C++ Programming
    Replies: 2
    Last Post: 12-07-2008, 05:22 AM
  2. Logical Error
    By gardenair in forum C Programming
    Replies: 2
    Last Post: 04-06-2003, 04:18 PM
  3. Size of 1 pixel
    By ooosawaddee3 in forum C++ Programming
    Replies: 4
    Last Post: 07-26-2002, 08:06 PM
  4. logical operators
    By sballew in forum C Programming
    Replies: 4
    Last Post: 09-04-2001, 06:24 PM