1

When I try using cout, it outputs a random number rather then the sentence I want. There is not compiler error, the program runs fine.

Here is my code:

//question.h
#ifndef _QUESTION_H_
#define _QUESTION_H_

using namespace std;
int first()
{
    cout<<"question \n";
    return 0;
}

#endif

//main.cpp
#include <iostream>
#include "question.h"

using namespace std;

void main(){
    cout<<""<<first<<""<<endl;
    cin.ignore();
    cin.get();
}

I'm fairly new to writing my own header files, so I'm not sure if I did something wrong with that or if there's a problem with visual studio.

Braeden Orchard
  • 235
  • 2
  • 12
  • 2
    first() returns an int but does some stream injecting... I don't even know what would happen if it was doing what you think you intend it to do. – Grady Player Mar 06 '13 at 02:10
  • @GradyPlayer, Indeed. Here's an example where the output from the function is first: http://liveworkspace.org/code/3RyOu1%243 – chris Mar 06 '13 at 02:15
  • Excellent example @chris, I was wondering if that buffer would get flushed first... Or if it called first into a register / tmp location before the other stream operation. – Grady Player Mar 06 '13 at 02:19
  • This may look weird but is well-defined: the output is the first empty string, the string `"question \n"`, the character `'0'`, the second empty string, and a newline, in that order. This is because every invocation of `operator<<` provides a sequence point on either side. (If this didn't work it wouldn't be possible to chain `cout << a << b << c << ...` at all.) – zwol Mar 06 '13 at 18:59
  • @Zack, Shouldn't it be the same thing as `std::cout << i << ' ' << ++i;`? That could print `i i+1` or `i+1 i`. This could do the same thing and print `"" "question \n"` or `"question \n" ""`. In the example I linked to, it prints `"question \n" ""1 0 ""2`, where `""1` and `""2` are the first and second empty strings respectively. – chris Mar 07 '13 at 00:00
  • @chris I didn't think so, but seeing your demo now I'm not sure. I would have thought that the implicit sequence points on either side of each `operator<<` forced strict left-to-right evaluation, including not calling the function until after everything to the left of it had been printed. – zwol Mar 07 '13 at 03:17
  • @Zack, This might make for a good question to clear things up if it isn't already on here. It must be distinctive from the constantly recurring "Why do I get different results when printing `std::cout << i << i++;`?" questions, though. Feel free to ask it if you want to. – chris Mar 07 '13 at 03:25
  • @chris Hang on, is `cout << i << i++` unspecified behavior? If so, I don't know what I'm talking about. (I don't use iostreams if I can possibly avoid it, so there's an excellent chance I indeed don't know how this works.) – zwol Mar 07 '13 at 03:34
  • @Zack, If we imagine it as `operator<<(operator<<(operator<<(std::cout, ""), first()), "");`, I think there would be a sequence point (at least in pre-C++11 terms) at each function call. Before that happens, the arguments must all be evaluated. That means that `""`, `first()`, and `""` would all have to be evaluated in an unspecified order (which shouldn't actually matter here with this logic) before any output is produced. After each output should be a sequence point to keep things in order. I think the output from `first()` must always be the first thing then and the others in order. – chris Mar 07 '13 at 03:46
  • Or maybe I'm doing it wrong and it could be the case that the most inner `""` could be evaluated with the paired `std::cout` and output before `first()` is evaluated, all of which could happen before or after the outer `""` is evaluated, but the outer would not be printed yet because the inner calls have not been evaluated. I think that might be how it is, in which case it would either be output first or after the first empty string. – chris Mar 07 '13 at 03:50
  • @Zack, I should have done this before, but I ran it on the available C++ compilers on LWS. All GCCs put the `first()` output first, and Intel and Clang put it after the first empty string ("abc" in the example). That inconclusively points to my second wall of text. As soon as I can be sure about what could happen, I'll update my answer with the appropriate changes. – chris Mar 07 '13 at 03:51

3 Answers3

5

You're printing the address of the function. You need to call it:

cout<<""<<first()<<""<<endl;
               ^^

As mentioned in the comments, this doesn't have to output what you expect, either. The order in which arguments to functions (and that is just a bunch of function calls) is unspecified, so your function output could be in any position the compiler chooses. To fix this, put separate statements:

cout<<"";
cout<<first(); //evaluated, so output inside first() printed before return value
cout<<""<<endl;

It might not matter with the empty strings, but it will when you replace those with something visible.

Also, don't use void main. Use int main() or int main(int, char**) (see here). Don't use using namespace std;, especially in headers, as std has a lot of crap in it that is pulled in with that statement, leading to easy and confusing conflicts (see here). Finally, choose a name that does not conflict with identifiers reserved for the implementation as your include guard.

Community
  • 1
  • 1
chris
  • 60,560
  • 13
  • 143
  • 205
  • There isn't an evaluation order issue in the OP's code. If corrected to call `first` instead of just taking its address, it can be relied upon to print `@question \n0#$` where `@` is the empty string to the left of `first`, `#` is the empty string to its right, and `$` is `endl`. But I think it was *meant* to print just `@question \n#$` -- the OP appears to have thought that this was how you write a "manipulator"-like iostream item. – zwol Mar 06 '13 at 17:14
1

You are printing the address of the function first rather than calling it. But changing the function call won't fix your problem all by itself, because first writes to cout internally and then returns a number, which will be printed, which doesn't appear to be what you want.

If you want first to act like an <iomanip> thingie you have to jump through a few more hoops -- read that header to see how it's done.

zwol
  • 135,547
  • 38
  • 252
  • 361
0

Use cout<<""<<first()<<""<<endl; you need to actually call the function, not print its address

Mawg says reinstate Monica
  • 38,334
  • 103
  • 306
  • 551