Skip to content

Operator Precedence and associativity

记住一些常见的operator precedence和associativity是理解一些expression的前提。

cppreference C++ Operator Precedence

Operators that have the same precedence are bound to their arguments in the direction of their associativity. For example, the expression a = b = c is parsed as a = (b = c), and not as (a = b) = c because of right-to-left associativity of assignment, but a + b - c is parsed (a + b) - c and not a + (b - c) because of left-to-right associativity of addition and subtraction.

NOTE: 同级按照优先级来进行绑定

Unary operators

Associativity specification is redundant for unary operators and is only shown for completeness:

1) unary prefix operators always associate right-to-left (delete ++*p is delete(++(*p)))

2) unary postfix operators always associate left-to-right (a[1][2]++ is ((a[1])[2])++).

Note that the associativity is meaningful for member access operators, even though they are grouped with unary postfix operators: a.b++ is parsed (a.b)++ and not a.(b++).

NOTE: 没有理解

Precedence规律

下面总结的一些规律

Scope resolution Precedence 最高

静态的

创建 temporary 的次之

创建temporary的:

operator 解释
a++ a-- Suffix/postfix increment and decrement 会创建一个temporary
type() type{} Functional cast 会创建一个temporary

需要注意的是: a++ a--排在第二位的原因是: 它的value computation是直接return它自己,这是非常重要的;

Member access的优先级再次之

member access:

operator
a[] Subscript
. -> Member access

Increment/decrement operators 高于 Indirection operator

C++中将Indirection operator归入到了Member access operators中,需要注意的是: Increment/decrement operators 高于 Indirection operator,可以依照前面的"创建 temporary "来进行记忆,因为a++ a--创建temporary,创建temporary的precedence是第二的,所以 Increment/decrement operators 高于 Indirection operator

Relational operatorsLogical operator 的优先级

Relational operatorsLogical operator 相关: Relational operators 的结果类型是bool类型,可以应用于logical operator,本节对它们的precedence进行说明:

precedence operator
3 ! ~ Logical NOT and bitwise NOT
precedence operator
9 < <= For relational operators < and ≤ respectively
> >= For relational operators > and ≥ respectively
10 == != For relational operators = and ≠ respectively
11 & Bitwise AND
12 ^ Bitwise XOR (exclusive or)
13 | Bitwise OR (inclusive or)
14 && Logical AND
15 || Logical OR

这样设计的目的是: 在一定程度上它能够简化我们的expression,在不使用**括号**的情况下能够使用 Logical operator 将多个 logical expression进行连接,比如下面的例子:

1 < 2 && 3 < 4

Assignment operator的优先级倒数第二低

precedence operator
16 a?b:c Ternary conditional[note 2]
throw throw operator
co_yield yield-expression (C++20)
= Direct assignment (provided by default for C++ classes)
+= -= Compound assignment by sum and difference
*= /= %= Compound assignment by product, quotient, and remainder
<<= >>= Compound assignment by bitwise left shift and right shift
&= ^= |= Compound assignment by bitwise AND, XOR, and OR

Precedence of arithmetic operator is higher than the conditional operator

这是cppreference C++ Operator Precedence中给出的:

For example, std::cout << a ? b : c; parses as (std::cout << a) ? b : c; because the precedence of arithmetic left shift is higher than the conditional operator.

Precedence and associativity

从cppreference C++ Operator Precedence给出的图中可以看出,具体相同precedence 的operator是具有相同associativity的。

Operator precedence and operator overload

在cppreference C++ Operator Precedence中对此进行了说明:

Operator precedence is unaffected by operator overloading.

Example

std::cout << a & b

(std::cout << a) & b

*p++

*(p++)

sqlite CSV virtual table

https://sqlite.org/src/file/ext/misc/csv.c

取成员变量的地址: &obj->member->的优先级高于&

static int csvtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
  CsvTable *pTab = (CsvTable*)p;
  CsvCursor *pCur;
  size_t nByte;
  nByte = sizeof(*pCur) + (sizeof(char*)+sizeof(int))*pTab->nCol;
  pCur = sqlite3_malloc64( nByte );
  if( pCur==0 ) return SQLITE_NOMEM;
  memset(pCur, 0, nByte);
  pCur->azVal = (char**)&pCur[1];
  pCur->aLen = (int*)&pCur->azVal[pTab->nCol];
  *ppCursor = &pCur->base;
  if( csv_reader_open(&pCur->rdr, pTab->zFilename, pTab->zData) ){
    csv_xfer_error(pTab, &pCur->rdr);
    return SQLITE_ERROR;
  }
  return SQLITE_OK;
}