Thread overview
Function pointers
Oct 16, 2001
Ben Cohen
Oct 16, 2001
Walter
Oct 17, 2001
Axel Kittenberger
Oct 17, 2001
Ben Cohen
Oct 19, 2001
Jeffrey Drake
Oct 20, 2001
Axel Kittenberger
Oct 23, 2001
Sean L. Palmer
October 16, 2001
In C, you can create a variable which points to a function:

int (*my_func)();

I can then assign the address of a function with the same prototype to this variable:

int a_func() { ... }

/* These are equivalent */
my_func = &a_func;
my_func = a_func;

And then I can call my_func as if calling a_func; the following are equivalent:

  int d = a_func();
  d = my_func();
  d = (*my_func)();

I find the definition of my_func, and the equivalence of my_func with *my_func and a_func with &a_func a bit confusing.


I note that in D, since you use import and forward declarations you are no longer allowed to declare function prototypes.  (This is stated in the spec.)


As a result, you have "freed" that syntax and could use it to simplify the statements above.

E.g.:

/* Declare a variable to which you assign a function taking no parameters
and returning int. */
int my_func();

int a_func() { ... }
my_func = a_func;

/* These are equivalent: */
int d = a_func();
      d = my_func();

This simplifies things and no pointers are now explicitly involved; I think the pointer above is a bit artificial anyway -- if it wasn't for prototypes, I would hope that C would have used this syntax anyway. (This is similar in spirit to replacing -> with . in structs.)

You could even go further and make the variable definition like this:

int() my_func;

This has the advantage (over "int my_func();") of not clashing with
existing C syntax, being easier to understand and being consistent with
array definitions.
October 16, 2001
You bring up an interesting point. I never liked the implictness in C regarding function pointers, I was thinking of doing away with it by requiring you to use & when taking the address of a function. -Walter

"Ben Cohen" <bc@skygate.co.uk> wrote in message news:9qhm2p$2b4t$1@digitaldaemon.com...
> In C, you can create a variable which points to a function:
>
> int (*my_func)();
>
> I can then assign the address of a function with the same prototype to this variable:
>
> int a_func() { ... }
>
> /* These are equivalent */
> my_func = &a_func;
> my_func = a_func;
>
> And then I can call my_func as if calling a_func; the following are equivalent:
>
>   int d = a_func();
>   d = my_func();
>   d = (*my_func)();
>
> I find the definition of my_func, and the equivalence of my_func with *my_func and a_func with &a_func a bit confusing.
>
>
> I note that in D, since you use import and forward declarations you are no longer allowed to declare function prototypes.  (This is stated in the spec.)
>
>
> As a result, you have "freed" that syntax and could use it to simplify the statements above.
>
> E.g.:
>
> /* Declare a variable to which you assign a function taking no parameters
> and returning int. */
> int my_func();
>
> int a_func() { ... }
> my_func = a_func;
>
> /* These are equivalent: */
> int d = a_func();
>       d = my_func();
>
> This simplifies things and no pointers are now explicitly involved; I think the pointer above is a bit artificial anyway -- if it wasn't for prototypes, I would hope that C would have used this syntax anyway. (This is similar in spirit to replacing -> with . in structs.)
>
> You could even go further and make the variable definition like this:
>
> int() my_func;
>
> This has the advantage (over "int my_func();") of not clashing with
> existing C syntax, being easier to understand and being consistent with
> array definitions.


October 17, 2001
> You bring up an interesting point. I never liked the implictness in C regarding function pointers, I was thinking of doing away with it by requiring you to use & when taking the address of a function. -Walter

I took the '^' operator, removed it's xor meaning. (xor is instead the binary '~') and assigned it to be the function pointer operator. Get the address from a function you need the ^ operator, assign the value of a function pointer, ^ operator, call the function it is pointing at, no ^.

Btw, I also changed the meaning of the '&' operator, it's no longer 100%ly address-of, but means just means "reference-of". There are slight differences in some functions, the reference of a reference is again just the reference.

int cork(int &i) # gets i by reference...
{
   if (i > 0) {
       i--;
      cork(&i);   # tell the compiler and reader to be aware that the
                 # of i can be changed after the call. (context free reading)
   }
}

- Axel
-- 
|D) http://www.dtone.org
October 17, 2001
In article <9qi29e$2i0v$1@digitaldaemon.com>, "Walter" <walter@digitalmars.com> wrote:

> You bring up an interesting point. I never liked the implictness in C regarding function pointers, I was thinking of doing away with it by requiring you to use & when taking the address of a function. -Walter

Hmm...

Using & has the advantage that you have to explicitly do it:

  my_func = &a_func;

Thus you can't accidentally call a_func without the brackets, giving a null statement:

  my_func;
  my_var = my_func;

instead of:

  my_func();
  my_var = my_func();

