[comp.lang.c] void * = pointer to a function

pm0@reef.cis.ufl.edu (Patrick Martin) (03/10/91)

I am trying to get a grip on pointers to functions.  Here is
the code I am having a problem with (Simplified to the bare
essense of the problem)

#include <stdio.h>

int Output_Num(int a)
{
   printf("The Number is: %d",a);
}

main()
{
   void *Function = (int (*) (int)) Output_Num;
   (*Function) (5);
}

I want to declare an object which is actually a pointer to a
function so I may call it through the other object instead.

I did read K&R's section on pointers to functions but still
could not get this code to work.

One more question, what would the code look like if the function
were:

void Hello_World() {printf("Hello world")}

main()
{
   void *F = (void (*) (void)) Hello_World;  /* can I use () in
					        place of (void)? */
   (*F) ();  /* or should the call be (*F) (void) */


Thanks,
Pat Martin

torek@elf.ee.lbl.gov (Chris Torek) (03/11/91)

In article <27385@uflorida.cis.ufl.EDU> pm0@reef.cis.ufl.edu
(Patrick Martin) writes:
>I am trying to get a grip on pointers to functions.  Here is
>the code I am having a problem with (Simplified to the bare
>essense of the problem)

There are several conceptual errors here.

[note, I have compressed the following vertically]
>#include <stdio.h>
>int Output_Num(int a) { printf("The Number is: %d",a); }
>main() {
>   void *Function = (int (*) (int)) Output_Num;
>   (*Function) (5);
>}

And:

>[if it were]
>void Hello_World() {printf("Hello world")}

[would it be]

>   void *F = (void (*) (void)) Hello_World;  /* can I use () in
>					        place of (void)? */
>   (*F) ();  /* or should the call be (*F) (void) */

The first error: to have a pointer to a function, you must declare an
object of type `pointer to function of ... returning T', where T is any
legal function-return type (i.e., a type that is not itself an array or
function type) and where `of ...' represent the number and types of
each argument.

In this case, you want:

	cdecl> declare Function as pointer to function (int) returning int
	int (*Function)(int)

and:

	cdecl> declare F as pointer to function (void) returning void
	void (*F)(void);

The second error: a cast is necessary only when you have a mismatch
between a value type and an object to which the value is to be assigned.
Even then the cast may be deleted under most circumstances:

	int i;
	i = (int) 3.141592653589793238462643383279502884;

The cast is unnecessary since conversion of floating point values to
integer values is `directly allowed'.

If you declare your function pointer correctly, you will not need a cast.

The third error (or not): a call through a pointer to a function is
pretty much identical to a `regular' call.  You would not write:

	main() { Hello_World(void); }	/* wrong */

in the second example, so you should not expect to write

	main() {
		void (*f)(void) = Hello_World;
		(*f)(void);		/* wrong */
		return 0;
	}

and instead you want just:

	main() {
		void (*f)(void) = Hello_World;
		(*f)();			/* right */
		return 0;
	}

ANSI C explicitly allows you to omit the `*' before the pointer:

	main() {
		void (*f)(void) = Hello_World;
		f();			/* right */
		return 0;
	}

Note that you *must* declare all functions before attempting to take
their addresses.  (Declaration via definition, as in the original two
examples, is fine.)  This is the same as having to declare variables
before taking their addresses; probably the only reason some people
find it confusing is that C allows you to *call* functions without
first declaring them.  (Some people, and some compilers, believe the
latter is a mistake and warn against it.)
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab EE div (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

ECSGRT@lure.latrobe.edu.au (GEOFFREY TOBIN, ELECTRONIC ENGINEERING) (03/13/91)

In article <27385@uflorida.cis.ufl.EDU>, pm0@reef.cis.ufl.edu (Patrick Martin) writes:
 
> main()
> {
>    void *Function = (int (*) (int)) Output_Num;
          ^^^^^^^^^
          Mistake here.

>    (*Function) (5);
       --------
       VAX C 3.1 compiler complains here.
> }

The mistake was to use an ordinary void pointer in place of a function
pointer.  The compiler isn't impressed that you called it "Function",
either, even though this fools the human eye.

I declared Function as follows, and VAX/VMS C 3.1 was content.

main()
{
   void (*Function)() = (int (*) (int)) Output_Num;
   (*Function) (5);
}

The cast is also unnecessary (at least in VAX/VMS C 3.1).  The compiler
was also completely satisfied with:

void (*Function)() = Output_Num;

I think that in the ANSI standard for C, void pointers (and their
elaborations, such as void function pointers) may be assigned from other
pointers.  The exact rules I forget.  For portability of your programs,
I recommend that you find out.  (Talk about "Do as I say..."! :-)

> What would the code look like if the function were:
> 
> void Hello_World() {printf("Hello world")}
> 
> main()
> {
>    void *F = (void (*) (void)) Hello_World;  /* () for (void) ? */
           ^
           You did it again.  A void pointer is not a function pointer.
A void pointer is a variable that contains an address.  No other
information is associated with it, because the "void" type has no
constants, so no values, so no variables.  ("void" is like the empty
set in math.)  Consequently, it is illegal to dereference F as "*F",
as F is here (as C understands it) an address without any contents.
All you can do with such an F is to print it using "%p", subtract
and add integers to it, assign it, cast it, and compare it with
other pointers.  (Any other possibilities, people?)

Instead, you may write (in VAX/VMS C 3.1, for example) :

	void (* F) () = Hello_World;

Now, regarding your next question:
In a K&R first-edition C compiler, "void" is never necessary; indeed,
in some older compilers, "void" may be rejected as unknown.  In ANSI C,
the inclusion of "void" is clearer, and in certain circumstances it is
required.

>    (*F) ();  /* or should the call be (*F) (void) ? */

The former is correct.  We don't write "g(void)" for the call of a
function with no arguments, for the same reason that we don't write
"max (int a, int b);" or "int max (int a, int b);" for the call of
a function of two arguments:  "void" is a type, not an argument list.

If my explanation is unclear, please express your doubts.
For other readers (or yourself later), if my explanations are wrong,
please flame away!

Yours sincerely,
Geoffrey Tobin