1

The following code gives the output as : ccb

int t = 0;
char a[] = {'a', 'b', 'c'};
cout<<a[t]<<a[++t]<<a[++t];

I want to know, what actually is happening in this code which generates the specified output. Any help will be appreciated.

Vishal
  • 87
  • 9
  • 2
    The second `++t` is __not__ guaranteed to be evaluated after the first `++t`. – Emil Laine Jul 07 '15 at 16:14
  • @zenith, can you provide a source that states that? – Mox Jul 07 '15 at 16:14
  • 1
    @Mox The C++ standard. There is no _sequence point_ between the two `++t`s so their order of evaluation is unspecified. – Emil Laine Jul 07 '15 at 16:15
  • @zenith, anyway saw the link. thanks for sharing. something new for me =) – Mox Jul 07 '15 at 16:16
  • @zenith I feel like this is not a good dupe. It does not justify why the (overloaded!) `<<` do not introduce sequencing. – Baum mit Augen Jul 07 '15 at 16:16
  • cppreference on order of evaluation: http://en.cppreference.com/w/cpp/language/eval_order – Matt Olson Jul 07 '15 at 16:17
  • 1
    @zenith, there is a sequence point at `cout << a[t]` since that involves a function call. Because of the overloaded << operator, `cout << a[t] << a[++t] << a[++t]` is equivalent to `((cout << a[t]) << a[++t]) << a[++t]`. The output seen by the OP is probably caused by uninitialized value of `t` or accessing `a` out of bounds. – R Sahu Jul 07 '15 at 16:23
  • @RSahu Clang gives the following warning: "unsequenced modification and access to `t`". – Emil Laine Jul 07 '15 at 16:25
  • 2
    It is unsequenced because it is something like `f(a,f(b,f(c,d)))`. But that is worth an answer IMO. – Baum mit Augen Jul 07 '15 at 16:27
  • Sorry for the uninitialised t here, but I actually did initialisation...forgot to put in here...now I have edited it. – Vishal Jul 07 '15 at 16:36

2 Answers2

2

My initial reaction: C++ does not guarantee the order of evaluation on a statement like

cout<<a[t]<<a[++t]<<a[++t];

You need to do something along the lines of:

cout<<a[t]<<a[t + 1]<<a[t + 2];
t += 3;

Upon further review, in response to R Sahu's comments (thanks): The order of evaluation may actually be determinate because operator << is a function call and a function call is a sequence point. However the order will not be as expected. In this case the t++ operations are executed in right-to-left order because the arguments to each function call must be evaluated before the call is made. I.e. this statement is actually:

cout ( << a[t] ( << a[++t] ( << a[++t] ) ) ) ;

and the innermost phrase is evaluated first.

Of course the above parenthesized expression is not valid. To be technically correct I should say:

operator << (operator << ( operator << ( cout, a[++t]), a[++t]), a[t]);

but that is confusing because in order to write the expression in this form I have to reverse the order of the index operators (which is what the compiler does).

And finally in response to Baum's comments: Even decomposing this into function calls this way does not make the call determinate because the order in which function arguments are evaluated is not specified so it could evaluate operator << (cout, a[++t]) before evaluating a[t]

The solution, avoiding operations with side-effects in complex statements, is still valid.

Dale Wilson
  • 9,166
  • 3
  • 34
  • 52
  • 1
    I don't think that is correct. When an operator is overloaded, the order of evaluation is very deterministic. The output seen by the OP is probably caused by uninitialized value of `t` or accessing `a` out of bounds. – R Sahu Jul 07 '15 at 16:18
  • It may be deterministic, but it's not as expected. I just tried it with VC and the arguments are evaluated right to left, so assuming starts at zero, t[0] appears last in the output. – Dale Wilson Jul 07 '15 at 16:28
  • 1
    @RSahu I do not think so. Even when the operator is overloaded, this is something like `f(f(f(cout, t), ++t), ++t)` and the evaluation of function arguments is not sequenced. But that should be explained. – Baum mit Augen Jul 07 '15 at 16:29
  • No. In `operator << ( operator << ( cout, a[++t]), a[++t])` `operator << ( cout, a[++t])` is neither sequenced before nor after the `, a[++t])`. – Baum mit Augen Jul 07 '15 at 16:49
0

The order of evaluation is unspecified. https://en.wikipedia.org/wiki/Sequence_point

Acha Bill
  • 1,255
  • 1
  • 7
  • 20