cout a function without calling it (not f() but f;). Why does it always print 1?
Asked Answered
C

2

20

My code is "calling" a function without (), and printing the result with std::cout. The function compiles and surprisingly, the code always returns 1.

I expected a function pointer to be printed instead of the 1s. Why is this happening? Did I get all 1's only by chance?

#include <iostream>
using namespace std;

void pr ()
{
    cout << "sth";
}

int main()
{

pr;
cout << pr;  // output: 1
cout << *pr; // output: 1
cout << &pr; // output: 1

}
Catch answered 12/6, 2013 at 18:48 Comment(5)
Implicit cast to bool of a function address.Riddance
This post may be useful: #2065192Dichasium
Implicit conversion to bool of a function address. There is no such thing as in implicit cast.Aureus
Leave it to the C++ questions to attract the pedants :PConcuss
Also: turn on your compiler's warnings to catch this sort of stuff. Live exampleConcuss
B
20

You're not actually calling pr in your code, you're passing the function pointer to cout. pr is then being converted to a bool when being passed to cout. If you put cout << boolalpha beforehand you will output true instead of 1.

EDIT:
With C++11 you can write the following overload:

    template <class RType, class ... ArgTypes>
    std::ostream & operator<<(std::ostream & s, RType(*func)(ArgTypes...))
    {
        return s << "(func_ptr=" << (void*)func << ")(num_args=" 
                 << sizeof...(ArgTypes) << ")";
    }

which means the call cout << pr will print (func_ptr=<address of pr>)(num_args=0). The function itself can do whatever you want obviously, this is just to demonstrate that with C++11's variadic templates, you can match function pointers of arbitrary arity. This still won't work for overloaded functions and function templates without specifying which overload you want (usually via a cast).

Bogard answered 12/6, 2013 at 18:52 Comment(3)
And that's a fallacy in the typesafe C++ iostreams. Or rather, in the implicit conversions of C++.Concuss
@Concuss Check the edit, with C++11 there's a cure for that now.Bogard
note that (void *)func is a conditionally-supported feature, the compiler may reject itTelemachus
M
5

The name of a function, when used without parentheses, can be implicitly cast to a function pointer. In fact, when you dereference or reference it, it remains nothing but a function pointer, or a poointer to a function pointer, etc. These function pointers, when printed, are implicitly cast to bool, which is why they simply output 1. If you want to output the actual memory address of the function, cast it to a void pointer:

cout<<(void*)pr;
Modigliani answered 12/6, 2013 at 18:53 Comment(3)
More generally, in most contexts, an expression of function type (including a function name) is implicitly converted to a pointer to the function. Exceptions are when it's the argument to sizeof (which is illegal) or to unary & (which yields the address of the function). This applies even when the function name is followed by parentheses; a function call requires a pointer-to-function as its first operand.Exordium
BTW, casting a function pointer to void* is likely to work on most systems, but I don't believe the behavior is defined. (For example, the conversion could lose information if function pointers are bigger than void*.)Exordium
Is there a (void*)pr equivalent that is well-formed? Some sort of (void_fnptr_t*)pr?Predial

© 2022 - 2024 — McMap. All rights reserved.