谜题1.5 关系操作符和条件操作符
请问,下面这个程序的输出是什么?
define PRINT(int) printf(#int " = %d\n",int)
main()
{
int x=1, y=1, z=1;
x += y += z;
PRINT( x < y ? y : x ); (1.5.1)
PRINT( x < y ? x ++ : y ++ );
PRINT(x); PRINT(y); (1.5.2)
PRINT( z += x < y ? x ++ : y ++ );
PRINT(y); PRINT(z); (1.5.3)
x = 3; y = z = 4;
PRINT( (z >= y >= x) ? 1 : 0 ); (1.5.4)
PRINT( z >= y && y >= x ); (1.5.5)
}
输出:
x < y ? y : x = 3 (1.5.1)
x < y ? x ++ : y ++ = 2 (1.5.2)
x = 3
y = 3
z += x < y ? x ++ : y ++ = 4 (1.5.3)
y = 4
z = 4
(z >= y >= x) ? 1 : 0 = 0 (1.5.4)
z >= y && y >= x = 1 (1.5.5)
解惑1.5 关系操作符和条件操作符
1.5.1
初始值:x = 3, y = 2, z = 1
x < y ? y : x
(x < y) ? (y) : (x) 除了涉及三个操作数以外,条件操作符与其他操作符没什么区别。
((x < y) ? (y) : (x))
(FALSE ? (y) : (x)) 先对条件求值,再根据其求值结果对“真”或“假”两个分支之一进行处理——这两种情况不可能同时发生。
((x)) 在这道谜题里,条件的求值结果是FALSE,所以这个条件表达式的值是“假”分支的值。
(3)
3
1.5.2
初始值:x = 3, y= 2, z = 1
x < y ? x++ : y++
((x < y) ? (x++) : (y++))
(FALSE ? (x++) : (y++)) 先对条件求值。
((y++)) 条件的求值结果是FALSE,所以接下来要对“假”分支进行求值。
(2), 此时y=3
2 (请注意:因为x++没有被求值,所以x的值仍是3)
1.5.3
初始值:x = 3, y = 3, z = 1
z += x < y ? x++ : y++
(z += ((x < y) ? (x++) : (y++)))
(z += (FALSE ? (x++) : (y++)))
(z += ((y++))) 条件表达式的结果成为赋值操作符右侧部分的值(右值)。
(z += (3)), 此时y=4
(z = z + 3)
(z = 4)
4
1.5.4
初始值:x = 3, y = 4, z = 4
(z >= y >= x) ? 1 : 0
(((z >= y) >= x) ? (1) : (0))
((TRUE >= x ) ? (1) : (0)) 按从内到外的顺序对条件求值。
((1 >= x) ? (1) : (0)) 最内层的条件的求值结果是TRUE。这个结果将与整数x进行比较。这种比较在C语言里是允许的,因为C语言里的TRUE值其实就是整数1。不过,这种做法并不好——具体到这道谜题,我们想检查z是否比y和x都大,但最终的求值结果显然不符合事实。(谜题1.5.5给出了对三个数值进行比较的正确做法。)
(FALSE ? (1) : (0))
((0))
0
1.5.5
初始值:x = 3, y = 4, z = 4`
z >= y && y >= x
((z >= y) && (y >= x))
(TRUE && (y>=x)) 按从左到右的顺序求值。
(TRUE && TRUE)
(TRUE)
1