From the C17 standard draft (6.3.2.1 ¶4; footnote removed):
A function designator is an expression that has function type. Except when it is the operand of the
sizeof
operator, or the unary&
operator, a function designator with type "function returning type" is converted to an expression that has type "pointer to function returning type".
- According to the footnote which I omitted from the quote above,
sizeof f
(for a function designatorf
) is non-standards-conformant. - Note that the C11 standard additionally mentions the
_Alignof
operator. - Note that the C2x draft additionally mentions the
typeof
operator.
As a result (here: f
is a function designator; fp
is a function pointer):
- One can indicate the address of a function as
&f
(explicit) orf
(short). - One can make a function call as:
(&f)(args)
orf(args)
fp(args)
or(*fp)(args)
Here,
- left-hand
(&f)(args)
/fp(args)
is consistent with function calls technically operating on function pointers, and - right-hand
f(args)
/(*fp)(args)
is consistent with the naive assumption that function calls operate on functions (instead of pointers to functions).
Stylistically,
- this answer labels
&f
as "always redundant", (&f)(args)
is virtually unused in practice, andf
/f(args)
/fp(args)
is the shortest style.
(For completeness' sake (and in case anyone else wants a nice summary), here is a longer list of expressions that are equivalent to f
: (&f)
, (*******f)
, (***&***f)
, (***&**&f)
, (&**&***f)
, (&**&**&f)
.)
But:
When is it ever necessary or meaningful to
- write
&f
(wheref
is a function designator) or - write
*fp
(wherefp
is a function pointer)?
(By "meaningful", I mean that the behavior of the program is altered.)
- The only case I am aware of is
sizeof &f
. (sizeof f
is illegal, even though the GCC dialect of C permits it (at least as of version 12.2.0), but with different semantics: It seemingly returns1
in all(?) cases. Why?)- I don't understand this. Letting
f
auto-convert to&f
would let us simplify the standard's phrasing and givesizeof f
useful semantics too. (Perhaps this restriction exists to maintain parallelism withtypeof
, which has been floating around as a compiler extension for a while.)
- I don't understand this. Letting
- I am not sure what happened with
_Alignof
. - If
typeof
is officially added to C with the next standard, a distinction betweentypeof &f
/typeof fp
andtypeof f
/typeof *fp
would be obviously meaningful.