Strange zero initialization with g++
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++?
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.
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.
Just add more parens:
int main()
{
int x((int()));
int y = int();
cout << x << " " << y << endl;
}
Now x is an int, not a function.
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.
C++ interprets the first one as the declaration of a function.
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.
精彩评论