运算符是如何工作的

引言

  • 运算符 ( operator ) 作用于操作数 ( operand ),这样就生成了表达式 ( expression )
  • 当没有运算符时,操作数本身也是一个表达式
  • 一个表达式总有一个唯一确定的值,计算机的本质就是计算和存储表达式的值
  • 那么这个值是如何计算呢
    • 只由一个操作数形成的表达式,它的值自然就是操作数本身的值
    • 那么由多个操作数和运算符组成的表达式,它的值又是怎么算出来的呢
    • 这涉及到两个方面
      1. 运算符的优先级和结合性,它解决的是:某个运算符到底跟哪个操作数进行计算的问题
      2. 计算子表达式的先后顺序,它解决的是:形成某个表达式的多个子表达式,到底哪个先计算的问题

各个编程语言都有关于运算符的优先级和结合性的问题,特别是像 C 语言这种运算符特别多的语言,搞清楚各种运算符的优先级和结合性是一个让人头疼的问题。

写这篇文章是为了搞清楚运算符的优先级和结合性的本质。

运算符的优先级和结合性

  • 同一个表达式在同一时间只能跟一个运算符进行计算,比如 a + b * c, b 要么跟 + 算,要么跟 *
  • 所以当同一个表达式左右两边各有一个运算符的时候,到底跟哪个算成了一个问题
  • 当这两个运算符的优先级大小不一样的时候,优先级可以解决表达式跟谁算的问题,比如 * 的优先级比 + 高,那么 a + b * cb 就要跟 * 算,那么也就是 a + (b * c)
  • 当这两个运算符完全一样(如 a + b + c),或者优先级大小一样的时候(如 a * b / c), 就要靠结合性来解决表达式跟谁算的问题。比如 + 是左结合的,那么 a + b + c 也就是 (a + b) + c;又比如 = 是右结合的,那么 x = y = z 也就是 x = (y = z)
  • 具体每个运算符的优先级大小和结合性方式,需要看对应语言的文档,通过查表来解决
  • 一个表达式总是想算出一个结果,得到一个唯一确定的值,计算过程中产生的其他效果都是副作用

计算子表达式的先后顺序

  • 解决了一个表达式怎么分配运算符和操作数的问题后,剩下的事情自然就是计算了,那就有个计算的先后问题
  • 对于 C 语言来说,并非优先级高的就先算,优先级低的就后算。比如 a * b + c - d, a, b, c, d 这 4 个子表达式,先算哪个是不一定的,不一定是先算 a * b, 再算 + c, 最后算 - d
  • 所以这也就是为什么在 C 语言里,不能出现这种表达式:a = (++a * b) / c, 因为 a++a 的计算先后顺序是未定义的,那么你在一个表达式里对同一个变量,对它同时进行改变和赋值的操作,是很危险的,程序的结果是未定义的
  • 对于 JavaScript,ECMAScript 标准规定,表达式永远从左往右进行计算

你可能感兴趣的:(运算符是如何工作的)