C语言中的条件运算符

4

每个if...then...else语句都可以转换为只使用?:的等效语句吗?

3个回答

7

代码:

if ( flag ) {
   exit(1);
}
else {
   return 0;
}

无法转换为:

flag ? exit(1) : return 0;

更好的例子 - 这将在循环内部:

if ( flag ) {
   continue;
}
else {
   break;
}

不能转换为:

flag ? continue : break;

你可以使用return (flag ? exit(1), 1 : 0),但那只是丑陋的写法。 - outis
@Pavel Radzivilovsky 请看这里:http://codepad.org/YU33Orwj只有当我们将void赋值给某个变量时,它才不起作用,否则它完美运行。 - Vitaly Dyatlov
我本以为我想出了一个能让答案变成“是”的方法;然后看了你的例子!最后我的建议是要适当地使用这些结构,而不是曲解地使用——这样会使问题变得无关紧要。 - Clifford

3

尽管我能想到的任何对于三元运算符的使用都可以用if/else实现,但反过来不成立;至少不是没有采用奇怪和毫无意义的“技巧”,这些技巧在性能、可读性或可维护性方面都没有好处。

if/else的语法为:

if( <boolean expression> )
    <statment>|<statment block>
else
    <statment>|<statment block>

三目运算符的语法如下:

<boolean expression> ? <expression> : <expression> ;

这里的重点是<expression><statement>是不同的语法元素。
这种形式的使用非常有限:
if( b ) x = y else x = z ;

可以实现为:

x = b ? y : x ;

但是这里的限制是在true和false子句中都分配了相同的变量,(因此y和z至少可转换为x的类型)。因此可以说任何条件赋值都可以使用三元运算符来实现(毕竟这是它的主要目的)。
现在,由于函数调用是一个有效的表达式,您可以将真和假子句包装在单独的函数中,但这样做只是为了证明一点而已。
if( b )
    true_stuff() ;
else
    false_stuff() ;

相当于:

b ? true_stuff() : false_stuff() ;

这些函数可以包含任何代码。

因此,为了将更一般的if/else案例转换为?:操作,必须首先将真/假语句块包装在单独的函数中。但即使是这样,Neil Butterworth的示例也会击败这种方法,因为breakcontinuereturn的行为会影响超出if/else结构范围的控制流(尽管这些也是您想要避免的代码示例!)。如果if/else中存在goto,那么也会打败这种方法。

我认为最终,即使你能够做到,你为什么要这样做呢?


1

不。

条件表达式的两个“分支”必须评估为相同的类型,并且该类型不得为void

例如,您可以这样做:

x > 0 ? printf("Positive!\n") : 0;

因为 printf 返回的是 int。(我只会在代码高尔夫比赛中使用它,实际上,我刚刚用过。)

但你不能这样做:

x > 0 ? exit() : 0;

因为exit返回void(或者实际上根本不返回)。


你不能编写一个返回 int 的函数,该函数调用 exit(0) 然后返回 0 吗?例如:x > 0 ? myExit() : 0;。这将起作用,因此我认为答案实际上是“是的,如果你没有更好的事情可做”。 - IVlad
你可以这样做,但这是没有意义的。而且,如果if/else语句包含大量代码而不仅仅是一个或两个语句,那么这种方法就行不通了。 - Puppy
你关于类型和void的第一个观点只有在尝试分配?:的结果或将其用作参数时才是正确的。至少在MSVC++2008中,你的第二个例子可以编译并运行。 - Clifford
@Clifford:嗯,你说得对。有趣。在这种情况下,0被转换为void吗? - Thomas
它似乎被视为一个空语句。例如,int main(){ 0;}可以编译,但不会为0;语句(或实际上任何其他未分配的常量表达式)生成代码。 - Clifford

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接