1. 问题
练习4.33:根据4.12节中的表(第147页)说明下面这条表达式的含义。
someValue ? ++x, ++y:--x, --y
2. 分析
表达式运算顺序的3个决定因素:运算符的优先级,运算符的结合律,运算对象的求值顺序。
优先级:规定复合表达式中运算符组合的方式
前置递增运算符(++) = 前置递减运算符(–) > 条件运算符(?:) > 逗号运算符(,)
注意:若未明确求值顺序,不同子表达式都使用同一对象,若其中某一表达式修改这个对象,会引发错误产生未定义的行为。如下实例,i和++i并未明确先算哪个。若先算i再算++i则输出0和1,若先算++i再算i则输出1和1,具体结果由编译器决定。一般是先用到的先算,即先输出i++则i=1,再输出i,则i是原先i++执行之后的结果。
#include <iostream>
using namespace std;
int main()
{
int i = 0;
cout << ++i << " " << i << endl;
return 0;
}
结合律:规定具有相同优先级的运算符如何组合在一起
前置递增运算符(++)、前置递减运算符(–):右结合
条件运算符(?:) :右结合
逗号运算符(,):左结合
#include <iostream>
#include <string>
using namespace std;
int main()
{
int grade = 70;
//因为条件运算符是右结合律,故从右向左看。
// grade > 60 ? "良" : "差" 组成一个包含条件运算符的表达式exp
// grade > 90 ? "优" : exp 组成另一个包含条件运算符的表达式
string s1 = (grade > 90 ? "优" : grade > 60 ? "良" : "差");
string s2 = (grade > 90 ? "优" : (grade > 60 ? "良" : "差"));
cout << grade << ":" << s1 << " " << s2 << endl;
//假设条件运算符是左结合律,则从左向右看。
//grade > 90 ? "优" : grade > 60 组成一个包含条件运算符的表达式exp
//expr ? "良" : "差" 组成另一个包含条件运算符的表达式
return 0;
}
求值顺序:
逻辑与运算符(&&):先算左侧表达式,若为假,则直接判断表达式为假,若为真,才会再算右侧表达式推出结果。
逻辑或运算符(||):先算左侧表达式,若为真,则直接判断表达式为真,若为假,才会再算右侧表达式推出结果。
条件运算符(?:):若条件为真,则算冒号左侧表达式,若为假,则算冒号右侧表达式。
逗号运算符(,):先算逗号左侧表达式,将结果丢弃。再算逗号右侧表达式,将结果返回。
其它运算符:未明确求值顺序。
#include <iostream>
using namespace std;
int main()
{
int i = 0;
int i1, i2, i3;
int i4 = (i1 = i, i2 = ++i, i3 = --i);
cout << "i1=" << i1 << endl;
cout << "i2=" << i2 << endl;
cout << "i3=" << i3 << endl;
cout << "i4=" << i4 << endl;
return 0;
}
3. 解答
若someValue =false,x=0,y=0,则程序实际运算过程如下:
#include <iostream>
using namespace std;
int main()
{
bool someValue = false;
int x = 0, y = 0;
//原表达式
someValue ? ++x, ++y : --x, --y;
//添加括号后的表达式
(someValue ? ((++x), (++y)) : (--x)), (--y);
//(++x), (++y), (--x) (--y)虽然优先级高,但它有求值顺序
//故不能一开始就全部计算,使表达式变成(someValue ? (1, 1) : 0), 0;
//应是:先用的先算,未用的不算。
(false ? ((++x), (++y)) : (--x)), (--y);
//条件为false,故选择冒号右侧表达式
(--x), (--y);
//逗号运算符先算左侧表达式,--x计算结果是x=0-1=-1
-1, (--y);
//再算右侧表达式,--y计算结果是y=0-1=-1
-1,-1;
//返回右侧表达式计算结果
-1;
return 0;
}
若someValue =ture,x=0,y=0,则程序实际运算过程如下:
#include <iostream>
using namespace std;
int main()
{
bool someValue = true;
int x = 0, y = 0;
//原表达式
someValue ? ++x, ++y : --x, --y;
添加括号后的表达式
(someValue ? ((++x), (++y)) : (--x)), (--y);
//(++x), (++y), (--x) (--y)虽然优先级高,但它有求值顺序
//故不能一开始就全部计算,使表达式变成(someValue ? (1, 1) : 0), 0;
//应是:先用的先算,未用的不算。
(true ? ((++x), (++y)) : (--x)), (--y);
//条件运算符中条件为true,执行冒号左侧表达式
((++x), (++y)), (--y);
//逗号运算符先执行左侧表达式,++x计算结果是x=0+1=1
(1, (++y)), (--y);
//再执行右侧表达式,++y计算结果是y=0+1=1
(1, 1), (--y);
//返回右侧表达式的计算结果
1, (--y);
//同理,--y计算结果是y=1-0=0
1, 0;
//同理,返回右侧表达式的计算结果
0;
return 0;
}
总的测试程序:
#include <iostream>
using namespace std;
int main()
{
int someValue;
int x, y;
someValue = false, x = 0, y = 0;
int i1 = (someValue ? ++x, ++y : --x, --y);
cout << "someValue=" << someValue << "\tx=" << x << "\ty=" << y << "\ti1=" << i1 << endl;
someValue = true, x = 0, y = 0;
int i2 = (someValue ? ++x, ++y : --x, --y);
cout << "someValue=" << someValue << "\tx=" << x << "\ty=" << y << "\ti2=" << i2 << endl;
//等价于
cout << "--------------------------------------------" << endl;
someValue = false, x = 0, y = 0;
int i3 = ((someValue ? ((++x), (++y)) : (--x)), (--y));
cout << "someValue=" << someValue << "\tx=" << x << "\ty=" << y << "\ti3=" << i3 << endl;
someValue = true, x = 0, y = 0;
int i4 = ((someValue ? ((++x), (++y)) : (--x)), (--y));
cout << "someValue=" << someValue << "\tx=" << x << "\ty=" << y << "\ti4=" << i4 << endl;
}