Dandgerous Ternary Expression


// main.cpp
// Demonstrate the dangerous ternary expression

#include
<iostream>
using namespace std ;

int main()
{
cout
<< (true ? 0, 1 : 0, 2) <<endl ; // Cause a warning
cout << (false ? 0, 1 : 0, 2) <<endl ; // Cause a warning

return 0 ;
}
Warning: (Code Blocks 10.05, g++)

Result:

 
   我们的原意是当 ' expression ? A, a: B, b ' express 为真时执行 A 并且将 a 作为返回值, 否则执行 B 并将 b 作为返回值.
   但是两个 cout 语句的输出都是 2. 为什么呢?
   回头再看 IDE 给我们的警告信息, 第一条是 'warning: left-hand operand of comma has no effect', 这是说逗号表达式左边的操作数无效, 也就是没有产生作用. 这可能造成严重的错误!
   看到这里你应该明白了, 原因是:
cout << (true ? 0, 1 : 0, 2) <<endl ; // 输出 2
       
   划线部分( 'true ? 0, 1, : 0' )当作三元表达式被解释了, 因为逗号表达式的优先级最低. 无论下划线的三元表达式结果如何, ( ... ) 的内容最终的返回值最后一个逗号表达式的结果, 也就是本例中红色加粗体的 2. 也就是说整个的三元表达式都无效!
   正因此, 编译器提示我们逗号表达式左边的三元表达式(下划线部分)无效.
   然而第二个提示 'warning: left-hand operand of comma has no effect' 有事怎么回事呢? 这是因为 蓝色标记的 'true' 导致三元表达式必然会执行 ? 与 : 之间的 '0, 1' 部分, 然而整个的三元表达式都无效, 那么 '0, 1' 中的逗号表达式自然也是无效的, 因此这次 IDE 提示我们逗号表达式右边的操作数( '1' )无效.
   下面的第三,第四条警告同理. 但是为什么第四条提示的还是 'left-hand ... has no effect' 我就不明其理了.
   以上是我在做二叉查找树时为了简约代码而导致错误, 付出了巨大代价换来的一点经验, 希望一:我说明白了, 二:你看明白了, 三:对你今后有做帮助.
   最后, 我建议三元表达式以如下方式书写:
                                     
// Expression ? A : B
int x = true ? 1 : 2 ; // A, B 为单一指令时不加 '()'
int y = true ? (0, 1) : (0, 2) ; // A, B 为多指令时加 '()'
(1 < 2 : x : y) = 0 ; // A, B 作为被操作对象时要在表达式边界加 '()'
cout <<(true ? x : (0, y)) <<endl ; // 遇到 cout 等时最外层加 '()', 否则不能通过编译

   ' ? : ' 表达式优先级低于 '&&, ||, ==, !=' 等, 因此一下语句是错误的:
if (expr1 && expr2 ? true : false) // 错误! 原意是 'expr1 && (expr2 ? true : false)'
   因为上述加粗部分先结合.

    ' ? : ' 表达式优先级等于 '=' 赋值语句, 因此一下语句是错误的:
int a = 1, b = 2 ;
1 < 2 ? a : b = 0 ; // 错误! 这里只有 b 能被赋值为 0
(1 < 2 ? a : b)
= 0 ; // 正确. 由条件控制 a 或 b 被赋值为 0
   因为 '?:' 与 '=' 优先级相同, 且都是右结合性, 因此, 在条件控制被赋值对象的应用中特别需要注意加括号.

   但高于逗号表达式. 且结合性是 right to left. 
posted @ 2011-05-13 14:04  walfud  阅读(876)  评论(0编辑  收藏  举报