20

I came across on a strange behavior of the following code, while playing around with initialization of ints using g++ 4.4.3.

  int main()

    {

        int x(int());

        int y = int();

        cout << x << "  " << y <<  endl;
    }

the result is:

1 0

The value of "y" is 0 as expected, but the value of x is strangely "1"!

On VS2008 yields the following link error (a function declaration, but without definition):

unresolved external symbol "int __cdecl x(int (__cdecl*)(void))"

Can anyone explain this strange behavior of g++?

Viktor Apoyan
  • 10,655
  • 22
  • 85
  • 147
Slavcho Ivanov
  • 244
  • 1
  • 5

6 Answers6

24

int x(int()); is parsed as function declaration.

It declares a function named x, returning an int and accepting one parameter, which has the type of a function returning an int and accepting no arguments.

This is known as the most vexing parse.

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • And why "its value" (not the quotes ) is 1 ? Isn't it supposed to be a address of a function of something? (+1, btw) – Kiril Kirov Apr 28 '11 at 07:40
  • Most vexing parse? No love for misinterpretation of `X>`? – Ben Jackson Apr 28 '11 at 07:40
  • @Ben - I'd agree with GMan, as `X>` is pretty obvious and (already) well-known, while this declaration of function is not that "familiar" – Kiril Kirov Apr 28 '11 at 07:42
  • Doh! It's an declaration, not definition, that's why it's not an address. But still - why it's `1` – Kiril Kirov Apr 28 '11 at 07:42
  • 1
    It's 1 because: http://stackoverflow.com/questions/2064692/how-to-print-function-pointers-with-cout – Ben Jackson Apr 28 '11 at 07:43
  • 1
    @Ben, others: [most vexing parse](http://en.wikipedia.org/wiki/Scott_Meyers) first pubished in 1992 by Scott Meyers. (all of C++ parsing is mildly vexing, but there can only be one Ivan The Terrible too) – sehe Apr 28 '11 at 07:49
  • Uhm... darn, I have just written a long answer to the `1` just to realize that that had been asked before. – David Rodríguez - dribeas Apr 28 '11 at 07:51
13

To complement GMan's answer here (x is a function definition) as to why the 1.

The reason for the output to be 1 is that at the place of call std::cout << x, the function decays into a pointer to the function (the language does not allow you to pass functions as arguments to other functions, so as with arrays an implicit conversion to pointer-to is performed). Now, there is no overload of an ostream that takes a function pointer, and the compiler tries to select a conversion to any of the available overloads. At that point it finds that the best conversion sequence is to bool and it prints 1 (the pointer is not 0).

You can check this by changing the behavior, you can use std::cout << std::boolalpha << x, and that will print true instead of 1. Also, it is interesting to note that VS is right with this one, as the expression std::cout << x requires taking the address of x, then the function is used and the program is ill-formed if there is no definition for that function. You can again check that by providing a definition:

int f() {}
int main() {
   int x(int());      // 1
   x( &f );           // 2
}
int x( int(*)() ) {   // 3
   std::cout << "In x" << std::endl;
}

Where I have manually performed the conversion from function to pointer-to-function in the definition of x (1) and the call with the argument f (2) --note that the declaration in 1 and the definition in 3 are the same signature, and that the & in x( &f ) will be performed by the compiler if you don't do it.

Community
  • 1
  • 1
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
4

Just add more parens:

int main()

    {

        int x((int()));

        int y = int();

        cout << x << "  " << y <<  endl;
    }

Now x is an int, not a function.

Jan
  • 1,807
  • 13
  • 26
3

As others have said, x is a function declaration. Since there is no predefined ostream inserter defined for function pointer types, g++ appears to using the implicit bool conversion (used for checking if a function pointer is NULL) to find a way to output it.

Visual C++, on the other hand, is complaining that the declared function x is never defined, and thus it can't complete the link. I suspect g++ in this case is smart enough to see that the function is never called, and thus doesn't worry about the link.

You might try adding a dummy definition of the function int x(int(*)()) { return 0xdeadbeef; } to the code and see what MSVC does with it then.

Drew Hall
  • 28,429
  • 12
  • 61
  • 81
2

C++ interprets the first one as the declaration of a function.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
1

This

int x(int());

Is actually a function declaration the input is a function of following signature

int fn(void)

The function pointer passed to std::cout << is converted to a bool(1) as it is a non-NULL pointer.

dubnde
  • 4,359
  • 9
  • 43
  • 63