www.digitalmars.com         C & C++   DMDScript  

D - Function pointers

reply "Ben Cohen" <bc skygate.co.uk> writes:
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.
Oct 16 2001
next sibling parent reply "Walter" <walter digitalmars.com> writes:
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.

Oct 16 2001
next sibling parent Axel Kittenberger <axel dtone.org> writes:
 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
Oct 16 2001
prev sibling next sibling parent "Ben Cohen" <bc skygate.co.uk> writes:
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.
Oct 17 2001
prev sibling parent reply "Jeffrey Drake" <jpt.d home.com> writes:
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


 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


 statements above.

 E.g.:

 /* Declare a variable to which you assign a function taking no


 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.


 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.


Oct 19 2001
parent Axel Kittenberger <axel dtone.org> writes:
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?
Oct 20 2001
prev sibling parent "Sean L. Palmer" <spalmer iname.com> writes:
 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
Oct 23 2001