在一个表达式中可能包含多个有不同运算符连接起来的、具有不同数据类型的数据对象;由于表达式有多种运算,不同的结合顺序可能得出不同结果甚至出现错误运算错误,因为当表达式中含多种运算时,必须按一定顺序进行结合,才能保证运算的合理性和结果的正确性、唯一性。

优先级从上到下依次递减,最上面具有最高的优先级,逗号操作符具有最低的优先级。表达式的结合次序取决于表达式中各种运算符的优先级。优先级高的运算符先结合,优先级低的运算符后结合,同一行中的运算符的优先级相同。

优先级与运算符
优先级

优先级与求值顺序无关。如a+b && bc,虽然优先级最高,但这个表达式求值顺序是从左到右。

优先级从上到下依次递减,最上面具有最高的优先级,逗号操作符具有最低的优先级。

相同优先级中,按结合性进行结合。大多数运算符结合性是从左到右,只有三个优先级是从右至左结合的,它们是单目运算符条件运算符赋值运算符

基本的优先级需要记住:

指针最优,单目运算优于双目运算。如正负号。

先算术运算,后移位运算,最后位运算。请特别注意:1 << 3 + 2 & 7等价于 (1 << (3 + 2))&7.

逻辑运算最后结合。

运算符

运算符是一种特殊的函数,它们具有一个或多个操作数并返回相应的值。操作数是被运算符用作输入的值,通常是字面值、变量或表达式。运算符可以是一元、二元或三元的,一元运算符有1个操作数,二元运算符有2个操作数,三元运算符有3个操作数。

结合性

当一个运算对象两侧的运算符优先级别相同时,则按运算符的结合性来确定表达式的运算顺序。关于结合性的概念在其他高级语言中是没有的,这是C语言的特点之一。在标准C语言的文档里,对操作符的结合性并没有做出非常清楚的解释。一个满分的回答是:它是仲裁者,在几个操作符具有相同的优先级时决定先执行哪一个。C语言也将34种运算符规定了不同的结合性。大多数运算符结合方向是“自左至右”,即:先左后右,也叫“左结合性”,例如 a-b + c,表达式中有-和+两种运算符,且优先级相同,按先左后右结合方向,先围绕减号结合,执行a-b的运算,再围绕加号结合,完成运算(a-b) + c。除了左结合性外,C 语言有三类运算符的结合方向是从右至左,也叫“右结合性”,即:单目运算符、条件运算符、以及赋值运算符。着重强调一点,无论是左结合性,还是右结合性,是针对两个相邻的优先级相同的运行符而言(不是表达中的运算对象),运算符是决定左右的基准点,先以前面的运算符(即位置上处于左边的运算符)构造运算,就是左结合,反之,就是右结合 [3] 。

C 运算符优先级列表:
优先级运算符名称或含义使用形式结合方向说明
1[]数组下标数组名[整型表达式]左到右
()圆括号(表达式)/函数名(形参表)
.成员选择(对象)对象.成员名
->成员选择(指针)对象指针->成员名
2-负号运算符-算术类型表达式右到左单目运算符
(type)强制类型转换(纯量数据类型)纯量表达式
++自增运算符++纯量类型可修改左值表达式单目运算符
--自减运算符--纯量类型可修改左值表达式单目运算符
*取值运算符*指针类型表达式单目运算符
&取地址运算符&表达式单目运算符
!逻辑非运算符!纯量类型表达式单目运算符
~按位取反运算符~整型表达式单目运算符
sizeof长度运算符sizeof 表达式sizeof(类型)
3/表达式/表达式左到右双目运算符
*表达式*表达式双目运算符
%余数(取模)整型表达式%整型表达式双目运算符
4+表达式+表达式左到右双目运算符
-表达式-表达式双目运算符
5<<左移整型表达式<<整型表达式左到右双目运算符
>>右移整型表达式>>整型表达式双目运算符
6>大于表达式>表达式左到右双目运算符
>=大于等于表达式>=表达式双目运算符
<小于表达式<表达式双目运算符
<=小于等于表达式<=表达式双目运算符
7==等于表达式==表达式左到右双目运算符
!=不等于表达式!= 表达式双目运算符
8&按位与整型表达式&整型表达式左到右双目运算符
9^按位异或整型表达式^整型表达式左到右双目运算符
10|按位或整型表达式|整型表达式左到右双目运算符
11&&逻辑与表达式&&表达式左到右双目运算符
12||逻辑或表达式||表达式左到右双目运算符
13?:条件运算符表达式1? 表达式2: 表达式3右到左三目运算符
14=赋值运算符可修改左值表达式=表达式右到左
/=除后赋值可修改左值表达式/=表达式
*=乘后赋值可修改左值表达式*=表达式
%=取模后赋值可修改左值表达式%=表达式
+=加后赋值可修改左值表达式+=表达式
-=减后赋值可修改左值表达式-=表达式
<<=左移后赋值可修改左值表达式<<=表达式
>>=右移后赋值可修改左值表达式>>=表达式
&=按位与后赋值可修改左值表达式&=表达式
^=按位异或后赋值可修改左值表达式^=表达式
|=按位或后赋值可修改左值表达式|=表达式
15,逗号运算符表达式,表达式,…左到右从左向右顺序结合

说明:

