2

EDIT: It's been pointed out that this question is sort of confusing. The short version is: "why have a separate pointer variable (eg, fnPtr) which points to a function (eg, fn) when the function name fn itself, without arguments, is already a pointer? /EDIT

I'm trying to understand something and could use feedback from the community regarding function pointers. (And while this might look like a duplicate of other questions on the topic, it really isn't, as least not that I could find.)

I understand the concept of a pointer to a function being used as an argument to another function as a callback...ie telling fn1 to use fn2 in some way during the execution of fn1. What I don't understand is the complex syntax being used in all of it. If fn is a defined function, then calling fn(...) will execute the function with the supplied arguments. However, fn used on its own is the address of the function, that is, a pointer to the function. Furthermore, fn, &fn, and *fn are all the same thing. Why have dedicated function pointers, and why create new variable (ie, fnPtr) which point to a function...the function name is already its own pointer!

This code compiles and works the same every time.

#include <stdlib.h>
#include <stdio.h>

int fn(int var) { //fn is a function which takes an int and returns an int
    return var;
}

int (*fnPtrAmp)(int) = &fn;
int (*fnPtr)(int) = fn;

int needsCallback(int variable, int callback(int)) {
    return callback(variable);
}

int needsCallbackPointer(int variable, int (*callbackPtr)(int)) {
    return callbackPtr(variable);
}

int needsCallbackPointerWithDereference(int variable, int (*callbackPtr)(int)) {
    return (*callbackPtr)(variable);
}

int main() {
    printf("%d\n", fn(4));
    printf("%d\n", fnPtr(4));
    printf("%d\n", (*fnPtr)(4));
    printf("%d\n", needsCallback(4,fn));
    printf("%d\n", needsCallbackPointer(4,fnPtr));
    printf("%d\n", needsCallbackPointer(4,fn));
    printf("%d\n", needsCallbackPointer(4,&fn));
    printf("%d\n", needsCallbackPointerWithDereference(4,fnPtr));
    printf("%d\n", needsCallbackPointerWithDereference(4,fn));
    printf("%d\n", needsCallbackPointerWithDereference(4,&fn));
    return 0;
}

The simplest syntax is that of needsCallback but that isn't done anywhere, it's always needsCallbackPointer and fnPtrAmp. Why? With needsCallback you don't even have to define an extra variable to be the function pointer. As I said before, the function name is its own pointer!

Could use some feedback...thanks.

