1
int ASCI1 = 1;

for (int i = 1; i < 8; i++)
{
    cout << ASCI1 << endl << ASCI1++;
}

I get output :

2
13
24
35
46
57
68

7 (and no end line here for some reason).

The idea was to get

1
2
3
4 
etc.

Completely stumped, please help!

TheProgramMAN123
  • 487
  • 1
  • 5
  • 13

4 Answers4

6

The << operator is not defined as a sequence point in C++, so it's possible for ASCI1 and ASCI1++ to be evaluated in any order.

If you try to perform reads and writes on an object with unsequenced evaluation, then you have undefined behavior, hence the garbage output you are seeing.

Finally, you don't see a newline at the end 1) because you got lucky, and 2) because even if your loop executed as you had planned, you're still performing a write without following it up with another endl

AndyG
  • 39,700
  • 8
  • 109
  • 143
  • Are you sure about the UB? When sequence points still existed, there was one before a function was entered, and one after the function call returned. I don't know if operator invocations count as function calls, though. – IInspectable Jun 08 '16 at 20:10
  • @IInspectable: [The Wikipedia page](https://en.wikipedia.org/wiki/Sequence_point) has a good writeup about it, actually. Basically, if I say in the same line `cout << (a++) << (b++);` where `a` and `b` are integers, then we don't know if `a+1` or `b+1` will get evaluated first because `<<` is not a sequence point, but it doesn't really matter. However, if I say something like `cout << a << a++;` then it *does* matter. [This other SO answer is another great resource](http://stackoverflow.com/a/4183735/27678) and it specifically covers the `>>` and `<<` operators. – AndyG Jun 08 '16 at 20:18
  • I don't see any specific notes about (stream) operators on that page. Given their function-like nature, I would have assumed that the same sequencing rules apply as for function calls. And in that case `cout << a << a++;` would be well defined. – IInspectable Jun 08 '16 at 20:22
  • @IInspectable: Unfortunately it's not, and if you plug something like that into [gcc](http://coliru.stacked-crooked.com/a/d778736db3a5c462) or [clang](http://coliru.stacked-crooked.com/a/124ada41d9c01dfa) they'll give you a warning like so (Clang): "warning: unsequenced modification and access to 'a' [-Wunsequenced]" – AndyG Jun 08 '16 at 20:35
  • So is [this answer](http://stackoverflow.com/a/4638386/1889329) wrong then? Or does `std::cout`'s `operator<<()` not count as a user-defined operator? Or have things changed in C++11? Or are those compiler diagnostics wrong? – IInspectable Jun 08 '16 at 20:40
  • @IInspectable: I think your confusion stems from your understanding of what "there was [a sequence point] before a function was entered, and one after the function call returned." What this means is that all the arguments to a function will have had their side effects completed before the function enters. It does not, however, mean, that if two functions are listed in order in an expression that they'll be evaluated in some left to right order (unless there is a sequence point between them, like logical && or something). – AndyG Jun 08 '16 at 20:47
  • That makes sense. In other words, while it is guaranteed for each call to the operator `<<` that its right-hand side is evaluated before the call, the individual operator `<<` invocations aren't sequenced relative to each other. – IInspectable Jun 08 '16 at 20:54
  • @IInspectable: The answer you linked to is not wrong, because it is about *nesting* function calls. Using `operator<<` on a stream does introduce sequence points in a manner of speaking, but not in the same way. Honestly at this point, the more I dig the more confusing it's getting. In the end it boils down to saying that there is no sequence point between invocations of `operator<<`, so saying something like `operator<<(a).operator<<(a++)` means the order in which `a` and `a++` are evaluated is unspecified. – AndyG Jun 08 '16 at 21:04
  • (Continued) , however, you will at least be guaranteed that `operator<<(a++)` will happen *after* `operator<<(a)` (but since the evaluation of `a` and `a++` are unsequenced we have undefined behavior. – AndyG Jun 08 '16 at 21:04
2

The code is not invisible. You are outputting two numbers per each loop execution, one on first line, then a newline, then another on the next line.

Just do

int ASCI1 = 1;
for (int i = 1; i <= 4; i++){
    cout << ASCI1++ << endl;
}
John M
  • 1,469
  • 17
  • 41
1

Not clear why you created that mess, just use:

int ASCI1 = 1;

for (int i = 0; i < 4; i++) {
    cout << ASCI1++ << endl;
}

Note you should either start with 0 (as shown) or change condition to <= otherwise you will loop 3 times instead of 4.

Slava
  • 43,454
  • 1
  • 47
  • 90
0

Let's consider the very first iteration of for loop (when ASCI1 is 1):

cout << ASCI1 << endl << ASCI1++;

This statement is transformed as (hypothetically):

cout.print(ASCI1).printNewLine().print(ASCI1++);

As others commented, order of evaluation is not defined. In your case, ++ operation is being performed first, but the last print statement is to be passed old value of variable (i.e. 1), and not incremented value. The just incremented value is passed to first print. Hence it becomes:

   cout.print(2).printNewLine().print(1); 

The value of ASCI1 would be 1 after this statement. It will give output as:

2\n
1

And the next iteration would print 3 and 2 the same way I explained above

2
13
2\n

You've been lucky that you used just one ++ statement in one statement.

What if first print is passed 1 and second is passed 2, or 1 and 1. It is up to compiler, and the compilation phase. This is Undefined Behaviour (UB)

Ajay
  • 18,086
  • 12
  • 59
  • 105