咱们该如何对付花里胡哨的运算符优先级(C)

写在前面:这里是小王成长日志,一名普通在校大学生,想成学习之余将本身的学习笔记分享出来,记录本身的成长轨迹,帮助可能须要的人,平时博客内容主要是一些学习笔记,项目实战笔记,一些技术的探究和本身的一些思考。欢迎你们关注,大家的每个评论点赞关注我都会仔仔细细去看的。有任何问题欢迎交流,我会尽我所能帮助你们的,共创CSDN美好环境。html

通常来讲,运算符优先级这种东西不该该去强行记忆,由于在本身不肯定的时候用括号来为表达式强行指定顺序就完事了,方便简单不伤脑,并且在不一样的语言中优先级也可能不一样,用多了天然就熟了,可是!git

直到看到一些题目,我才知道也许咱们可以控制本身,可是不能控制别人写出那种毁天灭地的代码,并且!老师也喜欢出那种花里胡哨的题目,平常掉发的程序猿继续落泪~github


1.速查表

供速查用,会不会都请先大体浏览一遍再看下面的。下面是一个文档,内含C语言经常使用转义字符、ASCII、优先级的对照表。(原本想直接上传CSDN的,奈何审批太慢)web

…发出来前几秒,有提示我审核经过了 点连接下载,不须要积分数组

连接:https://share.weiyun.com/5695tZw 密码:7ytpbmsvg

优先级函数

运算符学习

名称或含义ui

使用形式spa

结合方向

说明

1

[]

数组下标

数组名[常量表达式]

左到右

 

()

圆括号

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

 

.

成员选择(对象)

对象.成员名

 

->

成员选择(指针)

对象指针->成员名

 

2

-

负号运算符

-表达式

右到左

单目运算符

(类型)

强制类型转换

(数据类型)表达式

 

++

自增运算符

++变量名/变量名++

单目运算符

--

自减运算符

--变量名/变量名--

单目运算符

*

取值运算符

*指针变量

单目运算符

&

取地址运算符

&变量名

单目运算符

!

逻辑非运算符

!表达式

单目运算符

~

按位取反运算符

~表达式

单目运算符

sizeof

长度运算符

sizeof(表达式)

 

3

/

表达式/表达式

左到右

双目运算符

*

表达式*表达式

双目运算符

%

余数(取模)

整型表达式/整型表达式

双目运算符

4

+

表达式+表达式

左到右

双目运算符

-

表达式-表达式

双目运算符

5

<<

左移

变量<<表达式

左到右

双目运算符

>>

右移

变量>>表达式

双目运算符

6

>

大于

表达式>表达式

左到右

双目运算符

>=

大于等于

表达式>=表达式

双目运算符

<

小于

表达式<表达式

双目运算符

<=

小于等于

表达式<=表达式

双目运算符

7

==

等于

表达式==表达式

左到右

双目运算符

!=

不等于

表达式!= 表达式

双目运算符

8

&

按位与

表达式&表达式

左到右

双目运算符

9

^

按位异或

表达式^表达式

左到右

双目运算符

10

|

按位或

表达式|表达式

左到右

双目运算符

11

&&

逻辑与

表达式&&表达式

左到右

双目运算符

12

||

逻辑或

表达式||表达式

左到右

双目运算符

13

?:

条件运算符

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

右到左

三目运算符

14

=

赋值运算符

变量=表达式

右到左

 

/=

除后赋值

变量/=表达式

 

*=

乘后赋值

变量*=表达式

 

%=

取模后赋值

变量%=表达式

 

+=

加后赋值

变量+=表达式

 

-=

减后赋值

变量-=表达式

 

<<=

左移后赋值

变量<<=表达式

 

>>=

右移后赋值

变量>>=表达式

 

&=

按位与后赋值

变量&=表达式

 

^=

按位异或后赋值

变量^=表达式

 

|=

按位或后赋值

变量|=表达式

 

15

,

逗号运算符

表达式,表达式,…

左到右

从左向右顺序运算

2.记忆方法

开始记忆以前咱们先来看一下一些表中涉及到的概念:

什么是目?

所谓"目",也能够称之为元,那么咱们再来看看,单元(一元)运算符,双元运算符,三元运算符,再看看例如看看下面几个表达式,有没有点感受?

a++;// ++ 单目
    &b;//& 单目
    c - d;//- 双目
    e > f;//> 双目
    (1 > 2) ? a : b,//?: 三目

