C语言——运算符优先级问题

本文详细介绍了C语言中的各种运算符及其优先级,并解释了运算符的结合性是如何影响表达式的计算顺序。
 

优先级

运算符

名称或含义

使用形式

结合方向

说明

1

[]

数组下标

数组名[常量表达式]

左到右

 

()

圆括号

(表达式)/函数名(形参表)

 

.

成员选择(对象)

对象.成员名

 

->

成员选择(指针)

对象指针->成员名

 

2

-

负号运算符

-表达式

右到左

单目运算符

(类型)

强制类型转换

(数据类型)表达式

 

++

自增运算符

++变量名/变量名++

单目运算符

--

自减运算符

--变量名/变量名--

单目运算符

*

取值运算符

*指针变量

单目运算符

&

取地址运算符

&变量名

单目运算符

!

逻辑非运算符

!表达式

单目运算符

~

按位取反运算符

~表达式

单目运算符

sizeof

长度运算符

sizeof(表达式)

 

3

/

表达式/表达式

左到右

双目运算符

*

表达式*表达式

双目运算符

%

余数(取模)

整型表达式/整型表达式

双目运算符

4

+

表达式+表达式

左到右

双目运算符

-

表达式-表达式

双目运算符

5

<<

左移

变量<<表达式

左到右

双目运算符

>>

右移

变量>>表达式

双目运算符

6

>

大于

表达式>表达式

左到右

双目运算符

>=

大于等于

表达式>=表达式

双目运算符

<

小于

表达式<表达式

双目运算符

<=

小于等于

表达式<=表达式

双目运算符

7

==

等于

表达式==表达式

左到右

双目运算符

!=

不等于

表达式!= 表达式

双目运算符

8

&

按位与

表达式&表达式

左到右

双目运算符

9

^

按位异或

表达式^表达式

左到右

双目运算符

10

|

按位或

表达式|表达式

左到右

双目运算符

11

&&

逻辑与

表达式&&表达式

左到右

双目运算符

12

||

逻辑或

表达式||表达式

左到右

双目运算符

13

?:

条件运算符

表达式1? 表达式2: 表达式3

右到左

三目运算符

14

=

赋值运算符

变量=表达式

右到左

 

/=

除后赋值

变量/=表达式

 

*=

乘后赋值

变量*=表达式

 

%=

取模后赋值

变量%=表达式

 

+=

加后赋值

变量+=表达式

 

-=

减后赋值

变量-=表达式

 

<<=

左移后赋值

变量<<=表达式

 

>>=

右移后赋值

变量>>=表达式

 

&=

按位与后赋值

变量&=表达式

 

^=

按位异或后赋值

变量^=表达式

 

|=

按位或后赋值

变量|=表达式

 

15

,

逗号运算符

表达式,表达式,…

左到右

从左向右顺序运算

 

运算符的优先级:C语言中,运算符的运算优先级共分为15 级。1 级最高,15 级最低。在表达式中,优先级较高的先于优先级较低的进行运算。而在一个运算量两侧的运算符优先级相同时,则按运算符的结合性所规定的结合方向处理。