同一优先级的运算符,结合次序由结合方向所决定。

简单记就是:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符

C++ 运算符优先级列表:
运算符描述例子可重载性
第一级别
::作用域解析符Class::age = 2;不可重载
第二级别
()函数调用isdigit('1')可重载
()成员初始化c_tor(int x, int y) : _x(x), _y(y*10){};可重载
[]数组数据获取array[4] = 2;可重载
->指针型成员调用ptr->age = 34;可重载
.对象型成员调用obj.age = 34;不可重载
++后自增运算符for( int i = 0; i < 10; i++ ) cout << i;可重载
--后自减运算符for( int i = 10; i > 0; i-- ) cout << i;可重载
const_cast特殊属性转换const_cast<type_to>(type_from);不可重载
dynamic_cast特殊属性转换dynamic_cast<type_to>(type_from);不可重载
static_cast特殊属性转换static_cast<type_to>(type_from);不可重载
reinterpret_cast特殊属性转换reinterpret_cast<type_to>(type_from);不可重载
typeid对象类型符cout « typeid(var).name();cout « typeid(type).name();不可重载
第三级别(具有右结合性)
!逻辑取反if( !done ) …可重载
not! 的另一种表达
~按位取反flags = ~flags;可重载
compl~的另一种表达
++预自增运算符for( i = 0; i < 10; ++i ) cout << i;可重载
--预自减运算符for( i = 10; i > 0; --i ) cout << i;可重载
-负号int i = -1;可重载
+正号int i = +1;可重载
*指针取值int data = *intPtr;可重载
&值取指针int *intPtr = &data;可重载
new动态元素内存分配long *pVar = new long;MyClass *ptr = new MyClass(args);可重载
new []动态数组内存分配long *array = new long[n];可重载
delete动态析构元素内存delete pVar;可重载
delete []动态析构数组内存delete [] array;可重载
(type)强制类型转换int i = (int) floatNum;可重载
sizeof返回类型内存int size = sizeof floatNum;int size = sizeof(float);不可重载
第四级别
->*类指针成员引用ptr->*var = 24;可重载
.*类对象成员引用obj.*var = 24;不可重载
第五级别
*乘法int i = 2 * 4;可重载
/除法float f = 10.0 / 3.0;可重载
%取余数(模运算)int rem = 4 % 3;可重载
第六级别
+加法int i = 2 + 3;可重载
-减法int i = 5 - 1;可重载
第七级别
<<位左移int flags = 33 << 1;可重载
>>位右移int flags = 33 >> 1;可重载
第八级别
<小于if( i < 42 ) …可重载
<=小于等于if( i <= 42 ) ...可重载
>大于if( i > 42 ) …可重载
>=大于等于if( i >= 42 ) ...可重载
第九级别
==恒等于if( i == 42 ) ...可重载
eq== 的另一种表达
!=不等于if( i != 42 ) …可重载
not_eq!=的另一种表达
第十级别
&位且运算flags = flags & 42;可重载
bitand&的另一种表达
第十一级别
^位异或运算flags = flags ^ 42;可重载
xor^的另一种表达
第十二级别
|位或运算flags = flags | 42;可重载
bitor|的另一种表达
第十三级别
&&逻辑且运算if( conditionA && conditionB ) …可重载
and&&的另一种表达
第十四级别
||逻辑或运算if( conditionA || conditionB ) ...可重载
or||的另一种表达
第十五级别(具有右结合性)
? :条件运算符int i = (a > b) ? a : b;不可重载
第十六级别(具有右结合性)
=赋值int a = b;可重载
+=加赋值运算a += 3;可重载
-=减赋值运算b -= 4;可重载
*=乘赋值运算a *= 5;可重载
/=除赋值运算a /= 2;可重载
%=模赋值运算a %= 3;可重载
&=位且赋值运算flags &= new_flags;可重载
and_eq&= 的另一种表达
^=位异或赋值运算flags ^= new_flags;可重载
xor_eq^=的另一种表达
|=位或赋值运算flags |= new_flags;可重载
or_eq|=的另一种表达
<<=位左移赋值运算flags <<= 2;可重载
>>=位右移赋值运算flags >>= 2;可重载
第十七级别
throw异常抛出throw EClass(“Message”);不可重载
第十八级别
,逗号分隔符for( i = 0, j = 0; i < 10; i++, j++ ) …可重载
Java 运算符优先级列表:
运算符结合性
[ ] . ( ) (方法调用)从左向右
! ~ ++ -- +(一元运算) -(一元运算)从右向左
* / %从左向右
+ -从左向右
<< >> >>>从左向右
< <= > >= instanceof从左向右
== !=从左向右
&从左向右
^从左向右
|从左向右
&&从左向右
||从左向右
?:从右向左
=从右向左

一个特殊的例子:

public class stlye

{

public static void main(String[] args)

{   int a=10,b=6;   System.out.println("改变之前的数:a="+a+",b="+b);   a-=b++;   System.out.println("改变之后的数:a="+a+",b="+b);

}

}

运算结果为:

改变之前的数:a=10,b=6

改变之后的数:a=4,b=7

因为b++运算中先执行++,再返回后置++运算表达式(b++)的返回值(6)给-=运算符。

在这个程序中a-=b++等于a=a-b++=10-6,所以a=4。