I tried the following code of C++. However, the outputs of printf and std::cout are different. Why?
struct Foo
{
int a;
int b;
int c;
};
int main()
{
printf("%d\n", &Foo::c); // The output is 8
std::cout << &Foo::c << "\n"; // The output is 1
}
printf("%d\n", &Foo::c): this is undefined behavior, as &Foo::c is not an integer, but a pointer to member (but, actually, it is usual that the compiler stores pointer to data member as offset, and as 8 is the offset of Foo::c, 8 is printed).
std::cout << &Foo::c: this prints the value &Foo::c. As iostream doesn't have a pointer to member printer, it chooses the closest one: it converts it to bool, and prints it as integer. As &Foo::c converted to bool is true, 1 is printed.
The output is different because the behavior of your printf is undefined.
A pointer to member (like the one produced from &Foo::c) is not an integer. The printf function expects an integer, since you told it too with the %d specifier.
You can amend it by adding a cast to bool, like this:
printf("%d\n", (bool)&Foo::c)
A pointer to member may be converted to a bool (which you do with the cast), and the bool then undergoes integral promotion to an int on account of being an integral variadic argument to a variadic function.
Speaking of the conversion to bool, it's exactly the conversion that is applied implicitly by attempting to call std::ostream's operator<<. Since there isn't an overload of the operator that supports pointers to members, overload resolution selects another that is callable after implicitly converting &Foo::c to a boolean.
In addition to the more literal answer about why the compiler interpreted your code the way it did: you seem to have an XY problem You’re trying to format a pointer-to-member as an integer, which strongly suggests you meant to do something different.
If what you wanted was an int value stored in .c, you either need to create an instance Foo some_foo; and take some_foo.c, or else you need to declare Foo::c a static member, so there’s one unambiguous Foo::c across the entire class. Do not take the address in this case.
If what you wanted was to take an address of the .c member of some Foo, you should do as above so that Foo::c is static and refers to one specific variable, or else declare an instance and take its .c member, then take the address. The correct printf() specifier for an object pointer is %p, and to print an object pointer representation with <iostream>, convert it to void*:
printf( "%p\n", &some_foo.c );
std::cout << static_cast<void*>{&some_foo.c} << '\n';
If what you want is the offset of Foo::c within class Foo, you want the offsetof() macro in <stddef.h>. Since its return value is size_t, which is not the same size as int on 64-bit platforms, you would want to either cast the result explicitly or pass printf() the z type specifier:
#include <stddef.h>
/* ... */
constexpr size_t offset_c = offsetof( Foo, c );
printf( "%zu\n", offset_c );
cout << offset_c << '\n';
Whatever you were trying to do, if your compiler didn’t warn you about the type mismatch, you ought to turn on more warnings. This is especially true for someone coding by trial and error until the program compiles.
Related
Function pointers of dissimilar types can't be directly compared :
#include <iomanip>
#include <iostream>
int foo() { return 0; }
void bar(int) {}
int main()
{
// Doesn't compile, the comparison is not allowed
std::cout << std::boolalpha << (&foo == &bar) << std::endl;
return 0;
}
However, if one function pointer is cast to the type of the other function pointer, is it defined behavior to compare the result of that cast with the other function pointer?
#include <iomanip>
#include <iostream>
int foo() { return 0; }
void bar(int) {}
int main()
{
auto cast_ptr = reinterpret_cast<decltype(&bar)>(&foo);
// Printed "false" when I tried it, but is this guaranteed?
std::cout << std::boolalpha << (cast_ptr == &bar) << std::endl;
}
How about if both operators have been cast to a common but different type?
#include <iomanip>
#include <iostream>
int foo() { return 0; }
void bar(int) {}
int main()
{
using cast_type = void(*)();
auto cast_foo = reinterpret_cast<cast_type>(&foo);
auto cast_bar = reinterpret_cast<cast_type>(&bar);
// Also printed "false" when I tried it, but is this guaranteed?
std::cout << std::boolalpha << (cast_foo == cast_bar) << std::endl;
}
I understand that function pointers compare equal if and only if they both point to nullptr or to the same function. What's not clear to me is rather or not using a function pointer that's been cast to another function pointer type in a comparison is allowed.
Context
I'm maintaining a c++ library with a c compatible API. The library logs every call made to API functions. It's become useful to selectively disable this logging for certain functions at run time. The best current proposal in terms of usability is to supply a new API function which takes as an argument a pointer to the API function whose logging should be suppressed. Since the API functions have different arguments, these pointers would have different types and would need to be cast to a common function pointer type such as void(*)(). Then, before logging an API function call, a container of void(*)() would be searched for the address of the called function to know rather or not to log that call.
From [expr.reinterpret.cast]
A function pointer can be explicitly converted to a function pointer of a different type. [...] Except that converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified.
It is unspecified whether casted function pointers compare equally.
A pointer can be explicitly converted to any integral type large enough to hold it. The mapping function is implementation-defined.
Hence it is a natural choice to convert to std::intptr_t or some other suitable type, provided the implementation doesn't use some wacky conversion.
From GCC's documentation
A cast from pointer to integer discards most-significant bits if the pointer representation is larger than the integer type, sign-extends1 if the pointer representation is smaller than the integer type, otherwise the bits are unchanged.
AKA the sane conversion. Which is probably what you'll find in most cases I'd bet.
[1] Future versions of GCC may zero-extend, or use a target-defined ptr_extend pattern. Do not rely on sign extension.
Will the following work as expected?:
struct A {};
struct B: public A {
int x;
};
void f( B* o ) {
std::cout << o->x << std::endl;
}
int main () {
B b;
b.x = 5;
reinterpret_cast<void(*)(A*)>(f)( &b );
}
Its undefined behaviour to use such pointer after cast:
Any pointer to function can be converted to a pointer to a different function type. Calling the function through a pointer to a different function type is undefined, but converting such pointer back to pointer to the original function type yields the pointer to the original function.
From http://en.cppreference.com/w/cpp/language
So the answer to your question is actually positive - you are allowed to cast but nothing more.
You might ask "what is the point of only casting?" - this is usefull when you want to store various functions in single collection.
See 5.2.10/6 [expr.reinterpret.cast]:
A function pointer can be explicitly converted to a function pointer of a different type. The effect of calling a function through a pointer to a function type that is not the same as the type used in the definition of the function is undefined.
That said, note as an example that C++ allows you to dereference a null pointer, so maybe allowed is not the right term.
The following command compiles too:
reinterpret_cast<void(*)(A*, int)>(f)( &b, 42 );
It is allowed, as well as the one in the question, no matter if it works as expected or not (it mostly depends on your expectations, as noted by #luk32 in the comments).
The answer to your question would be yes, the cast is allowed, but the invokation of the function through the new pointer leads to an undefined behavior.
I need to store a function reference as a char*, and later call that function with only the char*.
I am looking for something like:
char* funcRef = (char*)myFunc;
//...
(void (*funcRef)())();
How do you do this? (Note: I am not asking how to call a function by reference, just if its possible to store a reference to it as a char* and then convert it back)
This conversion is not allowed. The allowable conversions are given in section 6.3 Conversions, sub-subsection 6.3.2.3 Pointers, of which paragraphs (6) and (8) apply to function pointers.
Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined...
and
A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.
Conversion between pointer to function and pointer to object is not on the allowed list; it is therefore disallowed.
There are systems where pointers to functions and pointers to objects are not interchangeable. The most obvious case is where the size of a function pointer is not the same as the size of an object pointer, such as Harvard architecture, or the 8086 in Compact or Medium model.
The reason your code isn't working is because a char* pointer is not a function pointer. You cannot call a char* as if it was a function. You need to cast that pointer back to a function pointer prior to using it as a function pointer.
Note very well: Whether this will work at all is highly compiler and system dependent.
There is nothing in the C standard that says anything about converting a pointer to a function to a pointer to an object, or vice versa. This is undefined behavior. On the other hand, POSIX standard requires that a compliant implementation must be able to convert a pointer to void to a pointer to a function. (Note: The reverse capability is not required.)
This question is also tagged as C++. Prior to C++11, converting a pointer to a function to a pointer to an object, or vice versa, was illegal. The compiler had to issue a diagnostic message. On POSIX-compliant systems, the compiler would issue a diagnostic and then generate the POSIXly-compliant object code. In C++11 and later, converting converting between pointers to functions to a pointers to an object, or vice versa, is conditionally-supported.
With those caveats, the following works on my POSIX-compliant machine, with multiple compilers. Whether it works on a non-POSIX compliant machine with non-POSIX complaint compilers is anyone's guess.
C++ version:
#include <iostream>
int sqr (int k) { return k*k; }
int p42 (int k) { return k+42; }
void call_callback(void* vptr, int k)
{
using Fptr = int(*)(int);
Fptr fun = reinterpret_cast<Fptr>(vptr);
std::cout << fun(k) << '\n';
}
int main ()
{
call_callback(reinterpret_cast<void*>(sqr), 2);
call_callback(reinterpret_cast<void*>(p42), 2);
}
C version:
#include <stdio.h>
int sqr (int k) { return k*k; }
int p42 (int k) { return k+42; }
void call_callback(void* vptr, int k)
{
printf ("%d\n", ((int(*)(int))(vptr))(k));
}
int main ()
{
call_callback((void*)(sqr), 2);
call_callback((void*)(p42), 2);
}
I am trying to do something like
#include <iostream>
using namespace std;
void foo () {
void (*fooptr) (void) = foo;
cout << fooptr << endl;
}
int main () {
void (*fooptr) (void) = foo;
foo ();
return 0;
}
My intent is to see the value of function pointers. If I look up for the address of any function in the main () function it makes sense that the function isn't called, It might have not been allocated the memory in the function call stack. But when I call the function and try to see the value of pointer. It still shows the same result 1. Any explanation?
I might not be printing the address of the called function itself. Is there any pointer like this like we have in classes. So that we can see the address of itself?
The standard stream types don't overload << for function pointers, only for regular pointers. You see the value 1 because a function pointer is implicitly convertible to bool, and there is an overload for bool, so that is chosen.
To print the address, you could convert it to a regular (object) pointer:
cout << reinterpret_cast<void*>(fooptr) << std::endl;
Note that this isn't completely portable: according to the standard, it's conditionally-supported, with an implementation-defined meaning. But it should give the expected address on any sensible implementation on mainstream platforms that store functions in regular memory. For more portability, you might convert to intptr_t or uintptr_t; but you'd need a bit of extra work if you want it to be formatted like a pointer.
In the code below, function-pointer and what i considered as "function-reference" seems to have identical semantics:
#include <iostream>
using std::cout;
void func(int a) {
cout << "Hello" << a << '\n';
}
void func2(int a) {
cout << "Hi" << a << '\n';
}
int main() {
void (& f_ref)(int) = func;
void (* f_ptr)(int) = func;
// what i expected to be, and is, correct:
f_ref(1);
(*f_ptr)(2);
// what i expected to be, and is not, wrong:
(*f_ref)(4); // i even added more stars here like (****f_ref)(4)
f_ptr(3); // everything just works!
// all 4 statements above works just fine
// the only difference i found, as one would expect:
// f_ref = func2; // ERROR: read-only reference
f_ptr = func2; // works fine!
f_ptr(5);
return 0;
}
I used gcc version 4.7.2 in Fedora/Linux
UPDATE
My questions are:
Why function pointer does not require dereferencing?
Why dereferencing a function reference doesn't result in an error?
Is(Are) there any situation(s) where I must use one over the other?
Why f_ptr = &func; works? Since func should be decayed into a pointer?
While f_ptr = &&func; doesn't work (implicit conversion from void *)
Functions and function references (i.e. id-expressions of those types) decay into function pointers almost immediately, so the expressions func and f_ref actually become function pointers in your case. You can also call (***func)(5) and (******f_ref)(6) if you like.
It may be preferable to use function references in cases where you want the &-operator to work as though it had been applied to the function itself, e.g. &func is the same as &f_ref, but &f_ptr is something else.
"Why function pointer does not require dereferencing?"
Because the function identifier itself is actually a pointer to the function already:
4.3 Function-to-pointer conversion
§1 An lvalue of function type T can be converted to an rvalue of type “pointer to T.” The result is a pointer to the function.
"Why dereferencing a function reference doesn't result in an error?"
Basically you can look at defining a reference as defining an alias (alternative name). Even in the standard in 8.3.2 References in part addressing creating a reference to an object, you will find:
"a reference can be thought of as a name of an object."
So when you define a reference:
void (& f_ref)(int) = func;
it gives you the ability to use f_ref almost everywhere where it would be possible to use func, which is the reason why:
f_ref(1);
(*f_ref)(4);
works exactly the same way as using the func directly:
func(1);
(*func)(4);
See here.
The address-of operator acts like you would expect, as it points to a function but cannot be assigned. Functions are converted to function pointers when used as rvalues, which means you can dereference a function pointer any number of times and get the same function pointer back.
As there are good answers from other people here, there is no answer explaining why f_ptr = &&func; does not work. When you apply the addressof operator & to a variable/function, you get its address. The adress itself is an r-value/a temporary variable. You cannot take the address of a temporary.
But it seems that there is a type error. The message implicit conversion from void* is very compiler specific for this code. I guess you are using GCC/Clang. GCC/Clang offers the ability to take the address of labels like &&label. The resulting value is of type void*. Other compilers will output something like cannot take address of temporary or invalid syntax. When using these compilers this kind of error could have been hidden without any warning in special circumstances:
int main() {
int foo = 42;
foo:;
void* a = &foo; // take the address of a variable/function
void* b = &&foo; // take the address of a label
std::cout << *(int*)a << '\n';
goto *b;
};
But who would name everything the same?