Printing function addresses always prints 1 on linux
Asked Answered
G

3

3

I'm developing a c++ program that is dealing with addresses for different variables and functions.

When I compiled my program on a Linux based OS, all functions including the main get the address of 1 instead of an 8 digit hexa number like other variables, which did not happen in Windows.

I wrote this small piece of code to explain the issue

#include <iostream>
using namespace std;
void Function1();
void Function1(){ 
}

int main(){
    int tmp;
    void (*a) ()=&Function1;
    cout<<a<<endl;
    cout<<&Function1<<endl;
    cout<<&main<<endl;
    return 0;
}

for all 3 cout calls, the output is 1 instead of the virtual address.

Geezer answered 28/8, 2014 at 0:1 Comment(4)
"which did not happen in Windows" It should have done.Flannel
@LightnessRacesinOrbit I've just tried, didn't happen indeed, VS2013Ardellaardelle
@0d0a: Huh, same in VS2012. This is a bug in one or the other. https://mcmap.net/q/1778074/-is-visual-studio-buggy-in-printing-the-function-address/560648Flannel
please fix the indentationBeachhead
A
7

The pointer gets converted to another type, bool, because it is a function pointer and there are no overloads of operator<< in the <iostream> library for function pointers (because there are an infinite number of such types). The pointer points to some non-zero address because it has been initialized with the address of the function - so it gets converted to 1 (only 0x0 address would give you boolean 0).

Solution

To assert correct behavior, you should cast the pointer to void* so you can use the operator<< overload for void*:

ostream & operator <<( ostream &, const void * );

Example:

void Function1(){}

int main() {
    void ( *a) () = &Function1;
    cout << ( void*)( a) << endl;
    /* or better - being explicit about harshness of this design */
    cout << reinterpret_cast< void*> ( a) <, endl;
}

http://ideone.com/Fne4Mu


C++ Standard n3337 § 4.12 Boolean conversions [conv.bool]

1 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. A prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.

Ardellaardelle answered 28/8, 2014 at 0:14 Comment(2)
Note that in standard C++, it is illegal to cast a function pointer to a void* (see stackoverflow.com/questions/36645660), but some compilers may allow it as an extension, but you should not rely on it.Spinule
Then how come std::cout can print address of a custom class object?Delubrum
T
3

<< has no standard overload taking a function pointer; so instead, the pointer is converted to bool (since that's a legitimate implicit conversion), giving 1, or true if you've used the std::boolalpha manipulator on the stream.

If you want the address, you'll have to explicitly convert it to an object pointer:

std::cout << reinterpret_cast<void*>(&Function1) << std::endl;
Telegony answered 28/8, 2014 at 0:15 Comment(1)
Note that in standard C++, it is illegal to cast a function pointer to a void* (see stackoverflow.com/questions/36645660), but some compilers may allow it as an extension, but you should not rely on it.Spinule
G
0

If I change your code to the following, the function pointer addresses will be displayed correctly:

void Function1() {
}

int main() {
    void*a = (void*)&Function1;
    cout<<a<<endl;
    cout<< (void*)&Function1<<endl;
    cout<< (void*)&main<<endl;
    return 0;
}

Output:

0x8048710
0x8048710
0x8048570

See the working sample here please.


The problem is, there's a standard operator overload available for

ostream& operator<<(ostream&,void*)

but not for function pointers

ostream& operator<<(ostream&,void (Function1Type*)())

and the least valid conversion draws

ostream& operator<<(ostream&,bool)

where everything other than 0x00000000 is true.

Gump answered 28/8, 2014 at 0:19 Comment(1)
@AbdulazizAldyaf If you want to thank me or the community you might consider accepting this answer: Just click that big white checkmark, just left beneath my post (you'll even earn rep for doing this).Milli

© 2022 - 2024 — McMap. All rights reserved.