如果一个表达式包含两个或两个以上的运算符,那么操作数的结合方式将决定这个表达式的结果。为了简便,我们把包含两个或两个以上运算符的表达式称为复合表达式。例如:3 + 2 * 5

如果 3 和 2 结合在一起,那么这个表达式的结果将会是 5 * 5 等于 25。当然,C 语言里,本例的 3 不会和 2 结合,而是 2 和 5 结合,得到 3 + 10 等于 13。

运算符的优先级(precedence)和结合律(associativity)决定操作数的结合方式。当复合表达式中的运算符的优先级不同时,操作数的结合方式由优先级决定。当复合表达式中的运算符的优先级相同时,操作数的结合方式由结合律决定。不过,我们也可以使用括号强制把操作数结合在一起。例如:

(3 + 2) * 5

强制把 3 和 2 结合在一起。

1. 优先级

操作数的结合方式决定复合表达式的值。当复合表达式中的运算符的优先级不同时,操作数的结合方式由优先级决定。操作数总是围绕优先级较高的运算符进行结合。例如:

8.0 + 20.0 / 4.0

因为除法运算符的优先级比加法运算符高,所以 20.0 和 4.0 结合,得到 5.0,然后 8.0 和 5.0 结合,得到 13.0。

2. 结合律

当复合表达式中的运算符的优先级相同时,操作数的结合方式由结合律决定。例如:

8.0 + 20.0 / 4.0 * 2.0

乘法运算符的优先级和除法运算符相同。不过,由于它们的结合率都是从左到右(即从左到右进行结合),所以 20.0 和 4.0 结合;得到的结果 5.0 再和 2.0 结合,得到 10.0;8.0 和 10.0 结合,得到 18.0。

大多数运算符的结合律都是从左到右,不过也有从右到左的(例如赋值运算符)。

3. 使用括号强制结合操作数

使用括号可以强制把操作数结合在一起。被括号括住的个体进行处理,这个个体同样要受到优先级和结合律的约束。例如:

(8.0 + 20.0 / 4.0) * 2.0

强制把 8.0 + 20.0 / 4.0 当成一个个体来处理。因为除法运算符的优先级比加法运算符高,所以 20.0 和4.0 结合,得到 5.0;然后 8.0 和 5.0 结合,得到 13.0;13.0 和 2.0 结合得到 26.0。

-9 + 4 * 5 + 6 + 8 * 7 - 1

根据优先级和结合律,这个表达式的结合方式等同于:

(((((-9)+(4 * 5))+ 6)+(8 * 7))- 1)

由于赋值运算符的结合律是从右到左,所以

i = j = k = l

的结合方式等同于:

(i =(j =(k = l)))

4. 运算顺序

优先级和结合律仅能确定操作数的结合方式,却不能决定操作数的运算顺序。例如:

5 * 3 + 8 * 4

根据优先级和结合律,我们知道,这个表达式的结合方式等同于

(5 * 3) + (8 * 4)  // 5 * 3 和 8 * 4 是 + 的操作数

但是, 到底是先运算 5 * 3 还是先运算 8 * 4,我们并不能确定。它们运算的先后是由编译器决定的。标准不规定操作数的运算顺序是为了让特定系统的编译器选择对该系统来说效率最高的运算顺序。但无论它们的运算先后如何,最终得到的结果都是 47。

下面我们来看一个小程序。

/*--------------------------------------------------------------

| 作者: Antigloss @http://stdcpp.cn@ 蚂蚁的 C/C++ 标准编程

|

| 功能: 演示优先级和结合律对运算结果的影响

-------------------------------------------------------------*/

#include

int main(void)

{

int var1, var2;

var1 = var2 = -(9 + 4) * 5 + (6 + 8 * (7 - 1));

printf("var1 = var2 = %d\n", var1);

return 0;

}

请认真阅读以上程序,想想会出现什么结果,然后编译运行,看看运行结果和您想象的是否一样。

因为优先级和结合律不能决定操作数的运算顺序,所以我们不知道到底是先运算 -(9 + 4) * 5 还是先运算 (6 + 8 * (7 - 1))。它们运算的先后是由编译器决定的。假设先运算 -(9 + 4) * 5,虽然加法运算符的优先级较低,但是括号强制把 9 和 4 结合在一起,得到 13。负号运算符的优先级比乘法运算符高,其作用于 13 得 -13。于是我们得到:

var1 = var2 = -13 * 5 + (6 + 8 * (7 - 1));

由于乘法运算符的优先级比加法运算符高,所以 -13 和 5 结合在一起,得到 -65:

var1 = var2 = -65 + (6 + 8 * (7 - 1));

在 (6 + 8 * (7 - 1)) 中,括号强制把 7 和 1 结合,得 6:

var1 = var2 = -65 + (6 + 8 * 6);

因为* 优先级高于 +,于是我们得到:

var1 = var2 = -65 + (6 + 48);

进而

var1 = var2 = -65 + 54;

var1 = var2 = -11;

因为赋值运算符的结合率是从右到左,所以 -11 被赋值给 var2,接着 var2 被赋值给 var1。最终的结果是,var1 和 var2 相等,它们的值都是 -11。

5. 规定了操作数的运算顺序的运算符

C 语言中,有四个运算符对其操作数的运算顺序做了明确的规定:

&&   ||   ?:   ,

除了这四个运算符以外,其它运算符都没有规定其操作数的运算顺序。

