Table
0. 为什么要掌握优先级
1. 优先级
1.1 优先级图表
1.2 运算符实例
1.3 优先级顺口溜
2. 结合性
3. 参考资料

写代码的时候,常会翻看的一个表就是“c语言运算符优先级表”。c的运算符优先级常常很让人头疼。其实,在大学里学习c的时候,老师告诉大家这个不用一定背下来,用的时候可以找书,或者加小括号就可以了。我听了,但是后来发现错了。很多人都听了,但不是每个人都发现这是错的。以至于有人觉得把优先级背下来是“没事闲的”

0. 为什么要掌握优先级

想想这两个问题:
a. 读别人的代码,遇到优先级问题看不懂,怎么办?
b. 一堆的括号,美观吗?
本想贴一张画来装饰墙壁,却用了一堆纸来固定!
有人说代码写多了,自然就会了。这个是很宽泛的说法。看你写的代码的水准,有些东西可能你一直都接触不到,何谈熟练。有些东西一定要梳理,总结。

1. 优先级

1.1 优先级图表

  • 优先级最高者不是真正意义上的运算符,包括:数组下标,函数调用,结构体成员选择符。
  • 单目运算符的优先级次之。(! ~ ++ -- - (type) * & sizeof)
  • 然后是双目运算符。双目运算符里, 算数运算符(* / % + -)优先级最高, 移位(<< >>)次之, 关系运算符(< <= > >= != ==)再次之, 接着是位运算符(& ^ | ),逻辑运算符(&& ||) 条件运算符(?: 三目),赋值运算符(= ...)。
  • 任何一个逻辑运算符的优先级低于任何一个关系运算符。
  • 移位运算符的优先级比算数运算符要低,但是比关系运算符要高。

1.2 运算符实例
a. while (c = getc(in) != EOF)
putc(c, out)
循环的意思是复制一个文件到另一个文件。但是由于!=的优先级比赋值运算符的优先级高,所以c被赋予了getc()的返回值与EOF比较后的布尔值,结果向out中写入了一堆1.
b. 解释下面几个声明
char *p[];
char (*p)[];
int *fp();
int (*fp)();

char *p[]
常常被错误的理解为指向字符数组的指针。
正确的是p一个数组,里面元素是指向字符的指针类型。
char (*p)[]
p是指向指向字符数组的指针。
int *fp()
常常错误理解为函数指针,该函数返回int类型。
正确的是fp是一个函数,他返回一个执行int的指针。
int (*fp)()
fp是函数指针,该函数返回int类型。

c. 解释下面的表达式
*p.f;
val & mask != 0;
max = val1 > val2 ? val1 : val2;

*p.f
对p去f偏移,作为指针,然后进行解引用。相当与*(p.f),因为.的优先级高与*。比较(*p).f。
val & mask != 0
相当与val & (mask != 0).
max = val1 > val2 ? val1 : val2
相当与 max = (val1 > val2 ? val1 :val2).

d. 一个复杂的声明

char *(* c[10])(int **p);
1. 有两个小括号,小括号的结合行是自左向右,所以我们先关注第一个小括号,简化声明(*c[10])();
c是一个数组,里面放10指针,后面紧跟这一个括号,所以这些指针是函数指针。
2. 关注第二个括号,(int **p)
显然p是函数的参数,它是个指向指针的指针。
3. 这看最前面的*
char *说明该函数的返回值是一个指向字符的指针。
4. 这个声明的意思就是:c是一个数组,里面有10个函数指针,指向的函数返回指针,指向字符,函数的参数是指向int类型指针的指针。

1.3 优先级顺口溜
醋坛酸味灌
味落跳福豆

共44个运算符

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

我更推荐在原理上理解以及长时间的使用来掌握,这顺口溜是网上刚刚翻到的,觉得挺好,辅助记忆。

2. 结合性
在标准C语言的文档里,对操作符的结合性并没有作出非常清楚的解释。一个满分的回答是:它是仲裁者,在几个操作符具有相同的优先级时决定先执行哪一个。
看例子:
int a, b = 1, c = 2;
a = b = c;
这个表达式只有赋值符,这样优先级就无法帮助我们呢决定哪个操作先执行。如果a = b先执行,然后 b = c执行。那么a最终取1。如果b = c先执行, a = b后执行,那么a最终取2。到底哪一个先执行?看结合性,复制的结合性是右至左,所以b = c,然后a = b。
同级的操作符,结合性相同。如果在计算表达式的值时候需要考虑结合性,那么最好把这个表达式一分为二。

3. 参考资料
《c Traps and Pitfalls》 Andrew Koenig著, ISBN 978-7-115-17179-5
《c 专家编程》 Peter Van Der Linden 著, ISBN 978-7-115-17180-1

