为什么三元运算符不支持块?

时间:2015-07-08 18:26:25

标签: c language-lawyer ternary-operator

为什么三元运算符没有块?换句话说,为什么以下代码不起作用并报告{}大括号的错误?

int main()
{
    int i = 1;
    (i==1)?{printf("Hello\n")}:{printf("World\n")};
    return 0;
}

修改

也许这个问题被误解了。原因是:为什么不支持块?为什么只有单一表达?

为什么不允许这样做?

int main()
{
    int i = 1;
    (i==1)?{printf("Hello\n");printf("World\n");}:{printf("Bye\n");printf("World\n");};
    return 0;
}

一个原因可能是三元通常用于左侧的条件赋值,而块将没有这样的返回,或者它会与块内的多个语句混淆。

8 个答案:

答案 0 :(得分:9)

引用C11标准,章节§6.5.15,条件运算符的语法是

conditional-expression:
    logical-OR-expression
    logical-OR-expression ? expression : conditional-expression

其中,第二个和第三个操作数是expression,而不是语句。

只是详细说明,

  

以下其中一项适用于第二和第三操作数:
   - 两个操作数都有算术类型;
   - 两个操作数具有相同的结构或联合类型;
   - 两个操作数都有空白类型;
   - 两个操作数都是指向兼容类型的合格或非限定版本的指针;
   - 一个操作数是指针,另一个是空指针常量;或
   - 一个操作数是指向对象类型的指针,另一个是指向限定符号或指针的指针   不合格的版本。

编辑:

回答问题

  

为什么只有单个表达式?

再次引用标准,

  

....结果是第二个或第三个操作数的值(无论哪个被评估),转换为下面描述的类型。

语句块,不会给出。评估expression可以。

答案 1 :(得分:4)

三元运算符由表达式组成。没有这种使用大括号的表达式。

你可以写简单

( i == 1 ) ? printf("Hello\n") : printf("World\n");

认为在表达式中可以出现大括号的唯一情况是使用复合文字。例如

struct A { int x; int y; } a = { 1, 2 };

a = a.x < a.y ? ( struct A ){ a.y, a.x } : ( struct A ){ ++a.x, --a.y }; 

至于这句话

(i==1)?{printf("Hello\n");printf("World\n");}:{printf("Bye\n");printf("World\n");};

然后可以使用逗号运算符

以下列方式重写
i == 1 ? ( printf("Hello\n"), printf("World\n") ) : ( printf("Bye\n"), printf("World\n") );

甚至喜欢

i == 1 ? printf("Hello\n"), printf("World\n") : ( printf("Bye\n"), printf("World\n") );

如果您需要代码块,请尽快回答您的问题,然后使用if-else语句而不是三元运算符。虽然if-else语句可能不会在表达式中使用。另一方面,对于代码的可重用性而言,表达式不会过于复杂是可取的。

作为任何运算符,三元运算符用于表达式并返回一些评估值。例如,作为表达式,它可以用作初始化程序或分配。

答案 2 :(得分:3)

三元运算符期望每个部分都有表达式{...}不是表达式,而是语句。

要扩展您的编辑,三元运算符的结果是一个表达式(但不是您建议的左值),并且语句块无法计算为值。

例如,这没有意义:

int x = (i==1)?{printf("Hello\n");printf("World\n");}:{printf("Bye\n");printf("World\n");};

但你可以这样做:

int x = (i==1)?(printf("Hello\n"), printf("World\n")):(printf("Bye\n"), printf("World\n"));

在这种情况下,逗号运算符将导致返回每个子表达式中的最后一个值。

答案 3 :(得分:2)

C语言中的

运算符只能在表达式中使用。表达式中没有“阻塞”这样的东西。在C语言中, blocks 是更高级句法结构的元素。块存在于语句的级别。表达式可以在语句中使用。但语句不能成为表达式(或在表达式中使用)。

您的特定示例可以根据表达式重写

i == 1 ?
  printf("Hello\n"), printf("World\n") :
  printf("Bye\n"), printf("World\n");

无需{}

(有关额外信息,请参阅Uses of C comma operator

答案 4 :(得分:0)

是的,三元运算符中只能有一个表达式。您必须对多个语句使用if-else。三元运算符仅在每个槽中使用一个表达式 虽然你可以在三元运算符中调用两个不同的函数

#include <stdio.h>

void a(){
 printf("Hello\n");
 printf("Hi\n");

}

void b(){
  printf("Hi\n");
  printf("Hello\n");
}

int main()
 {
int i = 1;
(i == 1) ? a() : b();
return 0;
}

答案 5 :(得分:0)

三元运算符并不打算用作控制结构,这意味着它并不意味着控制语句的执行。这只是一种选择评估两个或更多表达式中哪一个的方法。

正如Sourav Ghosh所示,条件表达式的语法不允许?:运算符的操作数为语句。

答案 6 :(得分:0)

这是不允许的,因为它没有任何意义。三元运算符旨在返回一个值。那{}块会是什么? 然后还有另一个构造if () { } else { }已经达到了你试图给? :的目的。这不是比你发布的代码好看吗?

int main(void)
{
    int i = 1;
    if (i==1) {
       printf("Hello\n");
       printf("World\n");
    } else {
       printf("Bye\n");
       printf("World\n");
    };
    return 0;
}

答案 7 :(得分:0)

正如其他人所说,GCC允许语句在语法上用作表达式,但这样的特性不是C标准的一部分。从历史上看,其原因可能与允许语句声明变量的事实有关,并且许多系统使用相同的堆栈来保存局部变量和参数,就像用于保存表达式求值中使用的临时值一样。允许新变量在语句执行中存在同时仍然保留旧变量会给编译器增加一些复杂性[注意,当在新表达式中调用函数时,会为该函数创建新变量,但是旧的价值观将会超出视野范围。直到被调用函数返回并且新变量被销毁]。

话虽如此,C语言的其他特性(如变长数组)需要比在表达式中嵌入语句的能力复杂得多,因此支持该设计的论据不再像在20世纪70年代。不幸的是,事实上某些东西曾经是一个令人信服的理由,不会在某种语言中包含一个特征,这可能会使它永远被这种方式所感知,即使今天的编译器的设计考虑与20世纪70年代的设计考虑不同。