128

Why is the output of the below program what it is?

#include <iostream>
using namespace std;

int main(){

    cout << "2+3 = " <<
    cout << 2 + 3 << endl;
}

produces

2+3 = 15

instead of the expected

2+3 = 5

This question has already gone multiple close/reopen cycles.

Before voting to close, please consider this meta discussion about this issue.

Community
  • 1
  • 1
Hokhy Tann
  • 1,249
  • 1
  • 9
  • 14
  • 96
    You want semicolon `;` at the end of the first output line, not `<<`. You are not printing what you think you are printing. You are doing `cout << cout`, which prints `1` (it uses `cout.operator bool()`, I think). Then `5` (from `2+3`) immediately follows, making it look like the number fifteen. – Igor Tandetnik Jan 19 '17 at 15:39
  • As @IgorTandetnik said, you're not printing what you think you are. There's no overload for printing `std::ostream` objects so it's being mapped to `true` and then printed as `1`. Then `2+3` (`5`) is being shown and you get `15`. – Kamil Koczurek Jan 19 '17 at 15:45
  • 1
    When it compiles (i.e. prior to c++11), cout << cout would output the address of stream cout, right? This is very unlikely to be `1`... – Stephan Lechner Jan 19 '17 at 15:56
  • 2
    @StephanLechner Correct. I get "2+3 = 0x8049c645" – simon Jan 19 '17 at 15:56
  • 5
    @StephanLechner That's probably using gcc4 then. They did not have fully compliant streams until gcc5, in particular, they still had the conversion implicit until then. – Baum mit Augen Jan 19 '17 at 16:00
  • 1
    I found a setting in xcode which produces `1`, and another setting that yields an address: Language dialect c++98 combined with "Standard library libc++ (LLVM standard library with c++11 support)" yields `1`, whereas c++98 combined with libstdc (gnu c++ standard library) yields an address; – Stephan Lechner Jan 19 '17 at 16:04
  • 4
    @IgorTandetnik that sounds like the beginning of an answer. There appear to be a lot of subtleties to this question that aren't evident on first read. – Mark Ransom Jan 19 '17 at 16:06
  • 2
    @StephanLechner `cout << cout` must be using [this](http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool) - `operator void*` pre-C++11, `explicit operator bool()` post-C++11. I guess you've found a combination where a) the header comes with the C++11-style definition, but b) the compiler ignores `explicit` part (as that didn't exist in C++03 and earlier) and allows `cout << cout` to compile; or perhaps the header #ifdefs away the `explicit` keyword, to avoid choking the "old" compiler. – Igor Tandetnik Jan 19 '17 at 16:11
  • Added a provisional answer - if anyone has a better one, please submit it so we can close the ridiculous duplicate. – Useless Jan 19 '17 at 16:29
  • 14
    Why do people keep voting to close this question? It's not "Please tell me what is wrong with this code," but "Why does this code produce this output?" The answer to the first is "you made a typo", yes, but the second requires an explanation of how the compiler is interpreting the code, why it's not a compiler error, and how it's getting "1" instead of a pointer address. – jaggedSpire Jan 19 '17 at 22:49
  • 6
    @jaggedSpire If it's not a typographical error, then it's a very bad question because then it deliberately uses an unusual construct that looks like a typographical error without pointing out that that's intentional. Either way, to deserves a close vote. (As either due to a typographical error or bad/malicious. This is a site for people looking for help, not people trying to trick others.) – David Schwartz Jan 20 '17 at 12:14
  • I think this is a valid post, but there is something fishy in the number of upvotes this question got. The rule of Stack Overflow, for some time now, is "post a question tagged C++ or Java that addresses a subtle misuse of the language, and you got a bunch of upvotes". So sad for a website dedicated to "professional programmmers". – Andrea Jan 20 '17 at 13:56
  • I'm thinking this is a duplicate anyway of http://stackoverflow.com/a/7489162/332733 – Mgetz Jan 20 '17 at 15:06
  • 2
    @Mgetz maybe not--while that does cover what happens when you do `cout << cout` in normal situations, this is a specific, weird instance where the output is a boolean value instead of an address because of the slightly incompatible combination of a C++98 compilation setting and a library for C++11 and later. – jaggedSpire Jan 20 '17 at 15:20
  • 4
    I've started a meta discussion due to multiple close/reopen cycles this question has gotten through: http://meta.stackoverflow.com/questions/342113/typo-which-leads-to-a-very-interesting-analysis – bolov Jan 23 '17 at 15:06
  • This is epic. It could not be more unintentional and confusing at first sight. – Etherealone Jan 24 '17 at 19:21
  • if I had asked a question like this, I would have got -10 votes !!! – Amin Etesamian Jan 24 '17 at 20:41
  • 3
    @AminEtesamian the *way* you ask is everything sometimes. This question has been heavily edited--if you look at the edit history you'll see a question that's essentially the same, but which would be (and was) downvoted heavily. I *think* the low point was -8, before the image was translated into real code. Note also that even though it's been edited multiple times it's still not explicit enough in acknowledging the typo that a close/reopen war over closing for a typo has ensued. They're presently discussing how to deal with *that* on meta. – jaggedSpire Jan 24 '17 at 21:11
  • it is just a typo I wonder why such voting up! cout << cout – Raindrop7 Jan 24 '17 at 22:07