细说C语言的优先级和结合性的更多相关文章

  1. 【部分原创】标准C语言的优先级、结合性、求值顺序、未定义行为和非确定行为浅析

    零. 优先级    在C++ Primer一书中,对于运算符的优先级是这样描述的:     Precedence specifies how the operands are grouped. It ...

  2. C语言运算符优先级及结合性

    今天去翻了下C语言运算符的优先级和结合性,发现当初学习的时候就没认真记住,惭愧.发现一篇讲得不错的文章,编辑了下转来供以后翻阅. C语言运算符优先级表(由上至下,优先级依次递减) 运算符 结合性 () ...

  3. C语言运算符优先级和结合性一览表

    所谓优先级就是当一个表达式中有多个运算符时,先计算谁,后计算谁.这个其实我们在小学学算术的时候就学过,如1+4÷2. 但是C语言中的运算符已经远不止四则运算中的加减乘除了,还有其他很多运算符.当它们出 ...

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

    运算符优先级和结合性 优先级                                       运算符 结合性                                         ...

  5. C语言运算符优先级和ASCII表

    1. C语言运算符优先级及结合性 优先级 运算符 名称或含义 使用形式 结合方向 说明 1 [] 数组下标 数组名[常量表达式] 左到右 -- () 圆括号 (表达式)/函数名(形参表) -- . 成 ...

  6. [转]说说C语言运算符的“优先级”与“结合性”

    补充自己的一点理解: 1.关于++i 与 i++的区别. ++i 和 i++如果是单独使用的语句,即二者后面均加上分号,或者其他单独使用的语句,没有任何区别.例如: for(i=0;i<100; ...

  7. C语言左值,运算符的优先级以及结合性探讨

    刚刚开始看一本书.<C陷阱与缺陷>,相信学习C语言的大家都对这本书有耳闻.今天看到了里面的贪心法则.也即在读到一个字符后,尽可能多的读入更多的字符,直到读入的字符组成的字符串已经不可能再组 ...

  8. 说说C语言运算符的“优先级”与“结合性”

    论坛和博客上常常看到关于C语言中运算符的迷惑,甚至是错误的解读.这样的迷惑或解读大都发生在表达式中存在着较为复杂的副作用时.但从本质上看,仍然是概念理解上的偏差.本文试图通过对三个典型表达式的分析,集 ...

  9. c语言优先级和结合性

    C语言的运算符众多,具有不同的优先级和结合性,我们将它们全部列了出来,方便大家对比和记忆: 优先级 运算符 名称或含义 使用形式 结合方向 说明 1 [] 数组下标 数组名[常量表达式] 左到右   ...

随机推荐

  1. vue.js的一些小语法v-for,v-text,v-html,v-on:click

    1.Vue的目录结构: ======================================================================================== ...

  2. Keepalived安装配置入门

    准备两台虚拟机,IP如下: A:192.168.1.11 B:192.168.1.12 A为Master,B为BackUp 1.安装 yum install keepalived -y 2.配置 A服 ...

  3. Hive的三种Join方式

    Hive的三种Join方式 hive Hive中就是把Map,Reduce的Join拿过来,通过SQL来表示. 参考链接:https://cwiki.apache.org/confluence/dis ...

  4. Java高级面试题

    一.基础知识: 1)集合类:List和Set比较,各自的子类比较(ArrayList,Vector,LinkedList:HashSet,TreeSet): 2)HashMap的底层实现,之后会问Co ...

  5. 使用阿里云ECS安装HDFS的小问题

    毕设涉及HDFS,理论看的感觉差不多了,想搭起来测试一下性能来验证以便进行开题报告,万万没想到装HDFS花费了许多天,踩了许多坑,记录一下. 背景:使用两台阿里云学生机ECS,分处不同账号不同区域,一 ...

  6. UIAutomation学习入门

    一.界面的自动化操作 .Ui自动化测试 .软件外挂 二.Win32基础知识 a.Win32中一切元素皆窗口,窗口之间有父子关系.整个桌面是一个“根窗口”. b.进程: 根据进程id拿到进程对象Proc ...

  7. 修饰器Decorator

    类的修饰 许多面向对象的语言都有修饰器(Decorator)函数,用来修改类的行为.目前,有一个提案将这项功能,引入了 ECMAScript. @testable class MyTestableCl ...

  8. spring mvc: 多解析器映射(资源绑定视图解析器 + 内部资源[普通模式/]视图解析器)

    spring mvc: 多解析器映射(资源绑定视图解析器 + 内部资源[普通模式/]视图解析器) 资源绑定视图解析器 + 内部资源(普通模式)视图解析器 并存方式 内部资源视图解析器: http:// ...

  9. 如何成为 Python 高手

    这篇文章主要是对我收集的一些文章的摘要.因为已经有很多比我有才华的人写出了大量关于如何成为优秀Python程序员的好文章. 我的总结主要集中在四个基本题目上:函数式编程,性能,测试,编码规范.如果一个 ...

  10. UVA-1619 Feel Good (单调队列)

    题目大意:给一个非负整数序列,求出一个使得区间和乘以区间最小值最大的区间. 题目分析:单调队列.维护两个数组,l[i]表示以a[i]为最小值的左半区间的最左边端点,r[i]表示以a[i]为最小值的右半 ...