Last night, being too tired, I wrote this strange line:
::TerminateThread(::TerminateThread, 0);
To my surprise, the compiler does not complain (It even run...)
Since TerminateThread() is defined as
BOOL WINAPI TerminateThread(HANDLE hThread, DWORD dwExitCode);
I'm no sure why I am able to compile it.
Any explanation?
HANDLE
is a pointer to void, and Microsoft's compiler allows implicitly converting a function pointer to a pointer to void.
This tripped me up many times, especially with the heap functions:
HeapAlloc (GetProcessHeap, 0, size); // oops, should be GetProcessHeap()
It takes the address of the function ::TerminateThread
. This is of type
BOOL WINAPI (*)(HANDLE, DWORD).
HANDLE is defined as
typedef PVOID HANDLE;
So, the compiler wrote code to convert the 'function pointer' type to PVOID which is perfectly valid in C++ ($4.10/2)
"An rvalue of type “pointer to cv T,” where T is an object type, can be converted to an rvalue of type “pointer to cv void.” The result of converting a “pointer to cv T” to a “pointer to cv void” points to the start of the storage location where the object of type T resides, as if the object is a most derived object (1.8) of type T (that is, not a base class subobject)."
EDIT 2:
@dreamlax is correct. It appears that C++03 standard does not allow converting a function pointer to a void * as the program below shows
void f(){}
int main(){
void (*p)(void) = f;
void *p1 = p;
}
I wonder why.
The real answer is: you got lucky. There are three types of code you can feed to a C or C++ compiler:
This last category is "Undefined behaviour" and is one of the worst things about C and C++. The compiler will accept the code, but it most likely won't do what you wanted. Converting a function pointer to a void pointer is not what you wanted, and you probably want a compiler warning telling you that you made a mistake.
Here's a list of possible undefined behaviour in C++. The best thing you can do is try to turn up the warning level of your compiler. In Visual C++ use /w3
or /w4
to turn the warning level up, and it will catch more undefined behaviour at compile time. In gcc, use -ansi -pedantic -W -Wall
to turn up your warning level to full.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With