austin1howard
  • 4,815
  • 3
  • 20
  • 23
  • 2
    You ask about five different questions and answer some of them in your own post. What is your actual question? – cdhowie Oct 09 '14 at 22:12
  • 1
    There seems to be 2 questions: (1) why have function pointers?, and (2) why is `&` allowed on a function name and `*` allowed on a function pointer. You answer (1) in your own post with the callback example, and (2) is answered [here](http://stackoverflow.com/questions/2795575/how-does-dereferencing-of-a-function-pointer-happen) – M.M Oct 09 '14 at 22:21
  • The question isn't why have function pointers per se, it's why have a separate pointer variable (eg, `fnPtr`) which points to a function (eg, `fn`) when the function name `fn` itself, without arguments, is already a pointer? – austin1howard Oct 09 '14 at 22:28
  • No, you dont need variables `per se`, you can use expressions. Remember, the basic syntax element in C is an expression. Expressions have types, too! – wildplasser Oct 09 '14 at 22:29
  • 3
    You only need to create a separate function pointer *variable* if you have several functions to choose from, but the choice isn't made until runtime. Otherwise, if you *know* you're always going to be passing a pointer to the same specific function, use that specific function name. – John Bode Oct 09 '14 at 22:31
  • You need a function pointer variable because you can assign to it (including implicit assignment, if it's a function argument). A function name is a constant. – alexis Oct 09 '14 at 22:44
  • A function name (you might call these symbols, too, as the linker and compilers do occasionally) is a name is a name and is something like `myVariable`. A constant is a constant and is something like `5`. – dom0 Oct 09 '14 at 22:45
  • Sorry for getting your ontology in a bunch. – alexis Oct 09 '14 at 22:46
  • 1
    @austin1howard you wrote this code so I am confused as to why you ask "why have this code". It's like saying "what is the point of `int x = 5;` when I could just write `5` later" – M.M Oct 09 '14 at 22:48

2 Answers2

4
  1. Function pointer variables are useful when control flow that follows later on modifies the function pointer (e.g. chooses a different callback).

    Function pointer variables are also useful when dealing with runtime binding, where you do not know the function at compile time but rather assign a function pointer at runtime, for example by using dlsym. This is often used in the context of extensible APIs (OpenGL is a popular user of this scheme, for example) and plugins.

  2. "The simplest syntax is that of needsCallback but that isn't done anywhere, it's always needsCallbackPointer and fnPtrAmp. Why?": to have the declaration in the parameter of a function consistent with how an variable or typedef declaration would look like.

  3. Another question you ask is why *fnPtr works, and why the parentheses.

    Well, the parentheses are required, because the function call operator () has a higher precedence than the dereference operator *, thus the function is first called and then the return value is derefenced. (*fnPtr)() works around that.

  4. someFunction and &someFunction are equivalent due to functions not being first-class citizens in C (functions are not normal objects that can be manipulated, like an int, for example), but function pointers are. Thus a function name is always and inherently converted to a function pointer to the function referenced by that name. Note that you can apply & multiple times to a function pointer, yielding a pointer to function pointer, pointer to pointer to function pointer etc.. Thus it does not behave in a sense like * does, which you can use as often as you want on a function pointer.

  5. *fnPtr works, because the * operator used on a function pointer essentially yields the exact same pointer. Same rationale as 4) - there are no function objects in the language. Thus you cannot get a function name back from a function pointer, not possible.

I don't know why the these operators were defined for function names and pointers, respectively. Maybe historic reasons? For consistency with other pointer types?

I suspect that the operator-less syntax was introduced later on to save typing, since you can't use a function name neither in an rvalue nor lvalue context meaningfully. Since theres nothing one can do with a function pointer either (except passing it around. You can of course change it, like fnPtr++; but where does that get you?), it makes quite a lot of sense to add the implicit conversion making fnPtr() possible, to save typing yet again.

(The last two paragraphs are pure speculation on my part.)

Community
  • 1
  • 1
dom0
  • 7,356
  • 3
  • 28
  • 50
  • Thanks dom0, that makes more sense. I understand about the dereferencing and address operator (* and &); that's basically why I was asking the question. If there's no difference between **fn, *fn, fn, &fn, ~~&&fn~~, then why even use them at all. – austin1howard Oct 09 '14 at 22:38
  • I edited my answer, there *is* a difference between `&fn` and `&&fn`. – dom0 Oct 09 '14 at 22:41
  • Yeah sorry, I get that...was typing without thinking. – austin1howard Oct 09 '14 at 22:42
  • 1
    I'm not sure. Maybe historic reasons or for consistency with other pointer types. It might also aid reading source code, but that's questionable at best. – dom0 Oct 09 '14 at 22:44
  • 1
    Oh, you hid a fifth question after that bunch of code. Added answer to that one as well (number two in my answer). – dom0 Oct 09 '14 at 23:08
  • I guess it makes sense to have it look consistent with variable pointers. It just seemed interesting to me how what's taught is the right way is not the simplest in terms of number of characters. Thanks, marking solved. – austin1howard Oct 10 '14 at 13:05
0

The purpose of function pointer syntax in C is two fold

1) To confuse programmers

2) To allow the compiler to syntax check that the callers of function pointers use the same arguments as the functions themselves.

The second is what leads to most of the confusion, since if you have a function pointer that returns a pointer then the binding of the derefence (*) doesn't work as expected, and you have to add the extra parentheses.

-A

Andrew C
  • 13,845
  • 6
  • 50
  • 57