5 Answers5

234

Whether intentionally or by accident, you have << at the end of the first output line, where you probably meant ;. So you essentially have

cout << "2+3 = ";  // this, of course, prints "2+3 = "
cout << cout;      // this prints "1"
cout << 2 + 3;     // this prints "5"
cout << endl;      // this finishes the line

So the question boils down to this: why does cout << cout; print "1"?

This turns out to be, perhaps surprisingly, subtle. std::cout, via its base class std::basic_ios, provides a certain type conversion operator that is intended to be used in boolean context, as in

while (cout) { PrintSomething(cout); }

This is a pretty poor example, as it's difficult to get output to fail - but std::basic_ios is actually a base class for both input and output streams, and for input it makes much more sense:

int value;
while (cin >> value) { DoSomethingWith(value); }

(gets out of the loop at end of stream, or when stream characters do not form a valid integer).

Now, the exact definition of this conversion operator has changed between C++03 and C++11 versions of the standard. In older versions, it was operator void*() const; (typically implemented as return fail() ? NULL : this;), while in newer it's explicit operator bool() const; (typically implemented simply as return !fail();). Both declarations work fine in a boolean context, but behave differently when (mis)used outside of such context.

In particular, under C++03 rules, cout << cout would be interpreted as cout << cout.operator void*() and print some address. Under C++11 rules, cout << cout should not compile at all, as the operator is declared explicit and thus cannot participate in implicit conversions. That was in fact the primary motivation for the change - preventing nonsensical code from compiling. A compiler that conforms to either standard would not produce a program that prints "1".

Apparently, certain C++ implementations allow mixing and matching the compiler and the library in such a way that produces non-conforming outcome (quoting @StephanLechner: "I found a setting in xcode which produces 1, and another setting that yields an address: Language dialect c++98 combined with "Standard library libc++ (LLVM standard library with c++11 support)" yields 1, whereas c++98 combined with libstdc (gnu c++ standard library) yields an address;"). You can have a C++03-style compiler that doesn't understand explicit conversion operators (which are new in C++11) combined with a C++11-style library that defines the conversion as operator bool(). With such a mix, it becomes possible for cout << cout to be interpreted as cout << cout.operator bool(), which in turn is simply cout << true and prints "1".

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85
  • 1
    @T.C. I'm pretty sure there's no difference between C++03 and C++98 in this particular area. I suppose I could replace all mentions of C++03 with "pre-C++11", if this would help clarify matters. I'm not at all familiar with the intricacies of compiler and library versioning on Linux et al; I'm a Windows/MSVC guy. – Igor Tandetnik Jan 19 '17 at 20:48
  • 4
    I wasn't trying to nitpick between C++03 and C++98; the point is that libc++ is C++11 and newer only; it doesn't try to conform to C++98/03. – T.C. Jan 19 '17 at 21:38
45

As Igor says, you get this with a C++11 library, where std::basic_ios has the operator bool instead of the operator void*, but somehow isn't declared (or treated as) explicit. See here for the correct declaration.

For example, a conforming C++11 compiler will give the same result with

#include <iostream>
using namespace std;

int main() {
    cout << "2+3 = " << 
    static_cast<bool>(cout) << 2 + 3 << endl;
}

but in your case, the static_cast<bool> is being (wrongly) allowed as an implicit conversion.


Edit: Since this isn't usual or expected behaviour, it might be useful to know your platform, compiler version, etc.


Edit 2: For reference, the code would usually be written either as

    cout << "2+3 = "
         << 2 + 3 << endl;

or as

    cout << "2+3 = ";
    cout << 2 + 3 << endl;

and it's mixing the two styles together that exposed the bug.

