一、结合性与优先性
1.文中指出:
首先,在多数情况下,C语言对表达式中各子表达式的求值次序并没有严格规定;其次,即使是求值次序确定的场合,也是要先确定了表达式的语义结构,在获得确定的语义之后才谈得上“求值次序”。
条件运算符是C语言中为数不多的对求值次序有明确规定的运算符之一。(另外还有三位,分别是逻辑与“&&”、逻辑或“||”和逗号运算符“,”)。
例如,x > y ? 100 : ++y > 2 ? 20 : 30。
条件运算符“向右结合”这一特性,并没有决定内层的条件表达式先被求值,而是决定了上面表达式的语义结构等价于“x > y ? 100 : (++y > 2 ? 20 : 30)”,而不是等价于“(x > y ? 100 : ++y) > 2 ? 20 : 30”。——这才是“向右结合”的真正含义。
C语言规定:条件表达式首先对条件部分求值,若条件部分为真,则对问号之后冒号之前的部分求值,并将求得的结果作为整个表达式的结果值,否则对冒号之后的部分求值并作为结果值。
因此,对于表达式“x > y ? 100 : (++y > 2 ? 20 : 30)”,首先看x大于y是否成立,在本例中它是成立的,因此整个表达式的值即为100。也因此冒号之后的部分得不到求值机会,它的所有副作用也就没机会生效。
2.案例运行
![](https://img2023.cnblogs.com/blog/2177087/202311/2177087-20231118001431515-1073862588.png)
这里可以看出条件表达式出现了像&&与||逻辑表达式一样的短路。
二、题目
int i = -2;
int n = ++i == 0 ? 99 : i == -1 ? 11 : 22;
请问n的值是多少?
答:n = 11!
![](https://img2023.cnblogs.com/blog/2177087/202311/2177087-20231117143714789-1446903392.png)
why?
首先,先确定语义结构,由于条件运算符其右结合,因此意义为n=++i==0?99:(i==-1?11:22);
其次就是对外层关系运算符判断,++i==0的值,如果是真,就对表达式的值就为99,否则进行后面的运算,
接着,由于优先级,先进行++i操作再判断++i==0,而++i返回的是i+1的值(这个后续有原理的基本解释),因此外层关系运算结果为假,取后面条件表达式
然后,i==-1取11,所以最后结果为11
三、关于++i与i++的变式
1.截取里面的一点内容,关于i++与++i的原理实现
int i;
int firstAdd() {
i = i + 1;
return i;
}
int lastAdd() {
int temp = i;
i = i + 1;
return temp;
}
int main() {
i = 0;
i = firstAdd();//i=++i
printf("%d\n", i);
i = 0;
i = lastAdd();//i=i++
printf("%d", i);
return 0;
}
2.运行i++==0
结果如下:
![](https://img2023.cnblogs.com/blog/2177087/202311/2177087-20231117145512071-439148216.png)
3.运行++i==0
结果如下:
![](https://img2023.cnblogs.com/blog/2177087/202311/2177087-20231117145603174-1713316828.png)
4.思考
注意:int i=-1;++i==0;与i++==0;不一样,前者结果为1后者结果为0。
如果i=-1呢?
如果换成n=i++==0?99:i==-1?11:22;呢?
如果换成n=i++==-1?99:i==-1?11:22;呢?