givi
givi

Reputation: 1903

C function pointers invocation syntax

Suppose there is a function pointer:

void func(float a1, float a2) {

}

void (*fptr)(float, float) = &func;

Is there any difference between these two lines (both compile and work on my compiler)?

(*fptr)(1,2);
fptr(1,2);

I suppose that the second version is just a shortcut of the first one, but want to ensure myself. And more important is it a standard behavior?

Upvotes: 4

Views: 619

Answers (2)

Keith Thompson
Keith Thompson

Reputation: 263207

They do the same thing.

The prefix of a function call is always an expression of pointer-to-function type.

An expression of pointer type, such as the name of a declared function. is implicitly converted to a pointer to that function, unless it's the operand of a unary "&" (which yields the function's address anyway) or of sizeof (which is illegal rather than yielding the size of a pointer).

The consequence of this rule is that all of these:

&func
func
*func
**func

are equivalent. They all evaluate to the address of the function, and they can all (if suitably parenthesized) be used as the prefix of a function call.

Upvotes: 8

Michael Burr
Michael Burr

Reputation: 340188

Yes, it is standard behavior and will work in all C compilers.

Function calls are actually always made through a pointer to function:

6.5.22 "Function calls":

The expression that denotes the called function (footnote 77) shall have type pointer to function returning void or returning an object type other than an array type

As footnote 77 indicates, a 'normal' function identifier is actually converted to a pointer-to-function when a function call is expression is used:

Footnote 77:

Most often, this is the result of converting an identifier that is a function designator.

Interestingly, dereferencing a function pointer (or a function designator converted to a function pointer) yields a function designator for the function, which will be converted back to a function pointer for the function call expression. So you can dereference the function pointer (or a normal function name), but don't have to.

6.5.3.2/4 "Address and indirection operators":

The unary * operator denotes indirection. If the operand points to a function, the result is a function designator

So as far as the standard is concerned, for your examples:

(*fptr)(1,2);
fptr(1,2);

The second isn't really a shorthand - it's what the compiler expects. Actually, the first example is really just a more verbose way of saying the same thing as the second. But some people might prefer the first form as it makes it more clear that a pointer is being used. There should be absolutely no difference in the generated code.

Another consequence of the standard's wording is that you can just as well dereference a normal function name:

func(1,2);
(*func)(1,2);  // equivalent to the above

Not that there's really any defensible point to doing that that I can think of.

Upvotes: 6

Related Questions