Useless
  • 64,155
  • 6
  • 88
  • 132
  • 1
    There is a typo in your first suggested solution code. One too many operator. – eerorika Jan 19 '17 at 16:40
  • 3
    Now I'm doing it as well, it must be contagious. Thanks! – Useless Jan 19 '17 at 16:41
  • 1
    Ha! :) In the initial edit of my answer, I suggested adding the semicolon, but didn't realize the operator at the end of the line. I think together with OP, we have generated most significant permutations of typos this can have. – eerorika Jan 19 '17 at 16:43
21

The reason for the unexpected output is a typo. You probably meant

cout << "2+3 = "
     << 2 + 3 << endl;

If we ignore the strings that have the expected output, we are left with:

cout << cout;

Since C++11, this is ill-formed. std::cout is not implicitly convertible to anything that std::basic_ostream<char>::operator<< (or a non member overload) would accept. Therefore a standards conforming compiler must at least warn you for doing this. My compiler refused to compile your program.

std::cout would be convertible to bool, and the bool overload of the stream input operator would have the observed output of 1. However, that overload is explicit, so it shouldn't allow an implicit conversion. It appears that your compiler/standard library implementation doesn't strictly conform to the standard.

In a pre-C++11 standard, this is well formed. Back then std::cout had an implicit conversion operator to void* which has a stream input operator overload. The output for that would however be different. it would print the memory address of the std::cout object.

eerorika
  • 232,697
  • 12
  • 197
  • 326
11

The posted code should not compile for any C++11 (or later conformant compiler), but it should compile without even a warning on pre C++11 implementations.

The difference is that C++11 made the convertion of a stream to a bool explicit:

C.2.15 Clause 27: Input/output library [diff.cpp03.input.output] 27.7.2.1.3, 27.7.3.4, 27.5.5.4

Change: Specify use of explicit in existing boolean conversion operators
Rationale: Clarify intentions, avoid workarounds.
Effect on original feature: Valid C++ 2003 code that relies on implicit boolean conversions will fail to compile with this International Standard. Such conversions occur in the following conditions:

  • passing a value to a function that takes an argument of type bool;
    ...

ostream operator << is defined with a bool parameter. As a conversion to bool existed (and was not explicit) is pre-C++11, cout << cout was translated to cout << true which yields 1.

And according to C.2.15, this should not longer compile starting with C++11.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • 3
    No conversion to `bool` existed in C++03, however there is `std::basic_ios::operator void*()` which is meaningful as the controlling expression of a conditional or loop. – Ben Voigt Jan 19 '17 at 22:30
8

You can easily debug your code this way. When you use cout your output is buffered so you can analyse it like this:

Imagine first occurence of cout represents the buffer and operator << represents appending to the end of the buffer. Result of operator << is output stream, in your case cout. You start from:

cout << "2+3 = " << cout << 2 + 3 << endl;

After applying the above stated rules you get a set of actions like this:

buffer.append("2+3 = ").append(cout).append(2 + 3).append(endl);

As I said before the result of buffer.append() is buffer. At the begining your buffer is empty and you have the following statement to process:

statement: buffer.append("2+3 = ").append(cout).append(2 + 3).append(endl);

buffer: empty

First you have buffer.append("2+3 = ") which puts the given string directly into the buffer and becomes buffer. Now your state looks like this:

statement: buffer.append(cout).append(2 + 3).append(endl);

buffer: 2+3 = 

After that you continue to analyze your statement and you come across cout as argument to append to the end of buffer. The cout is treated as 1 so you will append 1 to the end of your buffer. Now you are in this state:

statement: buffer.append(2 + 3).append(endl);

buffer: 2+3 = 1

Next thing you have in buffer is 2 + 3 and since addition has higher precedence than output operator you will first add these two numbers and then you will put the result in buffer. After that you get:

statement: buffer.append(endl);

buffer: 2+3 = 15

Finally you add value of endl to the end of the buffer and you have:

statement:

buffer: 2+3 = 15\n

After this process the characters from the buffer are printed from the buffer to standard output one by one. So the result of your code is 2+3 = 15. If you look at this you get additional 1 from cout you tried to print. By removing << cout from your statement you will get the desired output.

Ivan Kulezic
  • 440
  • 4
  • 15
  • 6
    Although this is all true (and beautifully formatted), I think it's begging the question. I believe the question boils down to _"Why does `cout << cout` produce `1` in the first place?"_, and you've just asserted that it does in the middle of a discussion on insertion operator chaining. – Useless Jan 25 '17 at 14:46
  • 1
    +1 for the beautiful formatting though. Considering that this is your first answer, it's nice that you're trying to help :) – galdin Jan 27 '17 at 11:12