c++ 中 `++i` 与 `i++` 在运算表达式中的优先级
来源:互联网 发布:淘宝客服是怎么做的 编辑:程序博客网 时间:2024/06/06 13:56
在算术表达式中,优先级高的运算符先运算,优先级低的运算符后运算,不同的优先级直接影响表达式的计算结果。
1. 说明
gcc中
gcc中的加法运算表达式中,是按照从左到右
按顺序,如果运算符两边有++i操作数,就先进行++i
操作,然后进行加法运算;vs中
vs中的加法运算表达式中,则不一样,只要表达式中有++i
操作数,就要先计算
,最后才是进行加法运算。
加法运算可以扩展到减法、乘法、除法运算和前置–、后置–。但是如果是四则混合运算还要考虑加、减、乘、除的优先级问题。
2. 实例1
计算如下表达式的值:
int i = 3, j = 0;j = (i++) + (i++) + (++i);cout << "i = " << i << endl; cout << "j = " << j << endl;
结果:
gcc
i = 6
j = 10vs2012
i = 6
j = 12
计算过程:
gcc
- 从左到右:fun = (i++) + (i++) = 3 + 3 = 6
- j = fun + (++i),表达式中有(++i)
- 先计算(++i): i = 4
- j = fun + i = fun + 4 = 10
- 计算左边(i++): i = 5
- 计算中间(i++): i = 6
vs2012
- 表达式中有(++i),先计算 :i = 4
- 从左到右:fun = (i++) + (i++) = i + i = 4 + 4 = 8
- j = fun + i = 8 + 4 = 12
- 计算左边(i++): i = 5
- 计算中间(i++): i = 6
3. 实例2
计算如下表达式的值:
int i = 3, j = 0;j = (++i) + (++i) + (++i);cout << "i = " << i << endl;cout << "j = " << j << endl;
结果:
gcc
i = 6
j = 16vs2012
i = 6
j = 18
计算过程:
gcc
- 从左到右:fun = (++i) + (++i)
- 先计算左侧(++i):i = 4
- 再计算右侧(++i):i = 5
- 然后计算 :fun = i + i = 5 + 5 = 10
- j = fun + (++i),
- 先计算右边(++i): i = 6
- 然后计算 :j = fun + i = 10 + 6 = 16
- 从左到右:fun = (++i) + (++i)
vs2012
- 表达式中有(++i),先计算
- 先计算左侧(++i):i = 4
- 再计算中间(++i):i = 5
- 先计算右边(++i): i = 6
- 从左到右:fun = i + i = 6 + 6 = 12
- j = fun + i = 12 + 6 = 18
- 表达式中有(++i),先计算
4. 实例3
计算如下表达式的值:
int i = 3, j = 0;j = (++i) + (++i) + (++i) + (++i);cout << "i = " << i << endl;cout << "j = " << j << endl;
结果:
gcc
i = 7
j = 23vs2012
i = 7
j = 28
计算过程与实例 1 和实例 2 类似,就不再推导。
5. 理解
为什么同是 c++,同样的代码在 gcc 下和 vs 下的结果会不一样呢?下面,先从几个概念说起:
表达式的副作用
- 含义:表达式在求值过程中要改变该表达式中作为操作数的某个变量的值。
- 原因:表达式中包含了具有副作用的操作符,这样的操作符包括:赋值操作符、复合赋值操作符、增1减1操作符。如:
j = (i++) + i + (i++)
。
顺序点
- 含义:也称作序列点,是计算机程序中一些执行点,在该点处之前的求值的所有的副作用已经发生,在它之后的求值的所有副作用仍未开始
- 例子:
for(int i = 0; i < N; y = i++)
中的两个分号就是顺序点,把int i = 0
,i < N
,y = i++
分开。
c++ 标准只保证,在一个顺序点处,求值和副作用全部完成,然后才能进入下面的部份,但是在两个顺序点直接,副作用的顺序并没有规定。所以在多个副作用同时存在的情况下,不同的编译器会有不同的执行顺序。
实际工作中,完全可以通过引入中间变量,避开“顺序点”这样容易出错,也极大地降低代码可读性的“边缘概念”。
6. c 与 c++ 顺序点出现的位置
- && (逻辑与)、 || (逻辑或)、逗号操作符的左操作数与右操作数求值之间(前两者是短路求值的一部分)。例如,表达式*p++ != 0 && *q++ != 0,子表达式*p++ != 0的副作用都会在试图访问q之前完成。
- 三元条件运算符的第一个操作数之后,第二或第三操作数之前。例如,表达式a = (*p++) ? (*p++) : 0在第一个*p++之后存在顺序点,因而在第二个*p++求值之前已经做完一次自增。
- 完整表达式结束处。包括表达式语句(如赋值a=b;),返回语句,if、switch、while、do-while语句的控制表达式,for语句的3个表达式。
- 函数调用时的函数入口点。函数实参的求值顺序未指定,但数序点意味着这些实参求值的副作用在进入函数时都已经完成。表达式f(i++) + g(j++) + h(k++),调用f(), g(), h()的顺序未指定,i, j, k的自增顺序也未指定。函数调用f(a,b,c)的实参列表不是逗号运算符,a, b, and c的求值顺序未指定。
- 函数返回时,在返回值已经复制到调用上下文。(仅C++标准指出这一顺序点)
- 初始化的结束。例如,声明int a = 5;中的对5求值之后。
- 在声明序列的每个声明(declarator)之间。例如,int x = a++, y = a++的两次a++求值之间。注意,此例不是逗号运算符。
7. 参考
参见维基百科
- c++ 中 `++i` 与 `i++` 在运算表达式中的优先级
- C语言优先级和(i++)+(i++)与(++i)+(++i)
- 在C语言中 i++与++i的区别
- i++和i--运算符优先级
- C中的 i++,++i
- (++i)+(++i)+(++i) 与(i++)+(i++)+(i++)表达式
- c,c++语言中 i++ 与 ++i
- C++ i++ 与++i的优先级
- JS中运算符i++与++i的详细分析
- java中的 i++ 与 C中的 i++ 的区别
- java中的 i++ 与 C中的 i++ 的区别
- java中的 i++ 与 C中的 i++ 的区别
- 在c/c++中,i++与++i的区别 (面试时常考的基础题)
- ++i i++ 在C语言和java中的区别
- 运算符优先级在逻辑表达式中的影响程度
- 关于(i++)与(++i)在计算中的讨论
- java中的i++与++i
- java中的i++与++i
- git入门
- Running Maven Defaults and Overriding with TestNG
- C++实现Windows下的Daemon,监控多个进程
- 装修的注意事项
- TraceView工具的使用说明
- c++ 中 `++i` 与 `i++` 在运算表达式中的优先级
- codecombat安息之云山峰11-21关及沙漠38关代码分享
- 【转】c++中vector的用法
- echarts简单实例+ $.extend()方法解析
- 欢迎使用CSDN-markdown编辑器
- UIWebView 小结
- Mat与IplImage*类型间的转换
- 关于百家姓
- Android自定义ListView实现分页加载