I was learning about generic pointer 'void*', that allows you to store addresses of multiple data types. However when trying to store the address of a function, I need to cast it, ptr = (void*)someFunc, while for primitive data types ptr = &a. ptr here is a void pointer.
Why does this happen?
void someFunc(){
cout << ("hello");
}
int main(){
int a = 5;
string b = "Hello boiii";
void* ptr = &a;
cout << "ptr holding address of variable a of type int" << endl;
cout << ptr << endl;
ptr = &b;
cout << "ptr holding address of variable b of object string" << endl;
cout << ptr << endl;
ptr = (void*)someFunc; // doubt
cout << "ptr holding address of function someFunc" << endl;
cout << ptr << endl;
return 0;
}
CodePudding user response:
This is the actual rule in the Standard that govern interchangeability and conversion between function pointers (including void(*)(void)
and object pointers (such as void*
):
Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning of such a conversion is implementation-defined, except that if an implementation supports conversions in both directions, converting a prvalue of one type to the other type and back, possibly with different cv-qualification, shall yield the original pointer value.
https://eel.is/c draft/expr.reinterpret.cast#8
This means that on some platforms, the conversion may be outright rejected (for example some architectures hold code and data in different memory spaces and require differently-sized pointers for each), while on platforms where it is possible, the conversion is likely to generate a portability warning if you have such warnings enabled.
POSIX makes some additional guarantees in order to support dynamic loading -- dlsym
's return value may be either an object or function pointer, so conversion between them has to be possible on POSIX platforms.
CodePudding user response:
You may not assign a pointer of the type c/v void * with a function pointer provided that the implementation does not conditionally supports such a conversion. You can only assign a pointer of the type c/v void * with a pointer to object.
From the C 14 Standard (4.10 Pointer conversions)
2 A prvalue of type “pointer to cv T,” where T is an object type, can be converted to a prvalue of type “pointer to cv void”. The result of converting a non-null pointer value of a pointer to object type to a “pointer to cv void” represents the address of the same byte in memory as the original pointer value. The null pointer value is converted to the null pointer value of the destination type.
and
8 Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning of such a conversion is implementation-defined, except that if an implementation supports conversions in both directions, converting a prvalue of one type to the other type and back, possibly with different cvqualification, shall yield the original pointer value.
And from the C Standard (6.3.2.3 Pointers)
1 A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
8 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 referenced type, the behavior is undefined.