++a || ++b && ++c在C语言中怎么计算
int a=0,b=0,c=0,k=0;//以下用到的所有变量都赋初值0
k=++a || ++b &&++c;
printf("a=%d b=%d c=%d\n",a,b,c);
printf("k=%d\n",k);
分析
很多地方说此处计算要用到优先级,其实不然
1、如果按照优先级相等来运算: ++a后a==1,++b被短路b==0,c==1
则应输出 a=1 b=0 c=1 k=1
编译运行:
与分析结果不符。
2、如果仅仅按照逻辑与优先级高来计算,应输出 a=0 b=1 c=1 k=1
显然也和运行结果不符合。
综上,此类计算并不依赖优先级运算,而是依赖结合性。
计算方法(以下为个人见解,如果有反例请提出)
首先要明确"与"的结合性高于"或"。
遇到逻辑与(&&)、或(||)的运算,要将与(&&)运算看成整体(将与运算用括号括起来,使得式中只存在逻辑或)值不变,然后从左向右依次计算,兼顾短路现象。注意这里的括号只起到整体作用,并不是先计算。则原式可化成:k=++a || (++b &&++c);
++a表达式的值为1,则逻辑或短路,所以括号内的表达式都不计算。
因此,输出a=1 b=0 c=0 k=1
与运算加括号值不变证明
k=++a || (++b &&++c);
printf("a=%d b=%d c=%d\n",a,b,c);
printf("k=%d\n",k);
将上述代码编译运行:
引申 1 判断以下程序输出
k = a++ && ++b || ++c;
printf("a=%d b=%d c=%d\n",a,b,c);
printf("k=%d\n",k);
分析:原式可化为k=( a++ && ++b) || ++c;
先看左边的与运算,a++表达式为0,a== 1;++b被短路,b==0;与运算值为0。
再看右边,++c的值为1,c==1;则应输出a=1 b=0 c=1 k=1
编译运行:
引申 2
int a=0,b=0,c=0,d=0,k=0;
k = a++ && ++b || ++c && d++;
printf("a=%d b=%d c=%d d=%d\n",a,b,c,d);
printf("k=%d\n",k);
分析:原式可化为k=(a++ && ++b)||(++c && d++)
先看左边(a++ && ++b):a++表达式的值为0,a==1;++b被短路,b==0;
左边(a++ && ++b)的值为0,或运算未被短路
再看右边 (++c && d++) :++c表达式的值为1,c==1;d++表达式的值为0,d==1;
右边(++c && d++)的值为 0; 0||0的值为0;
则应输出 a=1 b=0 c=1 d=1 k=0
编译运行:
引申 3
int a=0,b=0,c=0,d=0,k=0;
k = a++ || ++b && ++c || d++;
printf("a=%d b=%d c=%d d=%d\n",a,b,c,d);
printf("k=%d\n",k);
分析:原式可化为k=a++ || (++b && ++c) || d++
先看左边a++:a++表达式的值为0,a==1;表达式(++b && ++c)未被短路,则执行;
再看表达式(++b && ++c):表达式++b的值为1,b==1;表达式++c的值为1,c==1;
(++b && ++c)值为1 。
则表达式 a++||(++b && ++c)就变成 0||1==1 则最右边被短路d==0
则应输出 a=1 b=1 c=1 d=0 k=1
编译运行:
按照上面的分析,++a || ++b && ++c 相当于 (a+1) || (b+1) && (c+1),然后再等效于((a+1) || (b+1) )&& (c+1)。
例如假设a= -2 ,b= 1,c=2 :那么有
((-2+1)|| (3+1))&&(2+1)→
(-1 || 4)&& 3 →
1 && 3 →
1
{备注:
在有逻辑运算符号时,非零值等价于“1”,真命题也等价于“1”,而零和假命题作为“0 ”看。比如式子 5>10 ,它在逻辑运算中等价于“0”,所以式子(5>10)+1)=1。由此可以看出为了便于运算,最上面的推导还可以这样做(非零值直接用1代替):
假设a= -2 ,b= 1,c=2 :
((-2+1)|| (3+1))&&(2+1)→
(1 || 1)&& 1 →
1 && 1 →
1
备注完 }
另外,注意++a和a++的区别。