运算符的结合性:C语言中各运算符的结合性分为两种,即左结合性(自左至右)和右结合性(自右至左)。例如算术运算符的结合性是自左至右,即先左后右。如有表达式x-y+z 则y 应先与“-”号结合,执行x-y 运算,然后再执行+z 的运算。这种自左至右的结合方向就称为“左结合性”。而自右至左的结合方向称为“右结合性”。最典型的右结合性运算符是赋值运算符。如x=y=z,由于“=”的右结合性,应先执行y=z 再执行x=(y=z)

  运算。C语言运算符中有不少为右结合性,应注意区别,以避免理解错误。

  优先级从上到下依次递减,最上面具有最高的优先级,逗号操作符具有最低的优先级。

  所有的优先级中,只有三个优先级是从右至左结合的,它们是单目运算符、条件运算符、赋值运算符。其它的都是从左至右结合。

  具有最高优先级的其实并不算是真正的运算符,它们算是一类特殊的操作。()是与函数相关,[]与数组相关,而->及.是取结构成员。

  其次是单目运算符,所有的单目运算符具有相同的优先级,因此在我认为的真正的运算符中它们具有最高的优先级,又由于它们都是从右至左结合的,因此*p++与*(p++)等效是毫无疑问的。

  另外在C语言里,没有前置后置之分,因为++ -- 是右结合所以右侧优先运算,表现为 "操作数后置优先级比较高" 的假象,前置和后置的区分是因为运算符重载而后加入C++的

  接下来是算术运算符,*、/、%的优先级当然比+、-高了。

  移位运算符紧随其后。

  其次的关系运算符中,< <= > >=要比 == !=高一个级别,不大好理解。

  所有的逻辑操作符都具有不同的优先级(单目运算符除外,!和~)

  逻辑位操作符的"与"比"或"高,而"异或"则在它们之间。

  跟在其后的&&比||高。

  接下来的是条件运算符,赋值运算符及逗号运算符。

  在C语言中,只有4个运算符规定了运算方向,它们是&&、| |、条件运算符及赋值运算符。

  &&、| |都是先计算左边表达式的值,当左边表达式的值能确定整个表达式的值时,就不再计算右边表达式的值。如 a = 0 && b; &&运算符的左边位0,则右边表达式b就不再判断。

  在条件运算符中。如a?b:c;先判断a的值,再根据a的值对b或c之中的一个进行求值。

  赋值表达式则规定先对右边的表达式求值,因此使 a = b = c = 6;成为可能。

### 关于C语言运算符优先级的练习题 理解并熟练掌握C语言中的运算符优先级对于编写高效且无误的代码非常重要。下面是一些关于C语言运算符优先级的具体练习题及其解答。 #### 练习题1:简单算术表达式求值 给定如下表达式: ```c int a = 3 * (4 + 5); ``` 此表达式中,由于圆括号`()`具有最高优先级[^4],因此会先执行其中的操作即\(4+5\)得到9;接着乘法\(*\)被执行,最终结果为27。 #### 练习题2:逻辑与按位移位混合使用 考虑这段代码片段: ```c unsigned char b = ((0x8F >> 2) & 0xF0 | 0x0A); ``` 这里涉及到右移`\>>`, 按位与`&`以及按位或`|`三个不同类型的运算符。根据它们各自的优先级,首先是右移操作被处理,之后是按位与最后才是按位或。具体来说,`0x8F`(二进制表示为`10001111`)向右移动两位变成`00100011`也就是十进制下的35, 接着跟`0xF0`做按位与获得`00100000`再和`0x0A`作按位或得出最终的结果`00101010`或者说是整数42[^3]。 #### 练习题3:自增/减与其他运算组合 分析下列语句的行为: ```c int c=1,d; d=(++c)+(c++)+(--c)-(c--); printf("%d %d\n", d,c); ``` 在这个例子里面,前置增量(`++c`)会在读取变量之前增加其值而后者置增量(`c++`)则是在访问过后才改变数值。同样地适用于前缀减少(`--c`)和后缀减少(`c--`). 执行上述命令序列后的输出将是 `6 2`. 解析过程如下: - 初始状态:c=1; - `(++c)`使c变为2,并返回新值2; - `(c++)`此时c仍等于2,在这一步结束后才会更新成3,但是此处使用的还是原来的值2; - `(--c)`将c降回至1,并立即生效; - `(c--)`再次利用当前值1作为参与计算的部分,随后降低到0. 综上所述,总和为 \(2+2+1−1=6,\quad c=0.\) #### 练习题4:条件运算符的应用 观察这个三元条件运算符的例子: ```c int e,f,g,h; e=f=g=h=1; h=e?f?g:h:e; ``` 这里的重点在于理解条件运算符(?:)的工作方式——它属于最低级别的优先级之一[^1]. 表达式的评估遵循从左往右的原则直到遇到第一个问号为止,这意味着整个表达式实际上相当于`((e)?f:(g?h:e))`. 假设所有变量都被初始化为了1,则最终赋给`h`的是`f`的值也即是1.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值