本节书摘来自异步社区《C语言解惑》一书中的第1章,第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 关系操作符和条件操作符
初始值: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
初始值: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)
初始值: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
初始值: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
初始值:x = 3, y = 4, z = 4`
z >= y && y >= x
((z >= y) && (y >= x))
(TRUE && (y>=x)) 按从左到右的顺序求值。
(TRUE && TRUE)
(TRUE)
1