https://zhidao.baidu.com/question/539131588.html
初步划分:
初等运算符(如括号、[ ]、-> .
↓
单目运算符( ++ -- & 等)
↓
算数运算符(+ - * /)
http://c.biancheng.net/view/161.html
C语言运算符
编辑 讨论
C语言运算符是说明特定操作的符号 [1] ,它是构造C语言表达式的工具 [2] 。C语言的运算异常丰富,除了控制语句和输入输出以外的几乎所有的基本操作都为运算符处理。除了常见的三大类,算术运算符、关系运算符与逻辑运算符之外,还有一些用于完成特殊任务的运算符,比如位运算符。
中文名
C语言运算符
外文名
Operators of C programming language
类 别
计算机程序语言
作 用
说明特定操作
目录
- ▪ 赋值运算符 16 级
- ▪ 逗号运算符 17级
- 2 优先级
分类和级别
编辑
C语言的运算符主要用于构成表达式,同一个符号在不同的表达式中,其作用并不一致。下面按计算的优先顺序,分别说明不同作用的表达式。需要特别指出,在C语言标准中,并没有结合性的说法。 [1]
相同优先级运算符,从左至右依次运算。注意后缀运算优先级高于前缀。因此++i++应解释为++(i++)。
而与或非的运算优先级都不一样,因此a && b || b && c解释为(a && b) || (b && c)
合理使用优先级可以极大简化表达式。
基本表达式 1级
基本表达式(Primary expressions),主要是用于运算符之间,做为运算数。
标识,常量,字符串文字量,优先级提升表达式最优先执行。
优先级提升表达式是指圆括号包围的表达式,如“( expression )”
后缀表达式 2级
postfix-expression [ expression ],数组下标运算。
postfix-expression ( argument-expression-list),函数调用,括号内的参数可选。
postfix-expression . identifier,成员访问,
postfix-expression -> identifier,成员访问,->号之前应为指针。
postfix-expression ++,后缀自增
postfix-expression --,后缀自减
( type-name ) { initializer-list }
( type-name ) { initializer-list , } 复合初始化,C99后新增。例如
1 2 3 4 5 6 7 8 9 10 |
|
单目/一元运算 3级
++ unary-expression 前缀自增
-- unary-expression 前缀自减
unary-operator cast-expression 单目转型表达式, 包括 取地址& ,提领 * , 正号+ ,负号- 位反~ 逻辑否!。
sizeof unary-expression 求类型长度,对表达式求类型长度
sizeof ( type-name ) 求类型长度
强制类型表达式 4级
( type-name ) cast-expression,强制表达式成为type-name指定的类型。
乘法表达式 5级
“ * ” 乘法运算符;“ / ”除法运算符;“ % ” 取余运算符。
加法运算符 6级
“ + ”加法运算符;“ - ”减法运算符。
移位运算符 7级
<< 左移运算符;>> 右移运算符。
关系运算符 8级
<、<=、>、>=关系运算符。
相等运算符 9级
“ == ”等于运算符;“ != ”不等于运算符。
位与运算符 10级
“ & ”按位与运算符
位异或运算符 11级
“ ∧ ”按位异或运算符(Bitwise exclusive OR operator)。
位或运算符 12 级
“ | ”按位或运算符(Bitwise inclusive OR operator)。
逻辑与运算符 13级
“&&”逻辑与运算符。
逻辑或运算符 14 级
“ || ”逻辑或运算符。
三元条件运算符 15级
? :条件运算符。
赋值运算符 16 级
=、 +=、 -=、 *=、 /=、 %=、 &=、 ^=、 |=、 <<=、 >>=赋值运算符。
逗号运算符 17级
“,”逗号运算符。
[pre]C 语言中,逗号(,)也可以是运算符,称为逗号运算符(Comma Operator)。逗号运算符可以把两个以上(包含两个)的表达式连接成一个表达式,称为逗号表达式。其一般形式为:
子表达式1, 子表达式2, ..., 子表达式n
例如:
a + b, c = b, c++
逗号运算符的优先级是所有运算符中级别最低的,通常配合 for 循环使用。逗号表达式最右边的子表达式的值即为逗号表达式的值。上例中,c++ 的值(c 自增之前的值)即为该表达式的值。
逗号运算符保证左边的子表达式运算结束后才进行右边的子表达式的运算。也就是说,逗号运算符是一个序列点,其左边所有副作用都结束后,才对其右边的子表达式进行运算。因此,上例中,c 得到 b 的值后,才进行自增运算。
优先级
编辑
优先级:C语言中,运算符的运算优先级共分为15 级。1 级最高,15 级最低。 在表达式中,优先级较高的先于优先级较低的进行运算。而在一个运算量两侧的运算符 优先级相同时,则按运算符的结合性所规定的结合方向处理。
结合性:C语言中各运算符的结合性分为两种,即左结合性(自左至右)和右结合性(自右至左)。例如算术运算符的结合性是自左至右,即先左后右。如有表达式x-y+z 则y 应先与“-”号结合,执行x-y 运算,然后再执行+z 的运算。这种自左至右的结合 方向就称为“左结合性”。而自右至左的结合方向称为“右结合性”。最典型的右结合 性运算符是赋值运算符。如x=y=z,由于“=”的右结合性,应先执行y=z 再执行x=(y=z)运算。C语言运算符中有不少为右结合性,应注意区别,以避免理解错误。
优先级从上到下依次递减,最上面具有最高的优先级,逗号操作符具有最低的优先级。
所有的优先级中,只有三个优先级是从右至左结合的,它们是单目运算符、条件运算符、赋值运算符。其它的都是从左至右结合。
具有最高优先级的其实并不算是真正的运算符,它们算是一类特殊的操作。()是与函数相关,[]与数组相关,而->及.是取结构成员。
其次是单目运算符,所有的单目运算符具有相同的优先级,因此在我认为的 真正的运算符中它们具有最高的优先级,又由于它们都是从右至左结合的,因此*p++与*(p++)等效是毫无疑问的。
另外在C语言里,没有前置后置之分,因为++ -- 是右结合所以右侧优先运算,表现为 "操作数后置优先级比较高" 的假象,前置和后置的区分是因为运算符重载而后加入C++的
接下来是算术运算符,*、/、%的优先级当然比+、-高了。
移位运算符紧随其后。
其次的关系运算符中,< <= > >=要比 == !=高一个级别,不大好理解。
所有的逻辑操作符都具有不同的优先级(单目运算符除外,!和~)
逻辑位操作符的"与"比"或"高,而"异或"则在它们之间。
跟在其后的&&比||高。
在C语言中,只有4个运算符规定了运算方向,它们是&&、| |、条件运算符及赋值运算符。
&&、| |都是先计算左边表达式的值,当左边表达式的值能确定整个表达式的值时,就不再计算右边表达式的值。如 a = 0 && b; &&运算符的左边位0,则右边表达式b就不再判断。
在条件运算符中。如a?b:c;先判断a的值,再根据a的值对b或c之中的一个进行求值。
赋值表达式则规定先对右边的表达式求值,因此使 a = b = c = 6;成为可能。
口诀注释
优先级等级口诀
圆方括号、箭头一句号, 自增自减非反负、针强地址长度,
乘除,加减,再移位,
小等大等、等等不等,
八位与,七位异,六位或,五与,四或,三疑,二赋,一真逗。
其中“,”号为一个等级分段。
优先级等级注释
“圆方括号、箭头一句号”指的是第1级的运算符。其中圆方括号很明显“()、[]”,箭头 指的是指向结构体成员运算符“->”,句号 指的是结构体成员运算符“.” ;
“自增自减非反负、针强地址长度”指的是第2级的运算符。其中 非 指的是逻辑运算符“!”,反 指的是按位取反运算符“~”,负 指的是负号运算符“-”,针 指的是指针运算符“*”,强 指的是强制类型转换运算符,地址 指的是地址运算符“&”,长度 指的是长度运算符“sizeof ”;
“乘除,加减,再移位”移位指的是左移运算符“<<”和右移运算符“>>”,其中除法还包括了 取余运算符“%”;
“小等大等、等等不等” 指的是第6级到第7级的运算符:<、<=、>和>=,等等指的是等于运算符==,不等指的是不等于运算符!=
“八位与,七位异,六位或”其中 八位与 指的是第8级的 按位与 运算符“&”,七位异 指的是第9级的按位异或运算符“^”,六位或 指的是第10级的按位或运算符“|”;
“五与,四或”指的是第11级、第12级的逻辑与运算符“&&”和逻辑或运算符“||”;
“三疑,二赋,一真逗”指的是第13级到第15级的运算符。其中,三疑指的是条件运算符“?:” (三有双重含义:即指优先级别是三,它的运算符类型也是三目,疑也取“?”之意),二赋 指的是赋值运算符=、+=、-=、*=、/=、%=、>>=、<<=、&=、^=和|= ,一真逗 指的是第15级的“,”运算符,真字只是为了语句需要罢了。
由于C语言的运算符优先级与C++的不完全一样(主要是增加了几个运算符),所以这个口诀不能完全实用于C++.但是应该能够兼容,大家可以比较一下他们的区别应该就能够很快掌握C++的优先级的!
应用举例
1、赋值运算符:a=5;
a=b=0;
第一个赋值语句把5赋给变量a;第二个赋值语句的意思是把0同时赋值给两个变量。这是因为赋值语句是从右向左运算的,也就是说从右端开始计算,先b=0,然后a=b。
2、复合赋值运算符:a=1;a+=3;
上面第二个赋值语句等价于a=a+3;即a=4。
3、算术运算符:Area=Height*Width;num=num1+num2/num3-num4;
第一个赋值语句Height和Width相乘结果赋给变量Area;第二个赋值语句先完成num2与num3的整除运算,然后与num1相加,再减去num4,结果赋给num。运算符运算顺序先算乘除再算加减。单目正和单目负最先运算。
4、逻辑运算符:a=1,b=1;
a||b-1;
因为a=1为真值,所以不管b-1是不是真值,总的表达式一定为真值,这时后面的表达式就不会再计算了。
5、关系运算符:if(a>0)...
如果a>0,则执行if语句中的内容,否则退出。
6、条件运算符:a=(b>0)?b:-b;
当b>0时,a=b;当b不大于0时,a=-b;其实上面的意思就是把b的绝对值赋值给a。
7、逗号运算符:b=2,c=7,d=5;
a=(++b,c--,d+3);
有三个表达式,用逗号分开,所以最终的值应该是最后一个表达式的值,也就是d+3=8,所以a=8。
8、位逻辑运算符
包括:1。&位与符 2。|位或符 3。^位异或符 4。~位取反符
以操作数12为例。位运算符将数字12视为1100。位运算符将操作数视为位而不是数值。数值
可以是任意进制的:十进制、八进制或十六进制。位运算符则将操作数转化为二进制,并相应地返回1或0。
位运算符将数字视为二进制值,并按位进行相应运算,运算完成后再重新转换为数字。例如:
表达式10&15表示(1010 & 1111),它将返回表示1010的值10。因为真真得真,或者是11得1,同位全是1结果也是1
表达式10|15表示(1010 | 1111),它将返回表示1111的值15。假假得假。全零得零。
表达式10^15表示(1010 ^ 1111), 它将返回表示0101的值5。此时是同性相斥,相同的就为假。
表达式~10表示(~1010),它将返回表示0101的值 5。此号好理解,按位取反。
C语言运算符优先级和结合性一览表
C语言中文网推出辅导班啦,包括「C语言辅导班、C++辅导班、算法/数据结构辅导班」,全部都是一对一教学:一对一辅导 + 一对一答疑 + 布置作业 + 项目实践 + 永久学习。QQ在线,随时响应!
所谓优先级就是当一个表达式中有多个运算符时,先计算谁,后计算谁。这个其实我们在小学学算术的时候就学过,如1+4÷2
。
但是C语言中的运算符已经远不止四则运算中的加减乘除了,还有其他很多运算符。当它们出现在同一个表达式中时先计算谁后计算谁呢?所以本节还是有必要讲一下的。最后我还会将所有运算符展示出来,然后告诉你哪个优先级高、哪个优先级低。
首先不需要专门记忆,也没有必要。因为作为初学者,哪个优先级高、哪个优先级低我们很难记住。就算死记硬背记住了,时间长不用也会忘记。所以当一个表达式中有多个运算符时,如果不知道哪个优先级高哪个优先级低就查一下优先级表,附录E有一个运算符优先级表。此外用的时间长了自然而然就记住了,这样记才会记得深刻。
而且事实上在编程的时候也不需要考虑优先级的问题。因为如果不知道优先级高低的话,加一个括号就可以了,因为括号( )
的优先级是最高的。比如前面的程序中:
k = (j>i) && (8==i);
根据运算符的优先级,这条语句完全可以写成:
k = j>i && 8==i;
但是第一种写法别人一看就知道先计算谁后计算谁。
而且加圆括号也是一种编程规范,因为程序不只是写给自己看。
此外运算符还有“目”和“结合性”的概念,这个很简单。“目”就是“眼睛”的意思,一个运算符需要几个数就叫“几目”。比如加法运算符+
,要使用这个运算符需要两个数,如 3+2。对+
而言,3 和 2 就像它的两只眼睛,所以这个运算符是双目的。
C语言中大多数的运算符都是双目的,也有单目和三目的。单目运算符比如逻辑非,如!1
,它就只有一只眼睛,所以是单目的。整个C语言中只有一个三目运算符,即条件运算符? :
。这个稍后讲到条件语句的时候再介绍。关于“目”大家了解一下就行了。
那么“结合性”是什么呢?上面讲的优先级都是关于优先级不同的运算符参与运算时先计算谁后计算谁。但是如果运算符的优先级相同,那么先计算谁后计算谁呢?这个就是由“结合性”决定的。
比如1+2×3÷4
,乘和除的优先级相同,但是计算的时候是从左往右,即先计算乘再计算除,所以乘和除的结合性就是从左往右。就是这么简单!
C语言中大多数运算符的结合性都是从左往右,只有三个运算符是从右往左的。一个是单目运算符,另一个是三目运算符,还有一个就是双目运算符中的赋值运算符=
。双目运算符中只有赋值运算符的结合性是从右往左的,其他的都是从左往右。运算符的“结合性”也不要死记,在不断使用中就记住了。
运算符优先级和结合性一览表
优先级 | 运算符 | 名称或含义 | 使用形式 | 结合方向 | 说明 |
---|---|---|---|---|---|
1 | [] | 数组下标 | 数组名[常量表达式] | 左到右 | |
() | 圆括号 | (表达式) | |||
. | 成员选择(对象) | 对象.成员名 | |||
-> | 成员选择(指针) | 对象指针->成员名 | |||
2 | - | 负号运算符 | -表达式 | 右到左 | 单目运算符 |
(类型) | 强制类型转换 | (数据类型)表达式 | |||
++ | 自增运算符 | ++变量名 | 单目运算符 | ||
-- | 自减运算符 | --变量名 | 单目运算符 | ||
* | 取值运算符 | *指针变量 | 单目运算符 | ||
& | 取地址运算符 | &变量名 | 单目运算符 | ||
! | 逻辑非运算符 | !表达式 | 单目运算符 | ||
~ | 按位取反运算符 | ~表达式 | 单目运算符 | ||
sizeof | 长度运算符 | sizeof(表达式) | |||
3 | / | 除 | 表达式 / 表达式 | 左到右 | 双目运算符 |
* | 乘 | 表达式*表达式 | 双目运算符 | ||
% | 余数(取模) | 整型表达式%整型表达式 | 双目运算符 | ||
4 | + | 加 | 表达式+表达式 | 左到右 | 双目运算符 |
- | 减 | 表达式-表达式 | 双目运算符 | ||
5 | << | 左移 | 变量<<表达式 | 左到右 | 双目运算符 |
>> | 右移 | 变量>>表达式 | 双目运算符 | ||
6 | > | 大于 | 表达式>表达式 | 左到右 | 双目运算符 |
>= | 大于等于 | 表达式>=表达式 | 双目运算符 | ||
< | 小于 | 表达式<表达式 | 双目运算符 | ||
<= | 小于等于 | 表达式<=表达式 | 双目运算符 | ||
7 | == | 等于 | 表达式==表达式 | 左到右 | 双目运算符 |
!= | 不等于 | 表达式!= 表达式 | 双目运算符 | ||
8 | & | 按位与 | 表达式&表达式 | 左到右 | 双目运算符 |
9 | ^ | 按位异或 | 表达式^表达式 | 左到右 | 双目运算符 |
10 | | | 按位或 | 表达式|表达式 | 左到右 | 双目运算符 |
11 | && | 逻辑与 | 表达式&&表达式 | 左到右 | 双目运算符 |
12 | || | 逻辑或 | 表达式||表达式 | 左到右 | 双目运算符 |
13 | ?: | 条件运算符 | 表达式1? 表达式2: 表达式3 | 右到左 | 三目运算符 |
14 | = | 赋值运算符 | 变量=表达式 | 右到左 | |
/= | 除后赋值 | 变量/=表达式 | |||
*= | 乘后赋值 | 变量*=表达式 | |||
%= | 取模后赋值 | 变量%=表达式 | |||
+= | 加后赋值 | 变量+=表达式 | |||
-= | 减后赋值 | 变量-=表达式 | |||
<<= | 左移后赋值 | 变量<<=表达式 | |||
>>= | 右移后赋值 | 变量>>=表达式 | |||
&= | 按位与后赋值 | 变量&=表达式 | |||
^= | 按位异或后赋值 | 变量^=表达式 | |||
|= | 按位或后赋值 | 变量|=表达式 | |||
15 | , | 逗号运算符 | 表达式,表达式,… | 左到右 |
|
上表中可以总结出如下规律:
- 结合方向只有三个是从右往左,其余都是从左往右。
- 所有双目运算符中只有赋值运算符的结合方向是从右往左。
- 另外两个从右往左结合的运算符也很好记,因为它们很特殊:一个是单目运算符,一个是三目运算符。
- C语言中有且只有一个三目运算符。
- 逗号运算符的优先级最低,要记住。
- 此外要记住,对于优先级:算术运算符 > 关系运算符 > 逻辑运算符 > 赋值运算符。逻辑运算符中“逻辑非 !”除外。
一些容易出错的优先级问题
上表中,优先级同为1 的几种运算符如果同时出现,那怎么确定表达式的优先级呢?这是很多初学者迷糊的地方。下表就整理了这些容易出错的情况:
优先级问题 | 表达式 | 经常误认为的结果 | 实际结果 |
---|---|---|---|
. 的优先级高于 *(-> 操作符用于消除这个问题) | *p.f | p 所指对象的字段 f,等价于: (*p).f | 对 p 取 f 偏移,作为指针,然后进行解除引用操作,等价于: *(p.f) |
[] 高于 * | int *ap[] | ap 是个指向 int 数组的指针,等价于: int (*ap)[] | ap 是个元素为 int 指针的数组,等价于: int *(ap []) |
函数 () 高于 * | int *fp() | fp 是个函数指针,所指函数返回 int,等价于: int (*fp)() | fp 是个函数,返回 int*,等价于: int* ( fp() ) |
== 和 != 高于位操作 | (val & mask != 0) | (val &mask) != 0 | val & (mask != 0) |
== 和 != 高于赋值符 | c = getchar() != EOF | (c = getchar()) != EOF | c = (getchar() != EOF) |
算术运算符高于位移 运算符 | msb << 4 + lsb | (msb << 4) + lsb | msb << (4 + lsb) |
逗号运算符在所有运 算符中优先级最低 | i = 1, 2 | i = (1,2) | (i = 1), 2 |
这些容易出错的情况,希望读者好好在编译器上调试调试,这样印象会深一些。一定要多调试,光靠看代码,水平是很难提上来的。调试代码才是最长水平的。
运算符优先级
在一个表达式中可能包含多个有不同运算符连接起来的、具有不同数据类型的数据对象;由于表达式有多种运算,不同的结合顺序可能得出不同结果甚至出现错误运算错误,因为当表达式中含多种运算时,必须按一定顺序进行结合,才能保证运算的合理性和结果的正确性、唯一性。
优先级从上到下依次递减,最上面具有最高的优先级,逗号操作符具有最低的优先级。表达式的结合次序取决于表达式中各种运算符的优先级。优先级高的运算符先结合,优先级低的运算符后结合,同一行中的运算符的优先级相同。 [1]
中文名
运算符优先级
外文名
Operator Precedence
结合次序
表达式中各种运算符的优先级
最高优先级
是一类特殊的操作
具有相同的优先级
一元运算符
只须一个操作数就能执行的运算符
目录
- 5 C#
- 6 Visual Basic
优先级
优先级与求值顺序无关。如a+b && b*c,虽然*优先级最高,但这个表达式求值顺序是从左到右。
优先级从上到下依次递减,最上面具有最高的优先级,逗号操作符具有最低的优先级。
相同优先级中,按结合性进行结合。大多数运算符结合性是从左到右,只有三个优先级是从右至左结合的,它们是单目运算符、条件运算符、赋值运算符。
基本的优先级需要记住:
指针最优,单目运算优于双目运算。如正负号。
先算术运算,后移位运算,最后位运算。请特别注意:1 << 3 + 2 & 7等价于 (1 << (3 + 2))&7.
逻辑运算最后结合。
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。
C#
优先级 | 类别 | 运算符 |
1 | 基本 | (x) x.y f(x) a[x] x++ x-- new typeof sizeof checked unchecked |
2 | 单目 | + - ! ~ ++x --x (T)x |
3 | 乘法与除法 | * / % |
4 | 加法与减法 | + - |
5 | 移位运算 | << >> |
6 | 关系运算 | < > <= >= |
7 | 条件等 | == != |
8 | 位逻辑与 | & |
9 | 位逻辑异或 | ^ |
10 | 位逻辑或 | | |
11 | 条件与 | && |
12 | 条件或 | ‖ |
13 | 条件 | ?: |
14 | 赋值 | = |
一个特殊的例子:
class Program
{
static void Main(string[] args)
{
int a; a = 10; int b = 4;
a += b++;
Console.WriteLine("a={0}",a);
Console.WriteLine("b={0}", b);
Console.ReadLine();
}
}
运算结果为:
a=14
b=5
在这个程序中a+=b等于a=a+b=10+4,因为 b++ 时返回了一个临时变量后才进行自增。
Visual Basic
优先级 | 类别 | 运算符 |
1 | 乘方 | ^ |
2 | 取负 | - |
3 | 乘 | * |
3 | 除 | / |
4 | 四舍五入除/位移 | \ |
5 | 取模 | Mod |
6 | 加 | + |
6 | 减 | - |
7 | 字符串合并 | & 或 + |
8 | 相等 | = |
8 | 大于 | > |
8 | 大于等于 | >= |
8 | 小于 | < |
8 | 小于等于 | <= |
8 | 不等于 | <> |
8 | 同类对象 | Is |
8 | Like运算 | Like |
9 | 非 | Not |
10 | 与 | And |
11 | 或 | Or |
12 | 异或 | Xor |
13 | 逻辑等 | Eqv |
14 | 逻辑大于等于(蕴含) | Imp |
参考资料
实践:
#include <stdio.h>
#include <stdlib.h>
void func()
{
if( 1 >= 2 ==
2<=3 ){
printf(" success !!! \n");
}else{
printf(" error success !!! \n");
}
}
int main(int argc, char *argv[])
{
func();
return 0;
}
编译时提示:suggest parentheses around comparison in operand of == (翻译成中文是建议等号两边加括号)
优先级== 低于>=, <=,代码运行正确,但是这样写缺乏可读性.