单目运算符, 一些只须要一个操做数的运算符称为一元运算符(或单目运算符),以此类推,双目运算符有须要两个操做数数才能进行运算.三元则须要三个(参考百度百科

C语言中大部分都是双目运算符,小部分是单目的,三目运算符只有一个,就是条件运算符 ?:

结合方向是什么?

在上面的表里,咱们还能看到特殊的一列,就是结合方向,这一列指得是当运算符有优先级相同(同级)时的运算顺序.

巧记方法

其实我也不想记,想在使用中熟悉,想着加括号就好,可是牢不住老师太猛啊,仍是乖乖记一下吧:

  • 1,记住总表的规律
    • C语言中大多数运算符的结合性都是从左往右,只有三个运算符是从右往左的。一个是单目运算符,另外一个是三目运算符,还有一个就是双目运算符中的赋值运算符=
    • 双目运算符中只有赋值运算符的结合性是从右往左的,其余的都是从左往右。
    • C语言中有且只有一个三目运算符。
    • 逗号运算符的优先级最低,要记住。
    • 此外要记住,对于优先级:算术运算符 > 关系运算符 > 逻辑运算符 > 赋值运算符。逻辑运算符中“逻辑非 !”除外。

2.背一段顺口溜

这是我在网上找的一段顺口溜,背下来应该也是有用的

醋坛酸味灌

味落跳福豆

共44个运算符:

初等,4个:()[]->指向结构体成员.结构体成员
单目,9个:!~+±–负号(类型)*指针&取地址sizeof长度
算术,5个:*/%±减
位移,2个:<<>>
关系,6个:<<=>>===等于!=不等于
位逻,3个:&按位与^按位异或|按位或
逻辑,2个:&&逻辑与||逻辑或
条件,1个,三目:?:
赋值,11个:=+=-=*=/=%=>>=<<=&=^=|=
逗号,1个:,

简单记就是:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符

参考:

3.一块儿看看运算符优先级的一些题目

1. C语言混乱代码大赛-尝试理解一下下面这段代码

#include <stdio.h>
char *a; main(int t,int _,char* a){return!0<t?t<3?main(-79,-13,a+main(-87,1-_, main(-86,0,a+1)+a)):1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13? main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t, "@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n{n+,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/") :t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1) :0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a, "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"),a+1);}

能力有限,我就不班门弄斧了,并且这个远远不止于运算符优先级,感兴趣的同窗能够点上面的超连接去看看

2. *p++自增p仍是p所指向的变量?

在这一题中,根据咱们的理解,* 的优先级是要低于 自增符++的,因此 *p++ 实际上和 *(p++) 等价,它自增p而且返回p自增以前所指向的值。

若是咱们想要自增p所指向的值则须要写成 (*p)++;

看代码:

int *p = NULL;
    int arr[2] = {1, 10};

    p = arr;
    printf("*p++ = %d\n",*p++);//1
    printf("*p = %d\n",*p);//10

    p = arr;
    printf("(*p)++ = %d\n",(*p)++);//1
    printf("*p = %d\n",*p);//2

3. 试着理解a+++++b

在C中,写成这样也是没有意义的。词汇分析的规则规定,在一个简单的从左到右扫描中的每一个点,最长的记号被划分,无论这样出来的记号序列是否有意义。问题中的片断被解释为

a ++ ++ +

在语法上说这是个不合法的表达式
经提醒 在JAVA中这样写是合法的,注意区分
看代码

int a,b;
    a=1;
    b=2;
    printf("a+++++b = %d",a+++++b);

    /**************运行结果 test.c: In function 'main': test.c:9:30: error: lvalue required as increment operand printf("a+++++b = %d",a+++++b); **************/

4. k = j>i && 8==i;

岔看到这个表达式的时候会不会有点头晕,由于咱们平常都会在不明确的地方加上括号,例如

( k = j )&&( 8 == i )

可是在这个表达式中没有任何括号给咱们提示,而且涉及到了四种运算符,其优先级都须要咱们本身去考虑。

首先速查这四种运算符的优先级:

赋值运算符优先级最低,其次&&AND运算符,== 和 > 虽然都是双目运算符,可是== 优先级低于 > 运算符。

因此上式等同于
(k = (j > i)) && (8 == i)

看代码:

int k, j, i;
    k = 1;
    j = 2;
    i = 8;
    printf("%d\n",j > i);//0
    printf("%d\n",k = (j > i));//0
    printf("%d\n",8 == i);//1

    printf("(k = (j > i)) && (8 == i) = %d\n", (k = (j > i)) && (8 == i));//0
    printf("k = j > i && 8 == i = %d", k = j > i && 8 == i);//0

4.参考

  • 详见原文超连接

5.以往文章推荐


都看到这里了,各位哥哥姐姐叔叔阿姨给小王点个赞 关个注 留个言吧,和小王一块儿成长吧,大家的关注是对我最大的支持。


若是以上内容有任何不许确或遗漏之处,或者你有更好的意见,就在下面留个言让我知道吧-我会尽我所能来回答。