&&与||的妙用

On September 30, 2010, in C语言, 笔试面试, 语言学习, by sponge

我们都知道,&&是逻辑与, ||是逻辑或。对于这两个运算符,有下面的性质:

1 && 1 = 1; 1 && 0 = 0; 0 && 1 = 0; 0 && 0 = 0;
1 || 1 = 1; 1 || 0 = 1; 0 || 1 = 1; 0 || 0 = 0;

出了这些基本的性质之外,额外需要注意的是,在C语言中,这两个运算符有如下的性质:

  1. && 的 优先级高于 ||
  2. 让我们看如下代码:

    #inlcude <stdio.h>
    int main(){
            int a, b;
            a = 1 || 1 && 0;
            b = (1 || 1) && 0;
            printf("%d\n",a);
            printf("%d\n", b);
    }

    这段代码的输出是什么呢?大家可以自己验证下,答案是a=1; b=0。

  3. 这两个运算符都是短路(short circuit)操作符。什么是短路操作符呢?我们注意到,对于&&操作符来说,如果它的左操作数为false,则整个表达式一定为false,我们不需要再计算其右表达式,而C语言中确实也是这么做的。对于||情况也是一样的,如果其左操作数为true,则整个表达式一定为true,而不用计算其右表达式。这两个操作符只有在当左操作数不能决定整个表达式的值的时候才会计算右操作数。
  4. 如下面代码:

    #include <stdio.h>
    int func(); //计算一些事情并返回一个值
    int main(){
            0 && func(); //func()不会被计算
            1 || func(); //func()不会被计算
            1 && func(); //func()会被计算
            0 || func(); //func()会被计算
    }

下面我们来看一道题目,是EMC某年的笔试题:

题目:

函数声明如下:

int func(int i, int N);

其中,i<=N, 功能输出i递增到N再递减到i的整数,每行输出一个数。比如func(1, 5)的输出是:

1
2
3
4
5
4
3
2
1

要求:

  1. 函数中只能有一个语句,即1个分号。
  2. 不能使用do while until goto for if关键字,不能使用?:和逗号操作符。
  3. 唯一能使用的库函数为printf。

题目要求不能使用for等关键字,而且只有一个语句,那我们怎么才能实现一个循环递减和递增的数字序列呢?我们可以想到使用(递归),那么条件判断呢?这时,就可以利用&&和||的第二个性质来达到目的:

#include <stdio.h>
int func(int i, int N){
        return
        (i == N) && printf("%d\n",i) || printf("%d\n", i ) && func(i+1, N) && printf("%d\n", i);
}

另外,需要注意的是,尽管&&和||是短路操作符,但是“按位与/或”(&和|)却不是短路操作

anyShare分享到:
          
Tagged with:
 

8 Responses to “&&与||的妙用”

  1. sagi says:

    文中的 “func(i-1, N)” 应该是 func(1+1, N) 吧 ?

  2. yjf512 says:

    学习了~仿造写了一个:

    #include

    int func(int i, int N){
    return (((i<=N && printf("%d\n",i)) && (func(i+1,N)||1)) && printf("%d\n",i));
    }

  3. roclafamilia says:

    Helpful blog, bookmarked the website with hopes to read more!

  4. ligang says:

    这些纯技巧的东西,一般没什么意义。。。。

Leave a Reply

Note: Commenter is allowed to use '@User+blank' to automatically notify your reply to other commenter. e.g, if ABC is one of commenter of this post, then write '@ABC '(exclude ') will automatically send your comment to ABC. Using '@all ' to notify all previous commenters. Be sure that the value of User should exactly match with commenter's name (case sensitive).