0
点赞
收藏
分享

微信扫一扫

C 语言的一些笔记

米小格儿 2022-01-24 阅读 83
c语言



C 语言中 &&|| 优先级、结合性

分析下题的答案

在这里插入图片描述

C 语言运算符的优先级和结合性

首先,要知道 C 语言运算符的优先级和结合性。
查阅资料得知:&& 的优先级比 || 高,结合性是从左往右。运算时,会把 && 左边的表达式看做一个整体。
在这里插入图片描述

分析几个简单的示例

第 1 个示例

先来几个简单的示例,进行分析:

#include <stdio.h>

int main()
{
	int a = 1, b = 0;

	printf("%d\n", b && a || b);
	printf("%d\n", a || b && a);
	printf("%d\n", a || b && b);

	return 0;
}

/*
运行结果:

0
1
1
*/
第一条语句

printf("%d\n", b && a || b);

  1. && 优先级比 || 高,会先执行 b 这个表达式。b 的结果为 0,C 语言中 0 为假。&& 的特性:只要任何一边的结果为假,整个表达式的结果即为假。
  2. b 的结果已经为假,就不会再去理会右边整个 a || b,直接短路并返回结果,不往后面走了。
第二条语句

printf("%d\n", a || b && a);

  1. && 优先级比 || 高,&& 左边的所有内容都会被看做为一个整体,先去执行 && 左边的表达式 a || b
  2. a 为真,|| 一样也会短路,任意表达式为真,整个表达式即为真。
  3. || 左边已经短路了,同样也不会再去管右边的表达式 b && a 了。直接返回 1,结束本条语句。
第三条语句

printf("%d\n", a || b && b);

  1. 同样先去执行 && 左边的 a || b 表达式。
  2. a1|| 短路并返回结果,后面的表达式不会再去计算了。

第 2 个示例

#include <stdio.h>

int main()
{
	int a = 1, b = 0;

	printf("%d\n", b || a && a);

	return 0;
}

/*
运行结果:

1
*/

b || a && a

  1. && 的优先级比 || 高,会先去执行 && 左边的 b || a。(注:b || a&& 左边的一个整体)。
  2. b || a 中,同样也先执行左边的 bb0,此时 || 不会短路,它要继续去计算右边的结果。右边的 a1,整个 b || a 表达的结果为 1
  3. 现在的表达式是:1 && aa1&& 的两边都为 1,表达式为 1
  4. 计算完毕,返回结果 1

第 3 个示例

#include <stdio.h>

int main()
{
	int a = 1, b = 0, c = 1;

	printf("%d\n", b || a && c && b);

	return 0;
}

/*
运行结果:

0
*/

表达式 b || a && c && b 中,有两个 &&,按照结合性,是从左往右计算。

  1. 把表达式劈成两瓣,就是:b || a && c&& b
  2. 先去执行 b || a && c,再次把这个表达式劈开:b || a&& c
  3. 从左往右,先会计算 b || a 这个表达式的左边 bb 的结果为 0,然后计算 aa1,于是 b || a 的结果为 1。现在表达式为:1 && cc 也是 1。表达式 b || a && c 的结果为 1
  4. 现在的表达式为:1 && b&& 需要计算两边的结果才能判定是否都为 1。但是,b0。只要有一个结果为 0,整个 && 表达式就为 0。返回结果 0

小结

&&|| 同时在一条语句中,要记住 && 的优先级比 || 高,&& 左边的所有一切都是一个完整的整体。


再来一题

#include <stdio.h>

int main()
{
	int a = 1, b = 0, c = 0;

	c = (a+=10) || (b+=5) && (b+=5);
	printf("a=%d, b=%d, c=%d\n", a, b, c);

	a = 1, b = 0;
	c = (a+=10) || ( (b+=5) && (b+=5) );
	printf("a=%d, b=%d, c=%d\n", a, b, c);

	a = 1, b = 0;
	c = ( (a+=10) || (b+=5) ) && (b+=5);
	printf("a=%d, b=%d, c=%d\n", a, b, c);

	return 0;
}


/*
运行结果:

a=11, b=0, c=1
a=11, b=0, c=1
a=11, b=5, c=1
*/

第一条语句

c = (a+=10) || (b+=5) && (b+=5);

  1. 有三个“加后赋值语句”,都被小括号包裹了起来。三个优先级是平级的,就会去看 &&|| 的优先级。
  2. && 高于 ||,先会去执行 && 左边的 (a+=10) || (b+=5) 这个表达式。
  3. 再在这个 (a+=10) || (b+=5) 表达式中,先执行 (a+=10),现在 a 的结果为 11,且运行结果为真,即为 1
  4. 上述的表达式变成了 1 || (b+=5),遇到一个结果为真,|| 发生短路,不会再去管后面的 (b+=5),更不会去管 || 后面的那些整体了。
  5. 直接给 c 赋值为 1,并结束本条语句。

第二条语句

c = (a+=10) || ( (b+=5) && (b+=5) );

  1. 在第一条语句基础上,把 || 后面的语句用小括号再次包裹了起来。现在变成了 2 个小括号语句:(a+=10) || ( ... )
  2. 先执行 || 左边的小括号中的表达式,a = a + 10a 的结果为 11。表达式运行结果为真,即为 1
  3. 现在表达式是:c = 1 || ( (b+=5) && (b+=5) );|| 发生短路并将 1 赋值给 c 后,结束整条语句。

第三条语句

c = ( (a+=10) || (b+=5) ) && (b+=5);

  1. 小括号提升优先级,语句是:c = ( ... ) && (b+=5);
  2. 先执行 && 左边小括号中的语句 ( (a+=10) || (b+=5) )
  3. ( (a+=10) || (b+=5) ) 中,先执行 (a+=10)a 被赋值为 11,语句运行结果为 1|| 发生短路,不会去计算后面的 (b+=5)。但是,此条语句中的 (b+=5) 是被包裹在小括号中的。不执行 (b+=5) 该条语句,是因为被 || 短路了。出了小括号之后,还会有 ... && (b+=5) 这条语句的 && 右边需要去被执行。
  4. 现在的语句是:c = 1 && (b+=5);。左边的结果为真,但 && 还需要右边的结果。b+=5b 被赋值为 5,语句运行结果为 1
  5. 两边都为 1,将 1 赋值给 c

回到最初的问题

#include <stdio.h>

int main()
{
	int a = 2, b = 2, c = 2;

	c = (a = 3) || (a = 4) && (b = 5);
	printf("a=%d, b=%d, c=%d\n", a, b, c);

	return 0;
}


/*
运行结果:

a=3, b=2, c=1
*/

c = (a = 3) || (a = 4) && (b = 5);

  1. 语句也是由 3 个小括号包裹着。3 个小括号优先级是平级的,那么就要看 &&|| 的优先级谁更高,显然是 && 的优先级高。
  2. 于是表达式 (a = 3) || (a = 4) 这个整体会先被执行。
  3. (a = 3) || (a = 4) 这个整体中,又先执行 (a = 3)。给 a 赋值为 3,表达式运行结果为 1(即为真)。只要一个条件为真,|| 就会发生短路,不再去理会 || 后面 (a = 4) && (b = 5) 这一大坨东西。
  4. 1 赋值给 c,结束本条语句。

参考文献

C 语言运算符的优先级和结合性

举报

相关推荐

0 条评论