reinterpret cast problem.

D

Dave Townsend

Hi,

I'm trying to port a piece of code from Windows to Linux, the following
segment illustrates the coding problemI have: Under Linux, the
reinterpret_cast line
doesn't compile, the compiler says ISO C++ doesn allow a cast from
pointer-to-object
to pointer-to-function. However, I can use the plain-old-C-style cast and
the code compiles and works. I guess I have two questions:-

1. What is the sanctified way to write this type of code.
2. What is the rational behind the GNU compiler message ( presuming the
compiler is correctly interpreting the standard).

Thanks,

dave.

#include <stdio.h>

static int foo()
{
printf("hello\n");
return 0;
}

typedef int fnc_t();

int main(int argc, char* argv[])
{
void* fv = (fnc_t*)foo;

fnc_t* fnc = reinterpret_cast<fnc_t*>(fv); // illegal under GNU/linux

fnc();


return 0;
}
 
J

Jonathan Turkanis

Dave said:
Hi,

I'm trying to port a piece of code from Windows to Linux, the
following segment illustrates the coding problemI have: Under Linux,
the reinterpret_cast line
doesn't compile, the compiler says ISO C++ doesn allow a cast from
pointer-to-object
to pointer-to-function. However, I can use the plain-old-C-style
cast and the code compiles and works. I guess I have two questions:-

First, there are a number of compilers available for Windows and Linux. I gather
you're using GCC, but it wouldn't hurt to mention it. Also, the version is often
useful.
1. What is the sanctified way to write this type of code.
2. What is the rational behind the GNU compiler message ( presuming
the compiler is correctly interpreting the standard).

Thanks,

dave.

#include <stdio.h>

static int foo()
{
printf("hello\n");
return 0;
}

typedef int fnc_t();

int main(int argc, char* argv[])
{
void* fv = (fnc_t*)foo;

fnc_t* fnc = reinterpret_cast<fnc_t*>(fv); // illegal under
GNU/linux

fnc();


return 0;
}

GCC is correct. You can't reinterpret_cast between pointers to objects and
pointers to functions. If you need to be able to store either a function pointer
or an object pointer in a single variable, you can use a union:

union any_pointer
{
void* obj_ptr;
void (*func_ptr)();
};

Jonathan
 
I

Ivan Vecerina

Dave Townsend said:
I'm trying to port a piece of code from Windows to Linux, the following
segment illustrates the coding problemI have: Under Linux, the
reinterpret_cast line
doesn't compile, the compiler says ISO C++ doesn allow a cast from
pointer-to-object
to pointer-to-function. However, I can use the plain-old-C-style cast and
the code compiles and works. I guess I have two questions:-

1. What is the sanctified way to write this type of code.

Just as 'void*' can be used to store the address of any object, 'void (*)()'
can store the address of any function pointer.
typedef void (*voidF)();
You can safely cast any function pointer to voidF and back.
2. What is the rational behind the GNU compiler message ( presuming the
compiler is correctly interpreting the standard).

Does the reinterpret_cast generate a warning or an error?
I'm not sure it should be an error, but it sure is a valid warning:
it is formally not portable to convert a function pointer to void*
and back (even though current platforms typically use a common
address space and register set for both data and code).


I hope this helps,
Ivan
 
I

Ioannis Vranos

Dave said:
Hi,

I'm trying to port a piece of code from Windows to Linux, the following
segment illustrates the coding problemI have: Under Linux, the
reinterpret_cast line
doesn't compile, the compiler says ISO C++ doesn allow a cast from
pointer-to-object
to pointer-to-function.


It doesn't compile under Windows with gcc either:

C:\c>g++ temp.cpp -o temp.exe
temp.cpp: In function `int main(int, char**)':
temp.cpp:13: error: invalid conversion from `int (*)()' to `void*'
temp.cpp:15: error: ISO C++ forbids casting between pointer-to-function and
pointer-to-object
temp.cpp:21:2: warning: no newline at end of file

C:\c>


However, I can use the plain-old-C-style cast and
the code compiles and works. I guess I have two questions:-

1. What is the sanctified way to write this type of code.
2. What is the rational behind the GNU compiler message ( presuming the
compiler is correctly interpreting the standard).

Thanks,

dave.

#include <stdio.h>

static int foo()
{
printf("hello\n");
return 0;
}

typedef int fnc_t();

int main(int argc, char* argv[])
{
void* fv = (fnc_t*)foo;

fnc_t* fnc = reinterpret_cast<fnc_t*>(fv); // illegal under GNU/linux

fnc();


return 0;
}



Others have provided explanations for the rest. The above would be
better if it was:


#include <iostream>

namespace
{
int foo()
{
std::cout<<"hello\n";

return 0;
}
}

typedef int fnc_t();


int main()
{

fnc_t *fnc = foo;

fnc();


return 0;
}
 
J

Jack Klein

Hi,

I'm trying to port a piece of code from Windows to Linux, the following
segment illustrates the coding problemI have: Under Linux, the
reinterpret_cast line
doesn't compile, the compiler says ISO C++ doesn allow a cast from
pointer-to-object
to pointer-to-function. However, I can use the plain-old-C-style cast and
the code compiles and works. I guess I have two questions:-

1. What is the sanctified way to write this type of code.

There isn't any. There is absolutely no defined conversion between a
pointer to any type of object and a pointer to any type of function.
Not in either C or C++.

And in fact there are implementations where such conversions are
literally impossible, as pointers to functions are wider than pointers
to any type of object. Bits are truncated and there is no way to get
them back.
2. What is the rational behind the GNU compiler message ( presuming the
compiler is correctly interpreting the standard).

The rational is that in C++, as inherited from C, there are objects
and there are functions. They are apples and oranges, they do not
mix. In either language, conversion of a pointer to function to a
pointer to object, in either direction, with or without a cast, is
completely undefined.

The real problem is sloppy interfaces, both in Windows and *nix, where
they use a pointer to void to hold pointers to functions. This is not
and never has been defined behavior. A union of two pointers could
have been used with no runtime overhead in either execution time or
space on implementations where the two types are the same size, but
it's probably too late now.
Thanks,

dave.

#include <stdio.h>

static int foo()
{
printf("hello\n");
return 0;
}

typedef int fnc_t();

int main(int argc, char* argv[])
{
void* fv = (fnc_t*)foo;

fnc_t* fnc = reinterpret_cast<fnc_t*>(fv); // illegal under GNU/linux

Actually, it's illegal under any compiler. But since it's undefined
behavior, no diagnostic is required.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,201
Messages
2,571,049
Members
47,654
Latest member
LannySinge

Latest Threads

Top