6. C 语言提供的所有运算符

下图列出了 C 语言提供的所有运算符,按优先级从高到低进行排列,优先级相同的运算符放在同一行。

参考资料:C Primer 5th Edition

C99 标准

本文版权归蚂蚁的 C/C++ 标准编程以及 作者antigloss共同所有,转载请注明原作者和出处。谢谢。

c语言赋值运算与除法运算顺序,C语言运算符的优先级和结合律相关推荐

  1. java简单的除法运算_Java除法运算的陷阱

    3.求余:和除法差不多. System.out.println(23%4); System.out.println(23%-4); System.out.println(-23%4); System. ...

  2. 在c语言中下面的运算符中优先级最高的是,C语言习题请高手解答急急急1.下列运算符中优先级最高的运算符 爱问知识人...

    1.下列运算符中优先级最高的运算符是 A:! B: % C:-= D: && 2.下列运算符中优先级最低的运算符是 A:| B:!= C:=Y)&&(Y>=Z) ...

  3. 单片机c语言除法运算,针对小容量单片机程序优化方式--乘除法篇

    原标题:针对小容量单片机程序优化方式--乘除法篇 目前单片机的市场竞争很激烈,许多应用出于性价比的考虑,选择使用程序存储空间较小(如1K,2K)的小资源8位MCU芯片进行开发.一般情况下,这类MCU没 ...

  4. 灵魂拷问:用移位来代替除法运算真的效率高吗?Java 编译器到底有没有做除法优化?

    目录 引入 C++ 编译器对除法的优化 Java 编译器对除法的优化 移位运算对应的字节码 除法操作对应的字节码 查看及分析 JIT 即时编译结果 1.手动编译 OpenJDK 2.编译 hsdis- ...

  5. 【DONET学习笔记】C#与VB.NET除法运算的区别

    我是一名非计算科班出身的小白,爱好编程.从最初的VB.VBA到VB.NET,再到C#数据库等,由于没有扎实的理论基础,踩了很多坑.以下记录下关于除法运算的问题. 一.VB的除法运算 在除法运算方面,V ...

  6. 解析java中的除法运算和取模运算

    解析java中的除法运算和取模运算 A.除法运算 a.含义及其语法 除法运算就是被除数除以除数的这一过程 语法: 被除数/除数 注意:除数不能为0,且被除数和除数都得是数字 b.应用场景 1.和取模运 ...

  7. mysql逻辑运算符的优先顺序_PL/SQL运算符优先级

    运算符优先级决定表达式中术语的分组.这会影响表达式的评估求值顺序.某些运算符的优先级高于其他运算符; 例如,乘法运算符的优先级高于加法运算符. 例如,x = 7 + 3 * 2; 这里,求值结果x的值 ...

  8. [GO语言基础] 四.算术运算、逻辑运算、赋值运算、位运算及编程练习

    作为网络安全初学者,会遇到采用Go语言开发的恶意样本.因此从今天开始从零讲解Golang编程语言,一方面是督促自己不断前行且学习新知识:另一方面是分享与读者,希望大家一起进步.前文介绍了Golang的 ...

  9. c语言for循环除法运算,C语言入门这一篇就够了

    c语言入门 C语言一经出现就以其功能丰富.表达能力强.灵活方便.应用面广等特点迅速在全世界普及和推广.C语言不但执行效率高而且可移植性好,可以用来开发应用软件.驱动.操作系统等.C语言也是其它众多高级 ...

最新文章

  1. (转)Unity Assets目录下的特殊文件夹名称(作用和是否会被打包到build中)
  2. mysql修复坏表的方法
  3. 详解图像直方图均衡化原理,附MATLAB、C、C++源码
  4. 思博伦Landslide CORE帮助UQ实现自动化的现网测试
  5. 使用MONO使.net程序脱离.net框架运行
  6. php通过js发送请求数据,使用原生javascript发送ajax请求数据的步骤
  7. Java 8 的这个新特性,用起来真的很爽!
  8. 791. 高精度加法
  9. linux查看系统版本_Windows电脑如何查看电脑系统位数及版本号
  10. VC下的人人对弈五子棋(dos)
  11. html 怎么调用本地字体,CSS引入本地字体与在线字体
  12. 解决微信公众号accessToken白名单问题
  13. 注册域名dns服务器,dns服务器有什么用?如何用贝锐注册域名?
  14. Ubuntu安装及常用软件安装
  15. window自带的桌面整理工具
  16. 美国临床营养专家:冬季营养建议
  17. 谷歌高级架构师十年心血终成Kubernetes微服务实战文档
  18. 填坑之路——使用阿里云OSS上传文件
  19. 将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的“a“改为“b“(封装成一个方法)
  20. 关于爱情 懂得珍惜就好!

热门文章

  1. 计算机基础知识制图,计算机绘图基础
  2. gpio控制和相关操作
  3. Party Lemonade
  4. java 构造方法能被继承吗_Java中构造函数可以被继承么
  5. Java技术——Interface与abstract类的区别
  6. 导入Excel时数据类型处理工具类
  7. html表格图片右对齐,更好的方式在HTML表格中右对齐文本
  8. 冯诺依曼计算机体系结构
  9. numeric比较大小 数据库_数据库基础知识个人整理版-强烈推荐
  10. win10 屏幕切换鼠标手势桌面边缘快捷切换 ahk