4

Why the ternary operator does not have blocks? In other words, why the following code does not work and reports error for {} braces?

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

EDIT

Perhaps the question is misunderstood. It was: why blocks are not supported? Why only single expression?

Why this is not allowed to work?

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

One reason could be that ternary are often used for conditional assignment on left side and blocks will have no such returns or it will get confusing with multiple statements inside block.

Yu Hao
  • 115,525
  • 42
  • 225
  • 281
Naveen
  • 7,457
  • 11
  • 71
  • 150
  • Because there is a need to return a value. But GCC can like this `(i==1)?({printf("Hello\n");}:({printf("World\n");});` – BLUEPIXY Jul 08 '15 at 18:31
  • 2
    If your intention is to use multiple statements, you can use function calls in ternary operators – Mayukh Sarkar Jul 08 '15 at 18:35
  • 1
    Because this is a terrible use of the ternary operator. – Billy ONeal Jul 08 '15 at 18:39
  • 1
    I think the compiler only allows one expression may be because of two reason.. 1. It understands it as a boolean or 1/0 expression & multiple statement may hamper that 2. It is not good for readability..for this we have if-else which is more readable I guess – Mayukh Sarkar Jul 08 '15 at 18:44
  • @BLUEPIXY, my gcc compiler did not like the posted code nor your example line. amongst other things, this warning: "... ISO C forbids braced-groups within expressions [-Wpedantic]" – user3629249 Jul 08 '15 at 18:46

8 Answers8

10

To quote C11 standard, chapter §6.5.15, the syntax of the conditional operator is

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

Where, the second and third operands are expression, not statements.

Just to elaborate,

One of the following shall hold for the second and third operands:
— both operands have arithmetic type;
— both operands have the same structure or union type;
— both operands have void type;
— both operands are pointers to qualified or unqualified versions of compatible types;
— one operand is a pointer and the other is a null pointer constant; or
— one operand is a pointer to an object type and the other is a pointer to a qualified or unqualified version of void.


Edit:

To answer the question

Why only single expression?

again, quoting the standard,

....the result is the value of the second or third operand (whichever is evaluated), converted to the type described below.

Block of statements, will not give a value. The evaluation of an expression can.

Sourav Ghosh
  • 130,437
  • 16
  • 177
  • 247
4

The ternary operator consists of expressions. There is no such a kind of expression that uses braces.

You can write simply

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

It semss that the only case when braces can be present in an expression is the use of a compound literal. For example

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 }; 

As for this statement

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

then it can be rewritten the following way using the comma operator

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

Or even like

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

Shortly answering your question if you need a code block then use the if-else statement instead of the ternary operator. Though the if-else statement may not be used in expressions. On the other hand it is desirable for readeability of the code that expressions would not be too compound.

As any operator the ternary operator is used in expressions and returns some evaluated value. For example as an expression it can be used as initializer or in assignments.

Vlad from Moscow
  • 265,791
  • 20
  • 170
  • 303
3

The ternary operator expects an expression for each part, and {...} is not an expression, but a statement.

To expand on your edit, the result of a ternary operator is an expression (but not an lvalue as you suggest), and statement blocks can't evaluate to a value.

For example, this doesn't make sense:

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

But you could do this:

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

In which case, the comma operator would cause the last value in each subexpression to be returned.

dbush
  • 186,650
  • 20
  • 189
  • 240
  • *last value in each subexpression to be returned*? But I am getting `Hello World` and not `World World`. Did I understand incorrectly? – Naveen Jul 08 '15 at 18:47
  • @InsaneCoder notice the second "operand", as `x` will be TRUE. – Sourav Ghosh Jul 08 '15 at 18:49
  • Because the conditional part of the ternary operator is true, only the second part is evaluated. So `printf("Hello\n")` and `printf("World\n")` are both run, and the return value of the latter will be assigned to `x`. – dbush Jul 08 '15 at 18:49
2

Operators in C language can only be used in expressions. There's no such thing as "block" in an expression. In C language blocks are elements of higher-level syntactic structure. Blocks exists at the level of statements. Expression can be used in a statement. But statement cannot become an expression (or be used inside an expression).

Your particular example can be rewritten in terms of expressions

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

without any need for {}.

(See Uses of C comma operator for extra information)

Community
  • 1
  • 1
AnT
  • 302,239
  • 39
  • 506
  • 752
0

Yes only one expression is possible in ternary operators..You have to use if-else for multiple statements. Ternary operators takes one expression only in each slot although you can call two different functions in ternary operator

#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;
}
Mayukh Sarkar
  • 1,823
  • 1
  • 13
  • 34
  • 1
    There is actually _no_ statement at all allowed. As you already wrote, there are only _expressions_ allowed. Simple reason: it is an operator, thus it is also "just" an expression. – too honest for this site Jul 08 '15 at 18:31
0

The ternary operator is not meant to be used as a control structure, meaning it's not meant to control execution of statements. It's simply a way to choose which of two or more expressions will be evaluated.

As Sourav Ghosh has shown, the syntax of a conditional expression simply does not allow the operands of the ?: operator to be statements.

John Bode
  • 113,266
  • 18
  • 112
  • 190
0

This is not allowed because it makes no sense. The ternary operator is meant to return a value. What would that be for {} blocks? And then also there is another construct if () { } else { } that already serves the same purpose that you are trying to give to ? :. Doesn't this here look much nicer than the code that you posted?

int main(void)
{
    int i = 1;
    if (i==1) {
       printf("Hello\n");
       printf("World\n");
    } else {
       printf("Bye\n");
       printf("World\n");
    };
    return 0;
}
Jens Gustedt
  • 74,635
  • 5
  • 99
  • 170
0

As others have noted, GCC allows statements to be used syntactically as expressions, but such a feature is not part of the C standard. Historically, the reason for this likely had to do with the fact that statements are allowed to declare variables, and many systems use the same stack to hold local variables and parameters as is used to hold temporary values used in expression evaluation. Allowing new variables to come into existence within the execution of a statement while still keeping old variables in view would add some complexity to the compiler [note that when a function is called within a new expression, new variables are created for that function, but the old values will be "out of view" until the called function returns and the new variables are destroyed].

That having been said, other features of C such as variable-length arrays require far more complexity than would the ability to embed statements in expressions, so the arguments in favor of that design are no longer as compelling as they were in the 1970s. Unfortunately, the fact that something was once a compelling reason not to include a feature in a language may cause it to forevermore be perceived that way, even if design considerations for today's compilers are nothing like those of the 1970s.

supercat
  • 73,377
  • 7
  • 157
  • 198