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 operators 和 Logical operator 的优先级
Relational operators 和 Logical 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;
}