Valid Function Pointer Casting

M

Michael B Allen

I need a macro to compute an offset of an object relative to a base
address. The problem is the object can sometimes be a function pointer
with a base address of 0 but I don't know in advance that the object is
a function. Can it be done?

#define BREF(b,p) ((size_t)((p) ? (char *)(p) - (char *)(b) : 0))

The following code demonstrates that strict c89 doesn't accept casting
a pointer to a function to a pointer to char which makes my above code
invalid.

typedef int (*fn)(void);

void
test(fn f)
{
char *g = (char *)f;
}
int
main(void)
{
test(main);
return 0;
}

cc -std1 q.c
cc: Info: q.c, line 6: In the initializer for g, "f" of type "pointer
to function () returning void", is being converted to "pointer to char".
Such a cast is not permitted by the standard. (nonstandcast)
char *g = (char *)f;
--------------------------^
 
A

Alex Fraser

Michael B Allen said:
I need a macro to compute an offset of an object relative to a base
address. The problem is the object can sometimes be a function pointer
with a base address of 0 but I don't know in advance that the object is
a function. Can it be done?

Not portably.
#define BREF(b,p) ((size_t)((p) ? (char *)(p) - (char *)(b) : 0))

The following code demonstrates that strict c89 doesn't accept casting
a pointer to a function to a pointer to char which makes my above code
invalid.

That's correct. Consider architectures where code and data are in seperate
memory areas (eg many microcontrollers): such a conversion is nonsense.
(Usually, if the cast isn't nonsense, it will do what you expect.)

That may not be the only problem: when subtracting pointers, the result is
only defined by the standard if the pointers point to elements of the same
array or one past the last element of the array. (But, similarly, the result
is often what you expect even if this requirement isn't met.)

Alex
 
J

Jack Klein

I need a macro to compute an offset of an object relative to a base
address. The problem is the object can sometimes be a function pointer
with a base address of 0 but I don't know in advance that the object is
a function. Can it be done?

There is a flaw in your design or your reasoning. There can be no
object that is relative to a function.
#define BREF(b,p) ((size_t)((p) ? (char *)(p) - (char *)(b) : 0))

The following code demonstrates that strict c89 doesn't accept casting
a pointer to a function to a pointer to char which makes my above code
invalid.

No version of the C standard has ever defined a conversion between any
type of pointer to object and any type of pointer to function. They
are not convertible, just as you can't convert a banana to a
watermelon.

This is despite the fact that several operating system interfaces
(POSIX, Windows) define exactly that.
typedef int (*fn)(void);

void
test(fn f)
{
char *g = (char *)f;
}
int
main(void)
{
test(main);
return 0;
}

cc -std1 q.c
cc: Info: q.c, line 6: In the initializer for g, "f" of type "pointer
to function () returning void", is being converted to "pointer to char".
Such a cast is not permitted by the standard. (nonstandcast)
char *g = (char *)f;
--------------------------^

You have two choices. The first is to ignore or disable the warning,
which will work on some platforms but not all, for in some cases the
pointers might literally have different sizes. The second is to
reconsider your design and find a better way to implement it. If you
tell us the underlying problem you are trying to solve, we might be
able to help you with that.
 
E

Ed Vogel

Michael B Allen said:
cc: Info: q.c, line 6: In the initializer for g, "f" of type "pointer
to function () returning void", is being converted to "pointer to char".
Such a cast is not permitted by the standard. (nonstandcast)
char *g = (char *)f;
--------------------------^

Note that the diagnostic output by the compiler is only
an informational. There is still an object produced, and
your program will run as expected. If you wish you can
disable this diagnostic. One way to to do this is
to add -msg_disable nonstandcast to the command line

Ed Vogel
DEC/Compaq/HP C/C++ Engineering
 

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

Forum statistics

Threads
473,989
Messages
2,570,207
Members
46,783
Latest member
RickeyDort

Latest Threads

Top