1

I've been familiar with the ternary operator for quite some time now, and have worked with it in a few differnet languages. My understanding of the operator is this:

condition ? expr1 : expr2 However, in C++, the following code is legal:

int i = 45;
(i > 0) ? i-- : 1;

Aren't you, in effect, just writing 1; or i - 1;How is this a complete statement? I understand that the intention of the code is to decrement i if it's greater than 0, but I would've thought that the code would generate a compiler error as just being an expression, not a full statement. I expected code like this:

int i = 45;
i = (i > 0) ? i - 1 : i;
Michael
  • 2,673
  • 1
  • 16
  • 27
  • 1
    It's the same reason you can call a non-void function without assigning its result to anything. The language spec doesn't disallow it and the compiler understands it. – M. Shaw Jul 21 '15 at 02:28
  • possible duplicate of [what's an expression and expression statement in c++?](http://stackoverflow.com/questions/7479946/whats-an-expression-and-expression-statement-in-c) – NathanOliver Jul 21 '15 at 02:29

4 Answers4

3

This is called expression statement. The expression is evaluated and its value is discarded.

Even this is valid:

42;

although it does nothing. Only side effects (like i--, assignment, etc) in the expression have effects.


In fact, many statements we use are expression statements: assignments, function calls, etc:

a = 42;
foo();
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • Thanks; didn't know `42;` was legal C++ code. I think I was just used to Java and how it deals with expressions and statements. – Michael Jul 21 '15 at 02:37
1

That is a valid expression. You might have received a warning because you are not saving the result of the expression, but that you have the i-- your statement does have an effect.

Dan Loughney
  • 4,647
  • 3
  • 25
  • 40
1

In C++, an expression like 1 is a perfectly valid statement with no side effects. You could very feasibly write this function:

void f() {
    1;
}

In fact, even this is correct.

void f() {
    ;;;;
}

A literal statement evaluates its arguments but does nothing more. The system views 1; as being just like func();. The only difference is that while func(); would logically have some side effects, 1; does not so it ends up being a no-op. The ternary operator evaluates like an if-statement, so the second form is only evaluated if the operand is true. Thus:

(i > 0) ? i-- : 1;

If i is greater than 0, the second form is evaluated. When it is evaluated, it carries its side effect, which decrements i by 1. Otherwise, the third form is evaluated, which does nothing. Although this block of code works, it is not incredibly readable, so while it's nice toy code a real if-statement is ideal for situations like this. For the same reason, this line would have the same effect but be frowned upon for being equally unreadable.

((i > 0) && (i--)) || 1;

Assuming you didn't overwrite the boolean operators, this code will short-circuit and behave like the ternary operator. If i is not greater than 0, then the && need not evaluate its second operand since the && is false, but the || must since it might be true. Inversely, if i is greater than 0, the && needs to evaluate but the || already knows it's true.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
1

Aren't you, in effect, just writing 1; or i - 1;

No: i-- is not the same as i - 1. In the first case, the value of i is modified. In the second case it is not.

In the event that i less than or equal to zero, then you're correct that the resulting 'code' will be 1. However, the compiler will realise that this is not a useful thing to execute and so it ought to generate code equivalent to:

if( i > 0 ) i--;

Some (including myself) would consider that using the ternary operator in this fashion is bad style. Just for fun, here's another way someone might write it that's also not very nice (also more likely to generate compiler warning):

i > 0 && i--;

In the end, style is a matter of preference. The compiler, for the most part, will decide the best way to turn your code into assembly. So you owe it to yourself to write code that is clear and concise.

paddy
  • 60,864
  • 6
  • 61
  • 103