However, this should in any case be caught by D (according to the spec) if you do this as a single statement, and if you try to use its value then there will be a type error; so I don't think this will be a problem.


I prefer not to use & since it brings in pointer notation where it could
be avoided; also, you don't _have_ to use it in C.  However, if you can
call my_func() in the same way as a_func(), rather than having to call
(*my_func)(), then this suggests to me that they are of the same type and
should be assigned without using &.


The bit I think is more confusing is having to use * in the C variable type defintion when you don't really mean it.  (You could mean it if you were making an array of pointers to functions.  But then in C you would have to use **.  You still have to add one more * than I think is necessary.  It is this which creates all the other confusion in this matter.)

Functions should certainly behave more predictably:  this program works in gcc (I don't know whether it is valid standard C), with all functions returning the same value:

int test() {  return 45; }

int (*test_p)() = test;  /* or &test */ int (**test_pp)() = &test_p;

main() {
  printf("%d\n", test());
  printf("%d\n", (***test)());
  printf("%d\n", test_p());
  printf("%d\n", (*test_p)());
  printf("%d\n", (**test_p)());
  printf("%d\n", (*test_pp)());
  printf("%d\n", (**test_pp)());
  printf("%d\n", (***test_pp)());
  printf("%d\n", (****test_pp)());
}

In other words, you can add as many ********* as you like in front of function calls without changing the effect.  This is silly and should probably be an error.  The one thing that makes sense here is that test_pp is a pointer to a function, so you can't call "test_pp()" and have to dereference it first.
October 19, 2001
How about a delegate?

It basically is a prototype of a function that has delegate (keyword) in front of it. It is C#'s way of making function pointers and i like it a lot.

Regards,
jptd

"Walter" <walter@digitalmars.com> wrote in message news:9qi29e$2i0v$1@digitaldaemon.com...
> You bring up an interesting point. I never liked the implictness in C regarding function pointers, I was thinking of doing away with it by requiring you to use & when taking the address of a function. -Walter
>
> "Ben Cohen" <bc@skygate.co.uk> wrote in message news:9qhm2p$2b4t$1@digitaldaemon.com...
> > In C, you can create a variable which points to a function:
> >
> > int (*my_func)();
> >
> > I can then assign the address of a function with the same prototype to this variable:
> >
> > int a_func() { ... }
> >
> > /* These are equivalent */
> > my_func = &a_func;
> > my_func = a_func;
> >
> > And then I can call my_func as if calling a_func; the following are equivalent:
> >
> >   int d = a_func();
> >   d = my_func();
> >   d = (*my_func)();
> >
> > I find the definition of my_func, and the equivalence of my_func with *my_func and a_func with &a_func a bit confusing.
> >
> >
> > I note that in D, since you use import and forward declarations you are
no
> > longer allowed to declare function prototypes.  (This is stated in the
> > spec.)
> >
> >
> > As a result, you have "freed" that syntax and could use it to simplify
the
> > statements above.
> >
> > E.g.:
> >
> > /* Declare a variable to which you assign a function taking no
parameters
> > and returning int. */
> > int my_func();
> >
> > int a_func() { ... }
> > my_func = a_func;
> >
> > /* These are equivalent: */
> > int d = a_func();
> >       d = my_func();
> >
> > This simplifies things and no pointers are now explicitly involved; I think the pointer above is a bit artificial anyway -- if it wasn't for prototypes, I would hope that C would have used this syntax anyway.
(This
> > is similar in spirit to replacing -> with . in structs.)
> >
> > You could even go further and make the variable definition like this:
> >
> > int() my_func;
> >
> > This has the advantage (over "int my_func();") of not clashing with
> > existing C syntax, being easier to understand and being consistent with
> > array definitions.
>
>


October 20, 2001
Jeffrey Drake wrote:

> How about a delegate?
> 
> It basically is a prototype of a function that has delegate (keyword) in front of it. It is C#'s way of making function pointers and i like it a lot.

Can you paste an example maybe?
October 23, 2001
> This simplifies things and no pointers are now explicitly involved; I think the pointer above is a bit artificial anyway -- if it wasn't for prototypes, I would hope that C would have used this syntax anyway. (This is similar in spirit to replacing -> with . in structs.)
>
> You could even go further and make the variable definition like this:
>
> int() my_func;
>
> This has the advantage (over "int my_func();") of not clashing with
> existing C syntax, being easier to understand and being consistent with
> array definitions.

I like this form.  Consistent with the rest of the typespec system.  When dealing with a variable that holds function type, of *course* it's a pointer-to-function, it's certainly not going to go around copying the machine-code for the function around at runtime.  So the pointer part is unnecessary with function pointers and can be implicit.  Still different enough from a normal function declaration that the parser won't have trouble with it.

Sean